refactor wall filter

This commit is contained in:
温少
2012-03-16 13:00:10 +08:00
13 changed files with 1621 additions and 1270 deletions
@@ -17,6 +17,8 @@ public interface WallVisitor extends SQLASTVisitor {
Set<String> getPermitTables();
boolean containsPermitTable(String name);
boolean containsPermitObjects(String name);
Set<String> getPermitNames();
@@ -14,6 +14,7 @@ import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
@@ -33,6 +34,7 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
private final Set<String> permitTables = new HashSet<String>();
private final Set<String> permitSchemas = new HashSet<String>();
private final Set<String> permiNames = new HashSet<String>();
private final Set<String> permitObjects = new HashSet<String>();
private final List<Violation> violations;
@@ -40,22 +42,6 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
this(new ArrayList<Violation>());
}
public Set<String> getPermitNames() {
return permiNames;
}
public Set<String> getPermitFunctions() {
return permitFunctions;
}
public Set<String> getPermitTables() {
return permitTables;
}
public Set<String> getPermitSchemas() {
return permitSchemas;
}
public MySqlWallVisitor(List<Violation> violations){
this.violations = violations;
@@ -76,9 +62,39 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
permitTables.add("outfile");
}
public Set<String> getPermitNames() {
return permiNames;
}
public Set<String> getPermitFunctions() {
return permitFunctions;
}
public Set<String> getPermitTables() {
return permitTables;
}
public Set<String> getPermitSchemas() {
return permitSchemas;
}
public boolean containsPermitObjects(String name) {
name = name.toLowerCase();
return permitObjects.contains(name);
}
public Set<String> getPermitObjects() {
return permitObjects;
}
public List<Violation> getViolations() {
return violations;
}
public boolean visit(SQLPropertyExpr x) {
WallVisitorUtils.check(this, x);
return true;
}
public boolean visit(SQLBinaryOpExpr x) {
WallVisitorUtils.check(this, x);
@@ -1,12 +1,6 @@
package com.alibaba.druid.filter.wall.spi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -14,8 +8,6 @@ import java.util.Set;
import com.alibaba.druid.filter.wall.IllegalSQLObjectViolation;
import com.alibaba.druid.filter.wall.Violation;
import com.alibaba.druid.filter.wall.WallVisitor;
import com.alibaba.druid.logging.Log;
import com.alibaba.druid.logging.LogFactory;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObject;
@@ -23,6 +15,7 @@ import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
@@ -34,16 +27,14 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVIsitorAdapter;
import com.alibaba.druid.util.JdbcUtils;
public class OracleWallVisitor extends OracleASTVIsitorAdapter implements WallVisitor {
private final static Log LOG = LogFactory.getLog(OracleWallVisitor.class);
private final Set<String> permitFunctions = new HashSet<String>();
private final Set<String> permitTables = new HashSet<String>();
private final Set<String> permitSchemas = new HashSet<String>();
private final Set<String> permitNames = new HashSet<String>();
private final Set<String> permitObjects = new HashSet<String>();
private final List<Violation> violations;
@@ -54,48 +45,11 @@ public class OracleWallVisitor extends OracleASTVIsitorAdapter implements WallVi
public OracleWallVisitor(List<Violation> violations){
this.violations = violations;
addPermitFunction("sys_context");
addPermitFunction("userenv");
addPermitFunction("sys_guid");
addPermitFunction("sys_typeid");
addPermitName("uid");
addPermitName("user");
loadPermitTables();
}
private void loadPermitTables() {
try {
Enumeration<URL> e = Thread.currentThread().getContextClassLoader().getResources("META-INF/druid-filter-wall-permit-function.txt");
while (e.hasMoreElements()) {
URL url = e.nextElement();
InputStream in = null;
BufferedReader reader = null;
try {
in = url.openStream();
reader = new BufferedReader(new InputStreamReader(in));
for (;;) {
String line = reader.readLine();
if (line == null) {
break;
}
line = line.trim();
if (line.length() > 0) {
addPermitTable(line);
}
}
url.openStream();
} finally {
JdbcUtils.close(reader);
JdbcUtils.close(in);
}
}
} catch (IOException e) {
LOG.error("load oracle permit tables errror", e);
}
WallVisitorUtils.loadResource(this.permitNames, "META-INF/druid-filter-wall-permit-name.txt");
WallVisitorUtils.loadResource(this.permitSchemas, "META-INF/druid-filter-wall-permit-schema.txt");
WallVisitorUtils.loadResource(this.permitFunctions, "META-INF/druid-filter-wall-permit-function.txt");
WallVisitorUtils.loadResource(this.permitTables, "META-INF/druid-filter-wall-permit-table.txt");
WallVisitorUtils.loadResource(this.permitObjects, "META-INF/druid-filter-wall-permit-object.txt");
}
public void addPermitName(String name) {
@@ -113,6 +67,15 @@ public class OracleWallVisitor extends OracleASTVIsitorAdapter implements WallVi
permitTables.add(name);
}
public boolean containsPermitObjects(String name) {
name = name.toLowerCase();
return permitObjects.contains(name);
}
public Set<String> getPermitObjects() {
return permitObjects;
}
public Set<String> getPermitNames() {
return permitNames;
}
@@ -138,6 +101,11 @@ public class OracleWallVisitor extends OracleASTVIsitorAdapter implements WallVi
return true;
}
public boolean visit(SQLPropertyExpr x) {
WallVisitorUtils.check(this, x);
return true;
}
// executeQuery
public boolean visit(SQLBinaryOpExpr x) {
WallVisitorUtils.check(this, x);
@@ -189,6 +157,9 @@ public class OracleWallVisitor extends OracleASTVIsitorAdapter implements WallVi
@Override
public boolean containsPermitTable(String name) {
name = WallVisitorUtils.form(name);
if (name.startsWith("v$") || name.startsWith("v_$")) {
return true;
}
return permitTables.contains(name);
}
@@ -1,7 +1,17 @@
package com.alibaba.druid.filter.wall.spi;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Enumeration;
import java.util.Set;
import com.alibaba.druid.filter.wall.IllegalSQLObjectViolation;
import com.alibaba.druid.filter.wall.WallVisitor;
import com.alibaba.druid.logging.Log;
import com.alibaba.druid.logging.LogFactory;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
@@ -24,9 +34,22 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr;
import com.alibaba.druid.util.JdbcUtils;
public class WallVisitorUtils {
private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class);
public static void check(WallVisitor visitor, SQLPropertyExpr x) {
if (x.getOwner() instanceof SQLIdentifierExpr) {
String owner = x.getOwner().toString();
owner = WallVisitorUtils.form(owner);
if (visitor.containsPermitObjects(owner)) {
visitor.getViolations().add(new IllegalSQLObjectViolation(SQLUtils.toOracleString(x)));
}
}
}
public static void check(WallVisitor visitor, SQLBinaryOpExpr x) {
if (Boolean.TRUE == getValue(x)) {
visitor.getViolations().add(new IllegalSQLObjectViolation(SQLUtils.toSQLString(x)));
@@ -209,15 +232,15 @@ public class WallVisitorUtils {
return ((String) firstValue).length();
}
}
if ("if".equalsIgnoreCase(methodName) && x.getParameters().size() == 3) {
SQLExpr first = x.getParameters().get(0);
Object firstResult = getValue(first);
if (Boolean.TRUE == firstResult) {
return getValue(x.getParameters().get(1));
}
if (Boolean.FALSE == firstResult) {
getValue(x.getParameters().get(2));
}
@@ -290,7 +313,7 @@ public class WallVisitorUtils {
if (propExpr.getOwner() instanceof SQLIdentifierExpr) {
String ownerName = ((SQLIdentifierExpr) propExpr.getOwner()).getName();
ownerName = form(ownerName);
if (visitor.getPermitSchemas().contains(ownerName.toLowerCase())) {
@@ -307,7 +330,7 @@ public class WallVisitorUtils {
if (tableName != null) {
tableName = form(tableName);
if (visitor.getPermitTables().contains(tableName)) {
if (visitor.containsPermitTable(tableName)) {
visitor.getViolations().add(new IllegalSQLObjectViolation(visitor.toSQL(x)));
}
}
@@ -345,8 +368,41 @@ public class WallVisitorUtils {
if (name.startsWith("`") && name.endsWith("`")) {
name = name.substring(1, name.length() - 1);
}
name = name.toLowerCase();
return name;
}
public static void loadResource(Set<String> names, String resource) {
try {
Enumeration<URL> e = Thread.currentThread().getContextClassLoader().getResources(resource);
while (e.hasMoreElements()) {
URL url = e.nextElement();
InputStream in = null;
BufferedReader reader = null;
try {
in = url.openStream();
reader = new BufferedReader(new InputStreamReader(in));
for (;;) {
String line = reader.readLine();
if (line == null) {
break;
}
line = line.trim();
if (line.length() > 0) {
line = line.toLowerCase();
names.add(line);
}
}
url.openStream();
} finally {
JdbcUtils.close(reader);
JdbcUtils.close(in);
}
}
} catch (IOException e) {
LOG.error("load oracle permit tables errror", e);
}
}
}