improve wall filter

This commit is contained in:
wenshao
2013-04-09 19:08:14 +08:00
parent c814766889
commit 2a7af9be6a
11 changed files with 167 additions and 39 deletions
@@ -29,8 +29,7 @@ public class SQLSelectStatement extends SQLStatementImpl {
}
public SQLSelectStatement(SQLSelect select){
this.select = select;
this.setSelect(select);
}
public SQLSelect getSelect() {
@@ -38,6 +37,9 @@ public class SQLSelectStatement extends SQLStatementImpl {
}
public void setSelect(SQLSelect select) {
if (select != null) {
select.setParent(this);
}
this.select = select;
}
@@ -36,6 +36,9 @@ public class MySqlShowGrantsStatement extends MySqlStatementImpl implements MySq
}
public void setUser(SQLExpr user) {
if (user != null) {
user.setParent(this);
}
this.user = user;
}
@@ -210,24 +210,30 @@ public final class DruidStatManagerFacade {
} else if (valueB == null) {
newMap.put(key, valueA);
} else if ("blackList".equals(key)) {
Set<String> newSet = new HashSet<String>();
Map<String, Map<String, Object>> newSet = new HashMap<String, Map<String, Object>>();
Collection<String> collectionA = (Collection<String>) valueA;
for (String blackItem : collectionA) {
Collection<Map<String, Object>> collectionA = (Collection<Map<String, Object>>) valueA;
for (Map<String, Object> blackItem : collectionA) {
if (newSet.size() >= 1000) {
break;
}
newSet.add(blackItem);
String sql = (String) blackItem.get("sql");
Map<String, Object> oldItem = newSet.get(sql);
newSet.put(sql, mergWallStat(oldItem, blackItem));
}
Collection<String> collectionB = (Collection<String>) valueB;
for (String blackItem : collectionB) {
Collection<Map<String, Object>> collectionB = (Collection<Map<String, Object>>) valueB;
for (Map<String, Object> blackItem : collectionB) {
if (newSet.size() >= 1000) {
break;
}
newSet.add(blackItem);
String sql = (String) blackItem.get("sql");
Map<String, Object> oldItem = newSet.get(sql);
newSet.put(sql, mergWallStat(oldItem, blackItem));
}
newMap.put(key, newSet);
newMap.put(key, newSet.values());
} else {
if (valueA instanceof Map && valueB instanceof Map) {
Object newValue = mergWallStat((Map)valueA, (Map)valueB);
@@ -240,7 +246,7 @@ public final class DruidStatManagerFacade {
} else if (valueA instanceof List && valueB instanceof List) {
List<Map<String, Object>> mergedList = mergeNamedList((List) valueA, (List) valueB);
newMap.put(key, mergedList);
} else if (valueA instanceof String && valueB instanceof String && valueA.equals(valueB) && "name".equals(key)) {
} else if (valueA instanceof String && valueB instanceof String && valueA.equals(valueB)) {
newMap.put(key, valueA);
} else {
Object sum = SQLEvalVisitorUtils.add(valueA, valueB);
@@ -155,6 +155,7 @@ public abstract class WallProvider {
WallSqlStat wallStat = whiteList.get(sql);
if (wallStat == null) {
wallStat = new WallSqlStat(tableStats, functionStats, syntaxError);
wallStat.incrementAndGetExecuteCount();
whiteList.put(sql, wallStat);
}
@@ -176,6 +177,7 @@ public abstract class WallProvider {
WallSqlStat wallStat = blackList.get(sql);
if (wallStat == null) {
wallStat = new WallSqlStat(tableStats, functionStats, violations, syntaxError);
wallStat.incrementAndGetExecuteCount();
blackList.put(sql, wallStat);
}
@@ -212,6 +214,33 @@ public abstract class WallProvider {
return Collections.<String> unmodifiableSet(hashSet);
}
public List<Map<String, Object>> getBlackListStat() {
List<Map<String, Object>> map = new ArrayList<Map<String, Object>>();
lock.readLock().lock();
try {
if (blackList != null) {
for (Map.Entry<String, WallSqlStat> entry : this.blackList.entrySet()) {
WallSqlStat sqlStat = entry.getValue();
Map<String, Object> sqlStatMap = new LinkedHashMap<String, Object>();
sqlStatMap.put("sql", entry.getKey());
sqlStatMap.put("executeCount", sqlStat.getExecuteCount());
List<Violation> violations = sqlStat.getViolations();
if (violations.size() > 0) {
sqlStatMap.put("violationMessage", violations.get(0).getMessage());
}
map.add(sqlStatMap);
}
}
} finally {
lock.readLock().unlock();
}
return map;
}
public void clearCache() {
clearWhiteList();
@@ -312,6 +341,10 @@ public abstract class WallProvider {
if (schemaName == null) {
return true;
}
if (!this.config.isSchemaCheck()) {
return true;
}
schemaName = schemaName.toLowerCase();
if (getConfig().getDenySchemas().contains(schemaName)) {
@@ -638,7 +671,7 @@ public abstract class WallProvider {
info.put("functions", functions);
}
// info.put("whiteList", this.getWhiteList());
info.put("blackList", this.getBlackList());
info.put("blackList", this.getBlackListStat());
return info;
}
}
@@ -191,7 +191,10 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
}
if (!checkVar(x.getParent(), x.getName())) {
violations.add(new IllegalSQLObjectViolation("variable not allow : " + x.getName(), toSQL(x)));
boolean isTop = WallVisitorUtils.isTopNoneFromSelect(x);
if (!isTop) {
violations.add(new IllegalSQLObjectViolation("variable not allow : " + x.getName(), toSQL(x)));
}
}
return false;
}
@@ -236,7 +239,10 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
}
if (varName.startsWith("@@") && !checkVar(x.getParent(), x.getName())) {
violations.add(new IllegalSQLObjectViolation("variable not allow : " + x.getName(), toSQL(x)));
boolean isTop = WallVisitorUtils.isTopNoneFromSelect(x);
if (!isTop) {
violations.add(new IllegalSQLObjectViolation("variable not allow : " + x.getName(), toSQL(x)));
}
}
return false;
@@ -344,12 +350,12 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
public boolean visit(SQLSetStatement x) {
return false;
}
@Override
public boolean visit(MySqlReplaceStatement x) {
return true;
}
@Override
public boolean visit(SQLCallStatement x) {
return false;
@@ -74,6 +74,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowGrantsStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
@@ -818,9 +819,86 @@ public class WallVisitorUtils {
}
if (!visitor.getProvider().checkDenyFunction(methodName)) {
boolean isTopNoneFrom = isTopNoneFromSelect(x);
if (isTopNoneFrom) {
return;
}
boolean isShow = x.getParent() instanceof MySqlShowGrantsStatement;
if (isShow) {
return;
}
if ("CONNECTION_ID".equalsIgnoreCase(methodName)) {
SQLSelectQueryBlock queryBlock = getQueryBlock(x);
if (queryBlock != null) {
if (queryBlock.getFrom() instanceof SQLExprTableSource) {
SQLExpr expr = ((SQLExprTableSource) queryBlock.getFrom()).getExpr();
if ("information_schema.processlist".equalsIgnoreCase(expr.toString())) {
return;
}
}
}
}
addViolation(visitor, "deny function : " + methodName, x);
}
}
public static SQLSelectQueryBlock getQueryBlock(SQLObject x) {
if (x == null) {
return null;
}
if (x instanceof SQLSelectQueryBlock) {
return (SQLSelectQueryBlock) x;
}
SQLObject parent = x.getParent();
if (parent instanceof SQLExpr) {
return getQueryBlock(parent);
}
if (parent instanceof SQLSelectItem) {
return getQueryBlock(parent);
}
if (parent instanceof SQLSelectQueryBlock) {
return (SQLSelectQueryBlock) parent;
}
return null;
}
public static boolean isTopNoneFromSelect(SQLExpr x) {
if (!(x.getParent() instanceof SQLSelectItem)) {
return false;
}
SQLSelectItem item = (SQLSelectItem) x.getParent();
if (!(item.getParent() instanceof SQLSelectQueryBlock)) {
return false;
}
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) item.getParent();
if (!queryBlockFromIsNull(queryBlock)) {
return false;
}
if (!(queryBlock.getParent() instanceof SQLSelect)) {
return false;
}
SQLSelect select = (SQLSelect) queryBlock.getParent();
if (!(select.getParent() instanceof SQLSelectStatement)) {
return false;
}
SQLSelectStatement stmt = (SQLSelectStatement) select.getParent();
return stmt.getParent() == null;
}
private static boolean checkSchema(WallVisitor visitor, SQLExpr x) {
@@ -829,12 +907,12 @@ public class WallVisitorUtils {
owner = WallVisitorUtils.form(owner);
if (!visitor.getProvider().checkDenySchema(owner)) {
addViolation(visitor, "deny schema : " + owner, x);
return false;
return true;
}
if (visitor.getConfig().isDenyObjects(owner)) {
addViolation(visitor, "deny object : " + owner, x);
return false;
return true;
}
}