diff --git a/src/main/java/com/alibaba/druid/util/ServletPathMatcher.java b/src/main/java/com/alibaba/druid/util/ServletPathMatcher.java index 11a5885dd6..3bd6090c3d 100644 --- a/src/main/java/com/alibaba/druid/util/ServletPathMatcher.java +++ b/src/main/java/com/alibaba/druid/util/ServletPathMatcher.java @@ -16,6 +16,11 @@ package com.alibaba.druid.util; public class ServletPathMatcher implements PatternMatcher { + private final static ServletPathMatcher instance = new ServletPathMatcher(); + + public static ServletPathMatcher getInstance() { + return instance; + } /** *

diff --git a/src/main/java/com/alibaba/druid/wall/WallConfig.java b/src/main/java/com/alibaba/druid/wall/WallConfig.java index d37b9324b5..0886ac9f9d 100644 --- a/src/main/java/com/alibaba/druid/wall/WallConfig.java +++ b/src/main/java/com/alibaba/druid/wall/WallConfig.java @@ -24,353 +24,353 @@ import com.alibaba.druid.wall.spi.WallVisitorUtils; public class WallConfig implements WallConfigMBean { - private boolean noneBaseStatementAllow = false; + private boolean noneBaseStatementAllow = false; - private boolean callAllow = true; - private boolean selelctAllow = true; - private boolean selectIntoAllow = true; - private boolean selectIntoOutfileAllow = false; - private boolean selectWhereAlwayTrueCheck = true; - private boolean selectHavingAlwayTrueCheck = true; - private boolean selectUnionCheck = true; + private boolean callAllow = true; + private boolean selelctAllow = true; + private boolean selectIntoAllow = true; + private boolean selectIntoOutfileAllow = false; + private boolean selectWhereAlwayTrueCheck = true; + private boolean selectHavingAlwayTrueCheck = true; + private boolean selectUnionCheck = true; - private boolean deleteAllow = true; - private boolean deleteWhereAlwayTrueCheck = true; + private boolean deleteAllow = true; + private boolean deleteWhereAlwayTrueCheck = true; - private boolean updateAllow = true; - private boolean updateWhereAlayTrueCheck = true; + private boolean updateAllow = true; + private boolean updateWhereAlayTrueCheck = true; - private boolean insertAllow = true; - private boolean mergeAllow = true; + private boolean insertAllow = true; + private boolean mergeAllow = true; - private boolean multiStatementAllow = false; + private boolean multiStatementAllow = false; - private boolean truncateAllow = false; + private boolean truncateAllow = false; - private boolean commentAllow = false; + private boolean commentAllow = false; - private boolean schemaCheck = true; - private boolean tableCheck = true; - private boolean functionCheck = true; - private boolean objectCheck = true; - private boolean variantCheck = true; + private boolean schemaCheck = true; + private boolean tableCheck = true; + private boolean functionCheck = true; + private boolean objectCheck = true; + private boolean variantCheck = true; - private boolean mustParameterized = false; + private boolean mustParameterized = false; - private boolean allowDoPrivileged = false; + private boolean allowDoPrivileged = false; - protected final Set permitFunctions = new HashSet(); - protected final Set permitTables = new HashSet(); - protected final Set permitSchemas = new HashSet(); - protected final Set permitVariants = new HashSet(); - protected final Set permitObjects = new HashSet(); + protected final Set permitFunctions = new HashSet(); + protected final Set permitTables = new HashSet(); + protected final Set permitSchemas = new HashSet(); + protected final Set permitVariants = new HashSet(); + protected final Set permitObjects = new HashSet(); - protected final Set readOnlyTables = new HashSet(); + protected final Set readOnlyTables = new HashSet(); - private String dir; + private String dir; - private boolean inited; + private boolean inited; - private String guardTablePattern; - private String guardField; + private String tenantTablePattern; + private String tenantColumn; - public WallConfig(){ + public WallConfig() { - } + } - public String getGuardTablePattern() { - return guardTablePattern; - } + public String getTenantTablePattern() { + return tenantTablePattern; + } - public void setGuardTablePattern(String guardTablePattern) { - this.guardTablePattern = guardTablePattern; - } + public void setTenantTablePattern(String tenantTablePattern) { + this.tenantTablePattern = tenantTablePattern; + } - public String getGuardField() { - return guardField; - } + public String getTenantColumn() { + return tenantColumn; + } - public void setGuardField(String guardField) { - this.guardField = guardField; - } + public void setTenantColumn(String tenantColumn) { + this.tenantColumn = tenantColumn; + } - public boolean isAllowDoPrivileged() { - return allowDoPrivileged; - } + public boolean isAllowDoPrivileged() { + return allowDoPrivileged; + } - public void setAllowDoPrivileged(boolean allowDoPrivileged) { - this.allowDoPrivileged = allowDoPrivileged; - } + public void setAllowDoPrivileged(boolean allowDoPrivileged) { + this.allowDoPrivileged = allowDoPrivileged; + } - public boolean isInited() { - return inited; - } + public boolean isInited() { + return inited; + } - public WallConfig(String dir){ - this.dir = dir; - this.init(); - } + public WallConfig(String dir) { + this.dir = dir; + this.init(); + } - public String getDir() { - return dir; - } + public String getDir() { + return dir; + } - public void setDir(String dir) { - this.dir = dir; - } + public void setDir(String dir) { + this.dir = dir; + } - public final void init() { - loadConfig(dir); - } + public final void init() { + loadConfig(dir); + } - public void loadConfig(String dir) { - if (dir.endsWith("/")) { - dir = dir.substring(0, dir.length() - 1); - } + public void loadConfig(String dir) { + if (dir.endsWith("/")) { + dir = dir.substring(0, dir.length() - 1); + } - loadResource(this.permitVariants, dir + "/permit-variant.txt"); - loadResource(this.permitSchemas, dir + "/permit-schema.txt"); - loadResource(this.permitFunctions, dir + "/permit-function.txt"); - loadResource(this.permitTables, dir + "/permit-table.txt"); - loadResource(this.permitObjects, dir + "/permit-object.txt"); - loadResource(this.readOnlyTables, dir + "/readonly-table.txt"); - } + loadResource(this.permitVariants, dir + "/permit-variant.txt"); + loadResource(this.permitSchemas, dir + "/permit-schema.txt"); + loadResource(this.permitFunctions, dir + "/permit-function.txt"); + loadResource(this.permitTables, dir + "/permit-table.txt"); + loadResource(this.permitObjects, dir + "/permit-object.txt"); + loadResource(this.readOnlyTables, dir + "/readonly-table.txt"); + } - public boolean isNoneBaseStatementAllow() { - return noneBaseStatementAllow; - } + public boolean isNoneBaseStatementAllow() { + return noneBaseStatementAllow; + } - public void setNoneBaseStatementAllow(boolean noneBaseStatementAllow) { - this.noneBaseStatementAllow = noneBaseStatementAllow; - } + public void setNoneBaseStatementAllow(boolean noneBaseStatementAllow) { + this.noneBaseStatementAllow = noneBaseStatementAllow; + } - public boolean isTruncateAllow() { - return truncateAllow; - } + public boolean isTruncateAllow() { + return truncateAllow; + } - public void setTruncateAllow(boolean truncateAllow) { - this.truncateAllow = truncateAllow; - } + public void setTruncateAllow(boolean truncateAllow) { + this.truncateAllow = truncateAllow; + } - public boolean isSelelctAllow() { - return selelctAllow; - } + public boolean isSelelctAllow() { + return selelctAllow; + } - public void setSelelctAllow(boolean selelctAllow) { - this.selelctAllow = selelctAllow; - } + public void setSelelctAllow(boolean selelctAllow) { + this.selelctAllow = selelctAllow; + } - public boolean isSelectIntoAllow() { - return selectIntoAllow; - } + public boolean isSelectIntoAllow() { + return selectIntoAllow; + } - public void setSelectIntoAllow(boolean selectIntoAllow) { - this.selectIntoAllow = selectIntoAllow; - } + public void setSelectIntoAllow(boolean selectIntoAllow) { + this.selectIntoAllow = selectIntoAllow; + } - public boolean isSelectIntoOutfileAllow() { - return selectIntoOutfileAllow; - } + public boolean isSelectIntoOutfileAllow() { + return selectIntoOutfileAllow; + } - public void setSelectIntoOutfileAllow(boolean selectIntoOutfileAllow) { - this.selectIntoOutfileAllow = selectIntoOutfileAllow; - } + public void setSelectIntoOutfileAllow(boolean selectIntoOutfileAllow) { + this.selectIntoOutfileAllow = selectIntoOutfileAllow; + } - public boolean isSelectUnionCheck() { - return selectUnionCheck; - } - - public void setSelectUnionCheck(boolean selectUnionCheck) { - this.selectUnionCheck = selectUnionCheck; - } - - public boolean isSelectWhereAlwayTrueCheck() { - return selectWhereAlwayTrueCheck; - } - - public void setSelectWhereAlwayTrueCheck(boolean selectWhereAlwayTrueCheck) { - this.selectWhereAlwayTrueCheck = selectWhereAlwayTrueCheck; - } - - public boolean isSelectHavingAlwayTrueCheck() { - return selectHavingAlwayTrueCheck; - } - - public void setSelectHavingAlwayTrueCheck(boolean selectHavingAlwayTrueCheck) { - this.selectHavingAlwayTrueCheck = selectHavingAlwayTrueCheck; - } - - public boolean isDeleteAllow() { - return deleteAllow; - } - - public void setDeleteAllow(boolean deleteAllow) { - this.deleteAllow = deleteAllow; - } - - public boolean isDeleteWhereAlwayTrueCheck() { - return deleteWhereAlwayTrueCheck; - } - - public void setDeleteWhereAlwayTrueCheck(boolean deleteWhereAlwayTrueCheck) { - this.deleteWhereAlwayTrueCheck = deleteWhereAlwayTrueCheck; - } - - public boolean isUpdateAllow() { - return updateAllow; - } - - public void setUpdateAllow(boolean updateAllow) { - this.updateAllow = updateAllow; - } - - public boolean isUpdateWhereAlayTrueCheck() { - return updateWhereAlayTrueCheck; - } + public boolean isSelectUnionCheck() { + return selectUnionCheck; + } + + public void setSelectUnionCheck(boolean selectUnionCheck) { + this.selectUnionCheck = selectUnionCheck; + } + + public boolean isSelectWhereAlwayTrueCheck() { + return selectWhereAlwayTrueCheck; + } + + public void setSelectWhereAlwayTrueCheck(boolean selectWhereAlwayTrueCheck) { + this.selectWhereAlwayTrueCheck = selectWhereAlwayTrueCheck; + } + + public boolean isSelectHavingAlwayTrueCheck() { + return selectHavingAlwayTrueCheck; + } + + public void setSelectHavingAlwayTrueCheck(boolean selectHavingAlwayTrueCheck) { + this.selectHavingAlwayTrueCheck = selectHavingAlwayTrueCheck; + } + + public boolean isDeleteAllow() { + return deleteAllow; + } + + public void setDeleteAllow(boolean deleteAllow) { + this.deleteAllow = deleteAllow; + } + + public boolean isDeleteWhereAlwayTrueCheck() { + return deleteWhereAlwayTrueCheck; + } + + public void setDeleteWhereAlwayTrueCheck(boolean deleteWhereAlwayTrueCheck) { + this.deleteWhereAlwayTrueCheck = deleteWhereAlwayTrueCheck; + } + + public boolean isUpdateAllow() { + return updateAllow; + } + + public void setUpdateAllow(boolean updateAllow) { + this.updateAllow = updateAllow; + } + + public boolean isUpdateWhereAlayTrueCheck() { + return updateWhereAlayTrueCheck; + } - public void setUpdateWhereAlayTrueCheck(boolean updateWhereAlayTrueCheck) { - this.updateWhereAlayTrueCheck = updateWhereAlayTrueCheck; - } + public void setUpdateWhereAlayTrueCheck(boolean updateWhereAlayTrueCheck) { + this.updateWhereAlayTrueCheck = updateWhereAlayTrueCheck; + } - public boolean isInsertAllow() { - return insertAllow; - } + public boolean isInsertAllow() { + return insertAllow; + } - public void setInsertAllow(boolean insertAllow) { - this.insertAllow = insertAllow; - } + public void setInsertAllow(boolean insertAllow) { + this.insertAllow = insertAllow; + } - public boolean isMergeAllow() { - return mergeAllow; - } + public boolean isMergeAllow() { + return mergeAllow; + } - public void setMergeAllow(boolean mergeAllow) { - this.mergeAllow = mergeAllow; - } + public void setMergeAllow(boolean mergeAllow) { + this.mergeAllow = mergeAllow; + } - public boolean isMultiStatementAllow() { - return multiStatementAllow; - } + public boolean isMultiStatementAllow() { + return multiStatementAllow; + } - public void setMultiStatementAllow(boolean multiStatementAllow) { - this.multiStatementAllow = multiStatementAllow; - } + public void setMultiStatementAllow(boolean multiStatementAllow) { + this.multiStatementAllow = multiStatementAllow; + } - public boolean isSchemaCheck() { - return schemaCheck; - } + public boolean isSchemaCheck() { + return schemaCheck; + } - public void setSchemaCheck(boolean schemaCheck) { - this.schemaCheck = schemaCheck; - } + public void setSchemaCheck(boolean schemaCheck) { + this.schemaCheck = schemaCheck; + } - public boolean isTableCheck() { - return tableCheck; - } + public boolean isTableCheck() { + return tableCheck; + } - public void setTableCheck(boolean tableCheck) { - this.tableCheck = tableCheck; - } + public void setTableCheck(boolean tableCheck) { + this.tableCheck = tableCheck; + } - public boolean isFunctionCheck() { - return functionCheck; - } + public boolean isFunctionCheck() { + return functionCheck; + } - public void setFunctionCheck(boolean functionCheck) { - this.functionCheck = functionCheck; - } + public void setFunctionCheck(boolean functionCheck) { + this.functionCheck = functionCheck; + } - public boolean isVariantCheck() { - return variantCheck; - } + public boolean isVariantCheck() { + return variantCheck; + } - public void setVariantCheck(boolean variantCheck) { - this.variantCheck = variantCheck; - } + public void setVariantCheck(boolean variantCheck) { + this.variantCheck = variantCheck; + } - public boolean isObjectCheck() { - return objectCheck; - } + public boolean isObjectCheck() { + return objectCheck; + } - public void setObjectCheck(boolean objectCheck) { - this.objectCheck = objectCheck; - } + public void setObjectCheck(boolean objectCheck) { + this.objectCheck = objectCheck; + } - // /////////////////// + // /////////////////// - public boolean isCommentAllow() { - return commentAllow; - } + public boolean isCommentAllow() { + return commentAllow; + } - public void setCommentAllow(boolean commentAllow) { - this.commentAllow = commentAllow; - } + public void setCommentAllow(boolean commentAllow) { + this.commentAllow = commentAllow; + } - public Set getPermitFunctions() { - return permitFunctions; - } + public Set getPermitFunctions() { + return permitFunctions; + } - public Set getPermitTables() { - return permitTables; - } + public Set getPermitTables() { + return permitTables; + } - public Set getPermitSchemas() { - return permitSchemas; - } + public Set getPermitSchemas() { + return permitSchemas; + } - public Set getPermitVariants() { - return permitVariants; - } + public Set getPermitVariants() { + return permitVariants; + } - public Set getPermitObjects() { - return permitObjects; - } + public Set getPermitObjects() { + return permitObjects; + } - public Set getReadOnlyTables() { - return readOnlyTables; - } + public Set getReadOnlyTables() { + return readOnlyTables; + } - public boolean isMustParameterized() { - return mustParameterized; - } + public boolean isMustParameterized() { + return mustParameterized; + } - public void setMustParameterized(boolean mustParameterized) { - this.mustParameterized = mustParameterized; - } + public void setMustParameterized(boolean mustParameterized) { + this.mustParameterized = mustParameterized; + } - public boolean isPermitObjects(String name) { - if (!objectCheck) { - return false; - } + public boolean isPermitObjects(String name) { + if (!objectCheck) { + return false; + } - name = WallVisitorUtils.form(name); - return permitObjects.contains(name); - } + name = WallVisitorUtils.form(name); + return permitObjects.contains(name); + } - public boolean isPermitSchema(String name) { - if (!schemaCheck) { - return false; - } + public boolean isPermitSchema(String name) { + if (!schemaCheck) { + return false; + } - name = WallVisitorUtils.form(name); - return this.permitSchemas.contains(name); - } + name = WallVisitorUtils.form(name); + return this.permitSchemas.contains(name); + } - public boolean isPermitFunction(String name) { - if (!functionCheck) { - return false; - } - - name = WallVisitorUtils.form(name); - return this.permitFunctions.contains(name); - } - - public boolean isCallAllow() { - return callAllow; - } - - public void setCallAllow(boolean callAllow) { - this.callAllow = callAllow; - } + public boolean isPermitFunction(String name) { + if (!functionCheck) { + return false; + } + + name = WallVisitorUtils.form(name); + return this.permitFunctions.contains(name); + } + + public boolean isCallAllow() { + return callAllow; + } + + public void setCallAllow(boolean callAllow) { + this.callAllow = callAllow; + } } diff --git a/src/main/java/com/alibaba/druid/wall/WallProvider.java b/src/main/java/com/alibaba/druid/wall/WallProvider.java index e694bc8512..649dc6f2d2 100644 --- a/src/main/java/com/alibaba/druid/wall/WallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/WallProvider.java @@ -186,13 +186,13 @@ public abstract class WallProvider { } } - private static final ThreadLocal guardValueLocal = new ThreadLocal(); + private static final ThreadLocal tenantValueLocal = new ThreadLocal(); - public static void setGuardValue(Object value) { - guardValueLocal.set(value); + public static void setTenantValue(Object value) { + tenantValueLocal.set(value); } - public static Object getGuardValue() { - return guardValueLocal; + public static Object getTenantValue() { + return tenantValueLocal.get(); } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index 1bc9eb4e56..ae54bab3c0 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -34,12 +34,14 @@ import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLCharExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLNCharExpr; import com.alibaba.druid.sql.ast.expr.SQLNotExpr; import com.alibaba.druid.sql.ast.expr.SQLNullExpr; +import com.alibaba.druid.sql.ast.expr.SQLNumberExpr; import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; @@ -60,660 +62,768 @@ import com.alibaba.druid.sql.visitor.ExportParameterVisitor; import com.alibaba.druid.support.logging.Log; import com.alibaba.druid.support.logging.LogFactory; import com.alibaba.druid.util.JdbcUtils; +import com.alibaba.druid.util.ServletPathMatcher; +import com.alibaba.druid.wall.WallProvider; import com.alibaba.druid.wall.WallVisitor; import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation; public class WallVisitorUtils { - private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class); - - public static void check(WallVisitor visitor, SQLInListExpr x) { - - } - - public static void check(WallVisitor visitor, SQLBinaryOpExpr x) { - - } - - public static void check(WallVisitor visitor, SQLPropertyExpr x) { - checkSchema(visitor, x.getOwner()); - } - - public static void checkInsert(WallVisitor visitor, SQLInsertInto x) { - checkReadOnly(visitor, x.getTableSource()); - - if (!visitor.getConfig().isInsertAllow()) { - visitor.getViolations().add(new IllegalSQLObjectViolation(visitor.toSQL(x))); - } - } - - public static void checkSelelct(WallVisitor visitor, SQLSelectQueryBlock x) { - if (x.getInto() != null) { - checkReadOnly(visitor, x.getInto()); - } - - if (!visitor.getConfig().isSelectIntoAllow() && x.getInto() != null) { - addViolation(visitor, x); - return; - } - - if (!visitor.getConfig().isSelectWhereAlwayTrueCheck()) { - return; - } - - SQLExpr where = x.getWhere(); - - // if (visitor.getConfig().isMustParameterized()) { - if (where != null) { - checkCondition(visitor, x.getWhere()); - - if (Boolean.TRUE == getValue(where)) { - if (where instanceof SQLBinaryOpExpr) { - SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) where; - if (binaryOpExpr.getOperator() == SQLBinaryOperator.Equality - || binaryOpExpr.getOperator() == SQLBinaryOperator.NotEqual) { - if (binaryOpExpr.getLeft() instanceof SQLIntegerExpr - && binaryOpExpr.getRight() instanceof SQLIntegerExpr) { - return; - } - } - } - - addViolation(visitor, x); - } - - } - } - - public static void checkHaving(WallVisitor visitor, SQLExpr x) { - if (x == null) { - return; - } - - if (!visitor.getConfig().isSelectHavingAlwayTrueCheck()) { - return; - } - - if (Boolean.TRUE == getValue(x)) { - addViolation(visitor, x); - } - } - - public static void checkDelete(WallVisitor visitor, SQLDeleteStatement x) { - checkReadOnly(visitor, x.getExprTableSource()); - - if (!visitor.getConfig().isDeleteAllow()) { - addViolation(visitor, x); - return; - } - - if (!visitor.getConfig().isDeleteWhereAlwayTrueCheck()) { - return; - } - - if (x.getWhere() == null || Boolean.TRUE == getValue(x.getWhere())) { - addViolation(visitor, x); - return; - } - - checkCondition(visitor, x.getWhere()); - } - - private static void checkCondition(WallVisitor visitor, SQLExpr x) { - if (x == null) { - return; - } - - if (visitor.getConfig().isMustParameterized()) { - ExportParameterVisitor exportParameterVisitor = visitor.getProvider().createExportParameterVisitor(); - x.accept(exportParameterVisitor); - - if (exportParameterVisitor.getParameters().size() > 0) { - addViolation(visitor, x); - return; - } - } - } - - public static void checkReadOnly(WallVisitor visitor, SQLTableSource tableSource) { - if (tableSource instanceof SQLExprTableSource) { - String tableName = null; - SQLExpr tableNameExpr = ((SQLExprTableSource) tableSource).getExpr(); - if (tableNameExpr instanceof SQLName) { - tableName = ((SQLName) tableNameExpr).getSimleName(); - } - - if (tableName != null) { - tableName = form(tableName); - if (visitor.getConfig().getReadOnlyTables().contains(tableName)) { - addViolation(visitor, tableSource); - } - } - } else if (tableSource instanceof SQLJoinTableSource) { - SQLJoinTableSource join = (SQLJoinTableSource) tableSource; - - checkReadOnly(visitor, join.getLeft()); - checkReadOnly(visitor, join.getRight()); - } - } - - public static void checkUpdate(WallVisitor visitor, SQLUpdateStatement x) { - checkReadOnly(visitor, x.getTableSource()); - - if (!visitor.getConfig().isUpdateAllow()) { - addViolation(visitor, x); - return; - } - - if (!visitor.getConfig().isUpdateWhereAlayTrueCheck()) { - return; - } - - if (x.getWhere() == null || Boolean.TRUE == getValue(x.getWhere())) { - addViolation(visitor, x); - return; - } - - checkCondition(visitor, x.getWhere()); - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - public static Object getValue(SQLBinaryOpExpr x) { - x.getLeft().setParent(x); - x.getRight().setParent(x); - - if (x.getLeft() instanceof SQLName && x.getRight() instanceof SQLName) { - if (x.getLeft().toString().equalsIgnoreCase(x.getRight().toString())) { - if (x.getOperator() == SQLBinaryOperator.Equality) { - return Boolean.TRUE; - } else if (x.getOperator() == SQLBinaryOperator.NotEqual) { - return Boolean.FALSE; - } - - switch (x.getOperator()) { - case Equality: - case Like: - return Boolean.TRUE; - case NotEqual: - case GreaterThan: - case GreaterThanOrEqual: - case LessThan: - case LessThanOrEqual: - case LessThanOrGreater: - case NotLike: - return Boolean.FALSE; - default: - break; - } - } - } - - if (x.getOperator() == SQLBinaryOperator.BooleanOr) { - List groupList = new ArrayList(); - SQLExpr left = x.getLeft(); - for (;;) { - if (left instanceof SQLBinaryOpExpr && ((SQLBinaryOpExpr) left).getOperator() == x.getOperator()) { - SQLBinaryOpExpr binaryLeft = (SQLBinaryOpExpr) left; - groupList.add(binaryLeft.getRight()); - left = binaryLeft.getLeft(); - } else { - groupList.add(left); - break; - } - } - groupList.add(x.getRight()); - - boolean allFalse = true; - for (int i = groupList.size() - 1; i >= 0; --i) { - Object result = getValue(groupList.get(i)); - if (Boolean.TRUE == result) { - return true; - } - - if (Boolean.FALSE != result) { - allFalse = false; - } - } - - if (allFalse) { - return false; - } - - return null; - } - - - Object leftResult = getValue(x.getLeft()); - Object rightResult = getValue(x.getRight()); - - if (x.getOperator() == SQLBinaryOperator.BooleanAnd) { - if (Boolean.FALSE == leftResult || Boolean.FALSE == rightResult) { - return false; - } - - if (Boolean.TRUE == leftResult && Boolean.TRUE == rightResult) { - return true; - } - } - - if (x.getOperator() == SQLBinaryOperator.Like) { - if (x.getRight() instanceof SQLCharExpr) { - String text = ((SQLCharExpr) x.getRight()).getText(); - - if (text.length() >= 0) { - for (char ch : text.toCharArray()) { - if (ch != '%') { - return null; - } - } - - return true; - } - - } - } - - if (leftResult == null || rightResult == null) { - return null; - } - - if (x.getOperator() == SQLBinaryOperator.Equality) { - if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { - return true; - } - - return leftResult.equals(rightResult); - } - - if (x.getOperator() == SQLBinaryOperator.NotEqual || x.getOperator() == SQLBinaryOperator.LessThanOrGreater) { - if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { - return false; - } - - if (leftResult == null || rightResult == null) { - return null; - } - - return !leftResult.equals(rightResult); - } - - if (x.getOperator() == SQLBinaryOperator.GreaterThan) { - if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { - return false; - } - - if (leftResult == null || rightResult == null) { - return null; - } - - if (leftResult instanceof Comparable) { - return (((Comparable) leftResult).compareTo(rightResult) > 0); - } - } - - if (x.getOperator() == SQLBinaryOperator.GreaterThanOrEqual) { - if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { - return false; - } - - if (leftResult == null || rightResult == null) { - return null; - } - - if (leftResult instanceof Comparable) { - return ((Comparable) leftResult).compareTo(rightResult) >= 0; - } - } - - if (x.getOperator() == SQLBinaryOperator.LessThan) { - if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { - return false; - } - - if (leftResult == null || rightResult == null) { - return null; - } - - if (leftResult instanceof Comparable) { - return (((Comparable) leftResult).compareTo(rightResult) < 0); - } - } - - if (x.getOperator() == SQLBinaryOperator.LessThanOrEqual) { - if (x.getLeft() instanceof SQLNullExpr && x.getRight() instanceof SQLNullExpr) { - return false; - } - - if (leftResult == null || rightResult == null) { - return null; - } - - if (leftResult instanceof Comparable) { - return ((Comparable) leftResult).compareTo(rightResult) <= 0; - } - } - - if (x.getOperator() == SQLBinaryOperator.Concat) { - return leftResult.toString() + rightResult.toString(); - } - - if (x.getOperator() == SQLBinaryOperator.Add) { - if (leftResult == null || rightResult == null) { - return null; - } - - if (leftResult instanceof String || rightResult instanceof String) { - return leftResult.toString() + rightResult.toString(); - } - - if (leftResult instanceof Number || rightResult instanceof Number) { - return add((Number) leftResult, (Number) rightResult); - } - } - - return null; - } - - private static Number add(Number a, Number b) { - if (a instanceof BigDecimal) { - return ((BigDecimal) a).add(new BigDecimal(b.toString())); - } - - return a.longValue() + b.longValue(); - } - - public static Object getValue(SQLExpr x) { - if (x instanceof SQLBinaryOpExpr) { - return getValue((SQLBinaryOpExpr) x); - } - - if (x instanceof MySqlBooleanExpr) { - return ((MySqlBooleanExpr) x).getValue(); - } - - if (x instanceof SQLNumericLiteralExpr) { - return ((SQLNumericLiteralExpr) x).getNumber(); - } - - if (x instanceof SQLCharExpr) { - return ((SQLCharExpr) x).getText(); - } - - if (x instanceof SQLNCharExpr) { - return ((SQLNCharExpr) x).getText(); - } - - if (x instanceof SQLNotExpr) { - Object result = getValue(((SQLNotExpr) x).getExpr()); - if (result instanceof Boolean) { - return !((Boolean) result).booleanValue(); - } - } - - if (x instanceof SQLQueryExpr) { - if (isSimpleCountTableSource(((SQLQueryExpr) x).getSubQuery())) { - return Integer.valueOf(1); - } - } - - if (x instanceof SQLMethodInvokeExpr) { - return getValue((SQLMethodInvokeExpr) x); - } - - return null; - } - - public static Object getValue(SQLMethodInvokeExpr x) { - String methodName = x.getMethodName(); - if ("len".equalsIgnoreCase(methodName) || "length".equalsIgnoreCase(methodName)) { - Object firstValue = null; - if (x.getParameters().size() > 0) { - firstValue = (getValue(x.getParameters().get(0))); - } - - if (firstValue instanceof String) { - 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)); - } - } - - if ("chr".equalsIgnoreCase(methodName) && x.getParameters().size() == 1) { - SQLExpr first = x.getParameters().get(0); - Object firstResult = getValue(first); - if (firstResult instanceof Number) { - int intValue = ((Number) firstResult).intValue(); - char ch = (char) intValue; - - return "" + ch; - } - } - - if ("concat".equalsIgnoreCase(methodName)) { - StringBuffer buf = new StringBuffer(); - for (SQLExpr expr : x.getParameters()) { - Object value = getValue(expr); - if (value == null) { - return null; - } - - buf.append(value.toString()); - } - return buf.toString(); - } - - return null; - } - - public static boolean isSimpleCountTableSource(SQLTableSource tableSource) { - if (!(tableSource instanceof SQLSubqueryTableSource)) { - return false; - } - - SQLSubqueryTableSource subQuery = (SQLSubqueryTableSource) tableSource; - - return isSimpleCountTableSource(subQuery.getSelect()); - } - - public static boolean isSimpleCountTableSource(SQLSelect select) { - SQLSelectQuery query = select.getQuery(); - - if (query instanceof SQLSelectQueryBlock) { - SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query; - - boolean allawTrueWhere = false; - - if (queryBlock.getWhere() == null) { - allawTrueWhere = true; - } else { - Object whereValue = getValue(queryBlock.getWhere()); - if (whereValue == Boolean.TRUE) { - allawTrueWhere = true; - } else if (whereValue == Boolean.FALSE) { - return false; - } - } - boolean simpleCount = false; - if (queryBlock.getSelectList().size() == 1) { - SQLExpr selectItemExpr = queryBlock.getSelectList().get(0).getExpr(); - if (selectItemExpr instanceof SQLAggregateExpr) { - if (((SQLAggregateExpr) selectItemExpr).getMethodName().equalsIgnoreCase("COUNT")) { - simpleCount = true; - } - } - } - - if (allawTrueWhere && simpleCount) { - return true; - } - } - - return false; - } - - public static void checkFunction(WallVisitor visitor, SQLMethodInvokeExpr x) { - checkSchema(visitor, x.getOwner()); - - if (!visitor.getConfig().isFunctionCheck()) { - return; - } - - String methodName = x.getMethodName(); - - if (visitor.getConfig().isPermitFunction(methodName.toLowerCase())) { - addViolation(visitor, x); - } - - } - - private static void checkSchema(WallVisitor visitor, SQLExpr x) { - if (x instanceof SQLName) { - String owner = ((SQLName) x).getSimleName(); - owner = WallVisitorUtils.form(owner); - if (visitor.getConfig().isPermitSchema(owner)) { - addViolation(visitor, x); - } - - if (visitor.getConfig().isPermitObjects(owner)) { - addViolation(visitor, x); - } - } - - // if (ownerExpr instanceof SQLPropertyExpr) { - if (x instanceof SQLPropertyExpr) { - checkSchema(visitor, ((SQLPropertyExpr) x).getOwner()); - } - } - - public static void check(WallVisitor visitor, SQLExprTableSource x) { - SQLExpr expr = x.getExpr(); - - if (expr instanceof SQLPropertyExpr) { - checkSchema(visitor, ((SQLPropertyExpr) expr).getOwner()); - } - - if (expr instanceof SQLName) { - String tableName = ((SQLName) expr).getSimleName(); - if (visitor.isPermitTable(tableName)) { - addViolation(visitor, x); - } - } - } - - private static void addViolation(WallVisitor visitor, SQLObject x) { - visitor.getViolations().add(new IllegalSQLObjectViolation(visitor.toSQL(x))); - } - - public static void checkUnion(WallVisitor visitor, SQLUnionQuery x) { - if (!visitor.getConfig().isSelectUnionCheck()) { - return; - } - - if (WallVisitorUtils.queryBlockFromIsNull(x.getLeft()) || WallVisitorUtils.queryBlockFromIsNull(x.getRight())) { - addViolation(visitor, x); - } - } - - public static boolean queryBlockFromIsNull(SQLSelectQuery query) { - if (query instanceof SQLSelectQueryBlock) { - SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query; - SQLTableSource from = queryBlock.getFrom(); - - if (from == null) { - return true; - } - - if (from instanceof SQLExprTableSource) { - SQLExpr fromExpr = ((SQLExprTableSource) from).getExpr(); - if (fromExpr instanceof SQLName) { - String name = fromExpr.toString(); - - name = form(name); - - if (name.equalsIgnoreCase("DUAL")) { - return true; - } - } - } - - if (queryBlock.getSelectList().size() == 1 - && queryBlock.getSelectList().get(0).getExpr() instanceof SQLAllColumnExpr) { - if (from instanceof SQLSubqueryTableSource) { - SQLSelectQuery subQuery = ((SQLSubqueryTableSource) from).getSelect().getQuery(); - if (queryBlockFromIsNull(subQuery)) { - return true; - } - } - } - - boolean allIsConst = true; - for (SQLSelectItem item : queryBlock.getSelectList()) { - if (getValue(item.getExpr()) == null) { - allIsConst = false; - break; - } - } - if (allIsConst) { - return true; - } - } - - return false; - } - - public static String form(String name) { - if (name.startsWith("\"") && name.endsWith("\"")) { - name = name.substring(1, name.length() - 1); - } - if (name.startsWith("`") && name.endsWith("`")) { - name = name.substring(1, name.length() - 1); - } - - name = name.toLowerCase(); - return name; - } - - public static void loadResource(Set names, String resource) { - try { - Enumeration 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); - } - } + private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class); + + public static void check(WallVisitor visitor, SQLInListExpr x) { + + } + + public static void check(WallVisitor visitor, SQLBinaryOpExpr x) { + + } + + public static void check(WallVisitor visitor, SQLPropertyExpr x) { + checkSchema(visitor, x.getOwner()); + } + + public static void checkInsert(WallVisitor visitor, SQLInsertInto x) { + checkReadOnly(visitor, x.getTableSource()); + + if (!visitor.getConfig().isInsertAllow()) { + visitor.getViolations().add( + new IllegalSQLObjectViolation(visitor.toSQL(x))); + } + } + + public static void checkSelelct(WallVisitor visitor, SQLSelectQueryBlock x) { + if (x.getInto() != null) { + checkReadOnly(visitor, x.getInto()); + } + + if (!visitor.getConfig().isSelectIntoAllow() && x.getInto() != null) { + addViolation(visitor, x); + return; + } + + if (!visitor.getConfig().isSelectWhereAlwayTrueCheck()) { + return; + } + + SQLExpr where = x.getWhere(); + + if (where != null) { + x.getWhere().setParent(x); + checkCondition(visitor, x.getWhere()); + + if (Boolean.TRUE == getValue(where)) { + if (where instanceof SQLBinaryOpExpr) { + SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) where; + if (binaryOpExpr.getOperator() == SQLBinaryOperator.Equality + || binaryOpExpr.getOperator() == SQLBinaryOperator.NotEqual) { + if (binaryOpExpr.getLeft() instanceof SQLIntegerExpr + && binaryOpExpr.getRight() instanceof SQLIntegerExpr) { + return; + } + } + } + + addViolation(visitor, x); + } + + } + checkConditionForMultiTenant(visitor, x.getWhere(), x); + } + + public static void checkHaving(WallVisitor visitor, SQLExpr x) { + if (x == null) { + return; + } + + if (!visitor.getConfig().isSelectHavingAlwayTrueCheck()) { + return; + } + + if (Boolean.TRUE == getValue(x)) { + addViolation(visitor, x); + } + } + + public static void checkDelete(WallVisitor visitor, SQLDeleteStatement x) { + checkReadOnly(visitor, x.getExprTableSource()); + + if (!visitor.getConfig().isDeleteAllow()) { + addViolation(visitor, x); + return; + } + + if (!visitor.getConfig().isDeleteWhereAlwayTrueCheck()) { + return; + } + + if (x.getWhere() == null || Boolean.TRUE == getValue(x.getWhere())) { + addViolation(visitor, x); + return; + } + + x.getWhere().setParent(x); + checkCondition(visitor, x.getWhere()); + checkConditionForMultiTenant(visitor, x.getWhere(), x); + } + + private static void checkCondition(WallVisitor visitor, SQLExpr x) { + if (x == null) { + return; + } + + if (visitor.getConfig().isMustParameterized()) { + ExportParameterVisitor exportParameterVisitor = visitor + .getProvider().createExportParameterVisitor(); + x.accept(exportParameterVisitor); + + if (exportParameterVisitor.getParameters().size() > 0) { + addViolation(visitor, x); + return; + } + } + + } + + public static void checkConditionForMultiTenant(WallVisitor visitor, + SQLExpr x, SQLObject parent) { + String tenantTablePattern = visitor.getConfig().getTenantTablePattern(); + if (tenantTablePattern == null || tenantTablePattern.length() == 0) { + return; + } + + if (parent == null) { + throw new IllegalStateException("parent is null"); + } + + SQLTableSource tableSource; + if (parent instanceof SQLDeleteStatement) { + tableSource = ((SQLDeleteStatement) parent).getTableSource(); + } else if (parent instanceof SQLUpdateStatement) { + tableSource = ((SQLUpdateStatement) parent).getTableSource(); + } else if (parent instanceof SQLSelectQueryBlock) { + tableSource = ((SQLSelectQueryBlock) parent).getFrom(); + } else { + throw new IllegalStateException("not support parent : " + + parent.getClass()); + } + + String matchTableName = null; + if (tableSource instanceof SQLExprTableSource) { + SQLExpr tableExpr = ((SQLExprTableSource) tableSource).getExpr(); + + if (tableExpr instanceof SQLIdentifierExpr) { + String tableName = ((SQLIdentifierExpr) tableExpr).getName(); + if (ServletPathMatcher.getInstance().matches( + tenantTablePattern, tableName)) { + matchTableName = tableName; + } + } + } + + if (matchTableName == null) { + return; + } + + SQLExpr left, right; + if (tableSource.getAlias() != null) { + left = new SQLPropertyExpr(new SQLIdentifierExpr( + tableSource.getAlias()), visitor.getConfig() + .getTenantColumn()); + } else { + left = new SQLPropertyExpr(new SQLIdentifierExpr(matchTableName), + visitor.getConfig().getTenantColumn()); + } + + Object tenantValue = WallProvider.getTenantValue(); + if (tenantValue instanceof Number) { + right = new SQLNumberExpr((Number) tenantValue); + } else if (tenantValue instanceof String) { + right = new SQLCharExpr((String) tenantValue); + } else { + throw new IllegalStateException("tenant value not support type " + + tenantValue); + } + + SQLBinaryOpExpr tenantCondition = new SQLBinaryOpExpr(left, + SQLBinaryOperator.Equality, right); + + SQLExpr condition; + if (x == null) { + condition = tenantCondition; + } else { + condition = new SQLBinaryOpExpr(tenantCondition, + SQLBinaryOperator.BooleanAnd, x); + } + + if (parent instanceof SQLDeleteStatement) { + ((SQLDeleteStatement) parent).setWhere(condition); + } else if (parent instanceof SQLUpdateStatement) { + ((SQLUpdateStatement) parent).setWhere(condition); + } else if (parent instanceof SQLSelectQueryBlock) { + ((SQLSelectQueryBlock) parent).setWhere(condition); + } + } + + public static void checkReadOnly(WallVisitor visitor, + SQLTableSource tableSource) { + if (tableSource instanceof SQLExprTableSource) { + String tableName = null; + SQLExpr tableNameExpr = ((SQLExprTableSource) tableSource) + .getExpr(); + if (tableNameExpr instanceof SQLName) { + tableName = ((SQLName) tableNameExpr).getSimleName(); + } + + if (tableName != null) { + tableName = form(tableName); + if (visitor.getConfig().getReadOnlyTables().contains(tableName)) { + addViolation(visitor, tableSource); + } + } + } else if (tableSource instanceof SQLJoinTableSource) { + SQLJoinTableSource join = (SQLJoinTableSource) tableSource; + + checkReadOnly(visitor, join.getLeft()); + checkReadOnly(visitor, join.getRight()); + } + } + + public static void checkUpdate(WallVisitor visitor, SQLUpdateStatement x) { + checkReadOnly(visitor, x.getTableSource()); + + if (!visitor.getConfig().isUpdateAllow()) { + addViolation(visitor, x); + return; + } + + if (!visitor.getConfig().isUpdateWhereAlayTrueCheck()) { + return; + } + + if (x.getWhere() == null || Boolean.TRUE == getValue(x.getWhere())) { + addViolation(visitor, x); + return; + } + + x.getWhere().setParent(x); + checkCondition(visitor, x.getWhere()); + checkConditionForMultiTenant(visitor, x.getWhere(), x); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static Object getValue(SQLBinaryOpExpr x) { + x.getLeft().setParent(x); + x.getRight().setParent(x); + + if (x.getLeft() instanceof SQLName && x.getRight() instanceof SQLName) { + if (x.getLeft().toString() + .equalsIgnoreCase(x.getRight().toString())) { + if (x.getOperator() == SQLBinaryOperator.Equality) { + return Boolean.TRUE; + } else if (x.getOperator() == SQLBinaryOperator.NotEqual) { + return Boolean.FALSE; + } + + switch (x.getOperator()) { + case Equality: + case Like: + return Boolean.TRUE; + case NotEqual: + case GreaterThan: + case GreaterThanOrEqual: + case LessThan: + case LessThanOrEqual: + case LessThanOrGreater: + case NotLike: + return Boolean.FALSE; + default: + break; + } + } + } + + if (x.getOperator() == SQLBinaryOperator.BooleanOr) { + List groupList = new ArrayList(); + SQLExpr left = x.getLeft(); + for (;;) { + if (left instanceof SQLBinaryOpExpr + && ((SQLBinaryOpExpr) left).getOperator() == x + .getOperator()) { + SQLBinaryOpExpr binaryLeft = (SQLBinaryOpExpr) left; + groupList.add(binaryLeft.getRight()); + left = binaryLeft.getLeft(); + } else { + groupList.add(left); + break; + } + } + groupList.add(x.getRight()); + + boolean allFalse = true; + for (int i = groupList.size() - 1; i >= 0; --i) { + Object result = getValue(groupList.get(i)); + if (Boolean.TRUE == result) { + return true; + } + + if (Boolean.FALSE != result) { + allFalse = false; + } + } + + if (allFalse) { + return false; + } + + return null; + } + + Object leftResult = getValue(x.getLeft()); + Object rightResult = getValue(x.getRight()); + + if (x.getOperator() == SQLBinaryOperator.BooleanAnd) { + if (Boolean.FALSE == leftResult || Boolean.FALSE == rightResult) { + return false; + } + + if (Boolean.TRUE == leftResult && Boolean.TRUE == rightResult) { + return true; + } + } + + if (x.getOperator() == SQLBinaryOperator.Like) { + if (x.getRight() instanceof SQLCharExpr) { + String text = ((SQLCharExpr) x.getRight()).getText(); + + if (text.length() >= 0) { + for (char ch : text.toCharArray()) { + if (ch != '%') { + return null; + } + } + + return true; + } + + } + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (x.getOperator() == SQLBinaryOperator.Equality) { + if (x.getLeft() instanceof SQLNullExpr + && x.getRight() instanceof SQLNullExpr) { + return true; + } + + return leftResult.equals(rightResult); + } + + if (x.getOperator() == SQLBinaryOperator.NotEqual + || x.getOperator() == SQLBinaryOperator.LessThanOrGreater) { + if (x.getLeft() instanceof SQLNullExpr + && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + return !leftResult.equals(rightResult); + } + + if (x.getOperator() == SQLBinaryOperator.GreaterThan) { + if (x.getLeft() instanceof SQLNullExpr + && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof Comparable) { + return (((Comparable) leftResult).compareTo(rightResult) > 0); + } + } + + if (x.getOperator() == SQLBinaryOperator.GreaterThanOrEqual) { + if (x.getLeft() instanceof SQLNullExpr + && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof Comparable) { + return ((Comparable) leftResult).compareTo(rightResult) >= 0; + } + } + + if (x.getOperator() == SQLBinaryOperator.LessThan) { + if (x.getLeft() instanceof SQLNullExpr + && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof Comparable) { + return (((Comparable) leftResult).compareTo(rightResult) < 0); + } + } + + if (x.getOperator() == SQLBinaryOperator.LessThanOrEqual) { + if (x.getLeft() instanceof SQLNullExpr + && x.getRight() instanceof SQLNullExpr) { + return false; + } + + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof Comparable) { + return ((Comparable) leftResult).compareTo(rightResult) <= 0; + } + } + + if (x.getOperator() == SQLBinaryOperator.Concat) { + return leftResult.toString() + rightResult.toString(); + } + + if (x.getOperator() == SQLBinaryOperator.Add) { + if (leftResult == null || rightResult == null) { + return null; + } + + if (leftResult instanceof String || rightResult instanceof String) { + return leftResult.toString() + rightResult.toString(); + } + + if (leftResult instanceof Number || rightResult instanceof Number) { + return add((Number) leftResult, (Number) rightResult); + } + } + + return null; + } + + private static Number add(Number a, Number b) { + if (a instanceof BigDecimal) { + return ((BigDecimal) a).add(new BigDecimal(b.toString())); + } + + return a.longValue() + b.longValue(); + } + + public static Object getValue(SQLExpr x) { + if (x instanceof SQLBinaryOpExpr) { + return getValue((SQLBinaryOpExpr) x); + } + + if (x instanceof MySqlBooleanExpr) { + return ((MySqlBooleanExpr) x).getValue(); + } + + if (x instanceof SQLNumericLiteralExpr) { + return ((SQLNumericLiteralExpr) x).getNumber(); + } + + if (x instanceof SQLCharExpr) { + return ((SQLCharExpr) x).getText(); + } + + if (x instanceof SQLNCharExpr) { + return ((SQLNCharExpr) x).getText(); + } + + if (x instanceof SQLNotExpr) { + Object result = getValue(((SQLNotExpr) x).getExpr()); + if (result instanceof Boolean) { + return !((Boolean) result).booleanValue(); + } + } + + if (x instanceof SQLQueryExpr) { + if (isSimpleCountTableSource(((SQLQueryExpr) x).getSubQuery())) { + return Integer.valueOf(1); + } + } + + if (x instanceof SQLMethodInvokeExpr) { + return getValue((SQLMethodInvokeExpr) x); + } + + return null; + } + + public static Object getValue(SQLMethodInvokeExpr x) { + String methodName = x.getMethodName(); + if ("len".equalsIgnoreCase(methodName) + || "length".equalsIgnoreCase(methodName)) { + Object firstValue = null; + if (x.getParameters().size() > 0) { + firstValue = (getValue(x.getParameters().get(0))); + } + + if (firstValue instanceof String) { + 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)); + } + } + + if ("chr".equalsIgnoreCase(methodName) && x.getParameters().size() == 1) { + SQLExpr first = x.getParameters().get(0); + Object firstResult = getValue(first); + if (firstResult instanceof Number) { + int intValue = ((Number) firstResult).intValue(); + char ch = (char) intValue; + + return "" + ch; + } + } + + if ("concat".equalsIgnoreCase(methodName)) { + StringBuffer buf = new StringBuffer(); + for (SQLExpr expr : x.getParameters()) { + Object value = getValue(expr); + if (value == null) { + return null; + } + + buf.append(value.toString()); + } + return buf.toString(); + } + + return null; + } + + public static boolean isSimpleCountTableSource(SQLTableSource tableSource) { + if (!(tableSource instanceof SQLSubqueryTableSource)) { + return false; + } + + SQLSubqueryTableSource subQuery = (SQLSubqueryTableSource) tableSource; + + return isSimpleCountTableSource(subQuery.getSelect()); + } + + public static boolean isSimpleCountTableSource(SQLSelect select) { + SQLSelectQuery query = select.getQuery(); + + if (query instanceof SQLSelectQueryBlock) { + SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query; + + boolean allawTrueWhere = false; + + if (queryBlock.getWhere() == null) { + allawTrueWhere = true; + } else { + Object whereValue = getValue(queryBlock.getWhere()); + if (whereValue == Boolean.TRUE) { + allawTrueWhere = true; + } else if (whereValue == Boolean.FALSE) { + return false; + } + } + boolean simpleCount = false; + if (queryBlock.getSelectList().size() == 1) { + SQLExpr selectItemExpr = queryBlock.getSelectList().get(0) + .getExpr(); + if (selectItemExpr instanceof SQLAggregateExpr) { + if (((SQLAggregateExpr) selectItemExpr).getMethodName() + .equalsIgnoreCase("COUNT")) { + simpleCount = true; + } + } + } + + if (allawTrueWhere && simpleCount) { + return true; + } + } + + return false; + } + + public static void checkFunction(WallVisitor visitor, SQLMethodInvokeExpr x) { + checkSchema(visitor, x.getOwner()); + + if (!visitor.getConfig().isFunctionCheck()) { + return; + } + + String methodName = x.getMethodName(); + + if (visitor.getConfig().isPermitFunction(methodName.toLowerCase())) { + addViolation(visitor, x); + } + + } + + private static void checkSchema(WallVisitor visitor, SQLExpr x) { + if (x instanceof SQLName) { + String owner = ((SQLName) x).getSimleName(); + owner = WallVisitorUtils.form(owner); + if (visitor.getConfig().isPermitSchema(owner)) { + addViolation(visitor, x); + } + + if (visitor.getConfig().isPermitObjects(owner)) { + addViolation(visitor, x); + } + } + + // if (ownerExpr instanceof SQLPropertyExpr) { + if (x instanceof SQLPropertyExpr) { + checkSchema(visitor, ((SQLPropertyExpr) x).getOwner()); + } + } + + public static void check(WallVisitor visitor, SQLExprTableSource x) { + SQLExpr expr = x.getExpr(); + + if (expr instanceof SQLPropertyExpr) { + checkSchema(visitor, ((SQLPropertyExpr) expr).getOwner()); + } + + if (expr instanceof SQLName) { + String tableName = ((SQLName) expr).getSimleName(); + if (visitor.isPermitTable(tableName)) { + addViolation(visitor, x); + } + } + } + + private static void addViolation(WallVisitor visitor, SQLObject x) { + visitor.getViolations().add( + new IllegalSQLObjectViolation(visitor.toSQL(x))); + } + + public static void checkUnion(WallVisitor visitor, SQLUnionQuery x) { + if (!visitor.getConfig().isSelectUnionCheck()) { + return; + } + + if (WallVisitorUtils.queryBlockFromIsNull(x.getLeft()) + || WallVisitorUtils.queryBlockFromIsNull(x.getRight())) { + addViolation(visitor, x); + } + } + + public static boolean queryBlockFromIsNull(SQLSelectQuery query) { + if (query instanceof SQLSelectQueryBlock) { + SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) query; + SQLTableSource from = queryBlock.getFrom(); + + if (from == null) { + return true; + } + + if (from instanceof SQLExprTableSource) { + SQLExpr fromExpr = ((SQLExprTableSource) from).getExpr(); + if (fromExpr instanceof SQLName) { + String name = fromExpr.toString(); + + name = form(name); + + if (name.equalsIgnoreCase("DUAL")) { + return true; + } + } + } + + if (queryBlock.getSelectList().size() == 1 + && queryBlock.getSelectList().get(0).getExpr() instanceof SQLAllColumnExpr) { + if (from instanceof SQLSubqueryTableSource) { + SQLSelectQuery subQuery = ((SQLSubqueryTableSource) from) + .getSelect().getQuery(); + if (queryBlockFromIsNull(subQuery)) { + return true; + } + } + } + + boolean allIsConst = true; + for (SQLSelectItem item : queryBlock.getSelectList()) { + if (getValue(item.getExpr()) == null) { + allIsConst = false; + break; + } + } + if (allIsConst) { + return true; + } + } + + return false; + } + + public static String form(String name) { + if (name.startsWith("\"") && name.endsWith("\"")) { + name = name.substring(1, name.length() - 1); + } + if (name.startsWith("`") && name.endsWith("`")) { + name = name.substring(1, name.length() - 1); + } + + name = name.toLowerCase(); + return name; + } + + public static void loadResource(Set names, String resource) { + try { + Enumeration 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); + } + } } diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantUpdateTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantUpdateTest.java new file mode 100644 index 0000000000..8d2d6a8b89 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/TenantUpdateTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * 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 com.alibaba.druid.bvt.filter.wall; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.util.JdbcConstants; +import com.alibaba.druid.wall.WallCheckResult; +import com.alibaba.druid.wall.WallConfig; +import com.alibaba.druid.wall.WallProvider; +import com.alibaba.druid.wall.spi.MySqlWallProvider; + +public class TenantUpdateTest extends TestCase { + private String sql = "UPDATE T_USER SET FNAME = ? WHERE FID = ?"; + + private WallConfig config = new WallConfig(); + + protected void setUp() throws Exception { + config.setDeleteAllow(false); + config.setTenantTablePattern("*"); + config.setTenantColumn("tenant"); + } + + public void testMySql() throws Exception { + WallProvider.setTenantValue(123); + MySqlWallProvider provider = new MySqlWallProvider(config); + WallCheckResult checkResult = provider.check(sql); + Assert.assertEquals(0, checkResult.getViolations().size()); + + String resultSql = SQLUtils.toSQLString(checkResult.getStatementList(), + JdbcConstants.MYSQL); + Assert.assertEquals("UPDATE T_USER" + // + "\nSET FNAME = ?" + // + "\nWHERE T_USER.tenant = 123" + // + "\n\tAND FID = ?", resultSql); + } +}