You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2022/06/19 14:20:06 UTC
[doris] branch master updated: [fix](auth) Authentication exception when the name of database or table contains an underscore in grant statement. (#10213)
This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new f728fd4933 [fix](auth) Authentication exception when the name of database or table contains an underscore in grant statement. (#10213)
f728fd4933 is described below
commit f728fd49330e08a2fa23e6018b4e4f8d4a4fcc9d
Author: Ashin Gau <As...@users.noreply.github.com>
AuthorDate: Sun Jun 19 22:20:01 2022 +0800
[fix](auth) Authentication exception when the name of database or table contains an underscore in grant statement. (#10213)
---
.../org/apache/doris/common/PatternMatcher.java | 61 ++++++++++++++++++----
.../apache/doris/mysql/privilege/DbPrivEntry.java | 5 +-
.../doris/mysql/privilege/GlobalPrivEntry.java | 2 +-
.../apache/doris/mysql/privilege/PrivBitSet.java | 2 +-
.../doris/mysql/privilege/TablePrivEntry.java | 10 ++--
.../doris/mysql/privilege/PrivEntryTest.java | 48 +++++++++++++++++
6 files changed, 109 insertions(+), 19 deletions(-)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/PatternMatcher.java b/fe/fe-core/src/main/java/org/apache/doris/common/PatternMatcher.java
index a9eddc1b5e..5b5f3f0903 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/PatternMatcher.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/PatternMatcher.java
@@ -20,27 +20,70 @@ package org.apache.doris.common;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
+import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;
// Wrap for Java pattern and matcher
public class PatternMatcher {
+ public static final PatternMatcher MATCH_ANY = new PatternMatcher(Pattern.compile(".*"));
private Pattern pattern;
+ // The name of 'user', 'database' and 'table' don't support complex matching in grant statement.
+ // Only using '%' to match any string. In other cases, it's string case-sensitive(or not) equivalent matching,
+ // so using the origin string to determine whether it matches.
+ private String originString;
+ private boolean caseSensitive;
private static final Set<Character> FORBIDDEN_CHARS = Sets.newHashSet('<', '(', '[', '{', '^', '=',
'$', '!', '|', ']', '}', ')',
'?', '*', '+', '>', '@');
+ public PatternMatcher(Pattern pattern) {
+ this.pattern = pattern;
+ }
+
+ public PatternMatcher(String originString, boolean caseSensitive) {
+ this.originString = caseSensitive ? originString : originString.toLowerCase(Locale.ROOT);
+ this.caseSensitive = caseSensitive;
+ }
+
public boolean match(String candidate) {
- if (pattern == null || candidate == null) {
- // No pattern, how can I explain this? Return false now.
- // No candidate, return false.
+ if (candidate == null) {
return false;
}
- if (pattern.matcher(candidate).matches()) {
- return true;
+ if (pattern != null) {
+ return pattern.matcher(candidate).matches();
+ }
+ if (caseSensitive) {
+ return candidate.equals(originString);
+ } else {
+ return candidate.toLowerCase(Locale.ROOT).equals(originString);
+ }
+ }
+
+ /**
+ * Use in grant statement to support case-sensitive(or not) equivalent matching.
+ *
+ * @param originString The string to match.
+ * @param caseSensitive Case sensitive.
+ */
+ public static PatternMatcher createFlatPattern(String originString, boolean caseSensitive) {
+ return createFlatPattern(originString, caseSensitive, false);
+ }
+
+ /**
+ * Use in grant statement to support case-sensitive(or not) equivalent matching, or arbitrary matching.
+ *
+ * @param originString The string to match. If matchAny = true, this parameter has no effect.
+ * @param caseSensitive Case sensitive.
+ * @param matchAny match any string.
+ */
+ public static PatternMatcher createFlatPattern(
+ String originString, boolean caseSensitive, boolean matchAny) {
+ if (matchAny) {
+ return MATCH_ANY;
}
- return false;
+ return new PatternMatcher(originString, caseSensitive);
}
/*
@@ -149,7 +192,7 @@ public class PatternMatcher {
public static PatternMatcher createMysqlPattern(String mysqlPattern, boolean caseSensitive)
throws AnalysisException {
- PatternMatcher matcher = new PatternMatcher();
+ PatternMatcher matcher;
// Match nothing
String newMysqlPattern = Strings.nullToEmpty(mysqlPattern);
@@ -157,9 +200,9 @@ public class PatternMatcher {
String javaPattern = convertMysqlPattern(newMysqlPattern);
try {
if (caseSensitive) {
- matcher.pattern = Pattern.compile(javaPattern);
+ matcher = new PatternMatcher(Pattern.compile(javaPattern));
} else {
- matcher.pattern = Pattern.compile(javaPattern, Pattern.CASE_INSENSITIVE);
+ matcher = new PatternMatcher(Pattern.compile(javaPattern, Pattern.CASE_INSENSITIVE));
}
} catch (Exception e) {
throw new AnalysisException("Bad pattern in SQL: " + e.getMessage());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivEntry.java
index 06a37b1942..a8f1337df7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/DbPrivEntry.java
@@ -54,7 +54,7 @@ public class DbPrivEntry extends PrivEntry {
PatternMatcher dbPattern = createDbPatternMatcher(db);
- PatternMatcher userPattern = PatternMatcher.createMysqlPattern(user, CaseSensibility.USER.getCaseSensibility());
+ PatternMatcher userPattern = PatternMatcher.createFlatPattern(user, CaseSensibility.USER.getCaseSensibility());
if (privs.containsNodePriv() || privs.containsResourcePriv()) {
throw new AnalysisException("Db privilege can not contains global or resource privileges: " + privs);
@@ -70,8 +70,7 @@ public class DbPrivEntry extends PrivEntry {
dbCaseSensibility = false;
}
- PatternMatcher dbPattern = PatternMatcher.createMysqlPattern(db.equals(ANY_DB) ? "%" : db, dbCaseSensibility);
- return dbPattern;
+ return PatternMatcher.createFlatPattern(db, dbCaseSensibility, db.equals(ANY_DB));
}
public PatternMatcher getDbPattern() {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivEntry.java
index ba74d280b2..6444d6b8e2 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/GlobalPrivEntry.java
@@ -53,7 +53,7 @@ public class GlobalPrivEntry extends PrivEntry {
public static GlobalPrivEntry create(String host, String user, boolean isDomain, byte[] password, PrivBitSet privs)
throws AnalysisException {
PatternMatcher hostPattern = PatternMatcher.createMysqlPattern(host, CaseSensibility.HOST.getCaseSensibility());
- PatternMatcher userPattern = PatternMatcher.createMysqlPattern(user, CaseSensibility.USER.getCaseSensibility());
+ PatternMatcher userPattern = PatternMatcher.createFlatPattern(user, CaseSensibility.USER.getCaseSensibility());
return new GlobalPrivEntry(hostPattern, host, userPattern, user, isDomain, password, privs);
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivBitSet.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivBitSet.java
index 58fd169c59..9b47c69ebd 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivBitSet.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/PrivBitSet.java
@@ -47,7 +47,7 @@ public class PrivBitSet implements Writable {
public void unset(int index) {
Preconditions.checkState(index < PaloPrivilege.privileges.length, index);
- set &= ~set;
+ set &= 1 << index;
}
public boolean get(int index) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
index 82752c7ba3..c85a1f2912 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/TablePrivEntry.java
@@ -50,12 +50,12 @@ public class TablePrivEntry extends DbPrivEntry {
public static TablePrivEntry create(String host, String db, String user, String tbl, boolean isDomain,
PrivBitSet privs) throws AnalysisException {
PatternMatcher hostPattern = PatternMatcher.createMysqlPattern(host, CaseSensibility.HOST.getCaseSensibility());
- PatternMatcher dbPattern = PatternMatcher.createMysqlPattern(db.equals(ANY_DB) ? "%" : db,
- CaseSensibility.DATABASE.getCaseSensibility());
- PatternMatcher userPattern = PatternMatcher.createMysqlPattern(user, CaseSensibility.USER.getCaseSensibility());
+ PatternMatcher dbPattern = PatternMatcher.createFlatPattern(
+ db, CaseSensibility.DATABASE.getCaseSensibility(), db.equals(ANY_DB));
+ PatternMatcher userPattern = PatternMatcher.createFlatPattern(user, CaseSensibility.USER.getCaseSensibility());
- PatternMatcher tblPattern = PatternMatcher.createMysqlPattern(tbl.equals(ANY_TBL) ? "%" : tbl,
- CaseSensibility.TABLE.getCaseSensibility());
+ PatternMatcher tblPattern = PatternMatcher.createFlatPattern(
+ tbl, CaseSensibility.TABLE.getCaseSensibility(), tbl.equals(ANY_TBL));
if (privs.containsNodePriv() || privs.containsResourcePriv()) {
throw new AnalysisException("Table privilege can not contains global or resource privileges: " + privs);
diff --git a/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/PrivEntryTest.java b/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/PrivEntryTest.java
new file mode 100644
index 0000000000..71f6990191
--- /dev/null
+++ b/fe/fe-core/src/test/java/org/apache/doris/mysql/privilege/PrivEntryTest.java
@@ -0,0 +1,48 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you 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.apache.doris.mysql.privilege;
+
+import org.apache.doris.analysis.UserIdentity;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PrivEntryTest {
+ @Test
+ public void testNameWithUnderscores() throws Exception {
+ TablePrivEntry tablePrivEntry = TablePrivEntry.create(
+ "127.%", "db_db1", "user1", "tbl_tbl1", false,
+ PrivBitSet.of(PaloPrivilege.SELECT_PRIV, PaloPrivilege.DROP_PRIV));
+ // pattern match
+ Assert.assertFalse(tablePrivEntry.getDbPattern().match("db-db1"));
+ Assert.assertFalse(tablePrivEntry.getTblPattern().match("tbl-tbl1"));
+ // create TablePrivTable
+ TablePrivTable tablePrivTable = new TablePrivTable();
+ tablePrivTable.addEntry(tablePrivEntry, false, false);
+ UserIdentity userIdentity = new UserIdentity("user1", "127.%", false);
+ userIdentity.setIsAnalyzed();
+
+ PrivBitSet privs1 = PrivBitSet.of();
+ tablePrivTable.getPrivs(userIdentity, "db#db1", "tbl#tbl1", privs1);
+ Assert.assertFalse(PaloPrivilege.satisfy(privs1, PrivPredicate.DROP));
+
+ PrivBitSet privs2 = PrivBitSet.of();
+ tablePrivTable.getPrivs(userIdentity, "db_db1", "tbl_tbl1", privs2);
+ Assert.assertTrue(PaloPrivilege.satisfy(privs2, PrivPredicate.DROP));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org