Skip to content

Commit 8bd0d07

Browse files
committed
addressed the review comments
1 parent 4a1b8a1 commit 8bd0d07

2 files changed

Lines changed: 57 additions & 9 deletions

File tree

hive-agent/src/main/java/org/apache/ranger/services/hive/client/JdbcUrlValidator.java

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.slf4j.LoggerFactory;
2323

2424
import java.net.URLDecoder;
25+
import java.nio.charset.StandardCharsets;
2526
import java.util.Arrays;
2627
import java.util.Collections;
2728
import java.util.HashSet;
@@ -34,6 +35,7 @@ public final class JdbcUrlValidator {
3435
"socketfactory", "socketfactoryarg", "sslfactory", "sslfactoryarg",
3536
"sslhostnameverifier", "authenticationpluginclassname", "loggerclassname",
3637
"kerberosservername", "gssdelegatecred", "sslpasswordcallback")));
38+
private static final String[] DANGEROUS_PATTERNS = {"socketfactory", "sslfactory", "autodeserialize"};
3739

3840
private JdbcUrlValidator() {
3941
}
@@ -46,10 +48,7 @@ public static void validate(String jdbcUrl) throws HadoopException {
4648
throw e;
4749
}
4850
String trimmed = jdbcUrl.trim();
49-
int queryStart = trimmed.indexOf('?');
50-
if (queryStart == -1) {
51-
queryStart = trimmed.indexOf(';');
52-
}
51+
int queryStart = findQueryStart(trimmed);
5352
if (queryStart != -1) {
5453
String queryString = trimmed.substring(queryStart + 1);
5554
validateQueryString(queryString, trimmed);
@@ -58,7 +57,7 @@ public static void validate(String jdbcUrl) throws HadoopException {
5857
}
5958

6059
private static void validateQueryString(String queryString, String fullUrl) throws HadoopException {
61-
String[] tokens = queryString.split("[&;]");
60+
String[] tokens = queryString.split("[&;?]");
6261
for (String token : tokens) {
6362
if (token.trim().isEmpty()) {
6463
continue;
@@ -67,7 +66,7 @@ private static void validateQueryString(String queryString, String fullUrl) thro
6766
String paramName = (eqIdx >= 0 ? token.substring(0, eqIdx) : token).trim();
6867
String decodedParamName = paramName;
6968
try {
70-
decodedParamName = URLDecoder.decode(paramName, "UTF-8");
69+
decodedParamName = URLDecoder.decode(paramName, StandardCharsets.UTF_8);
7170
} catch (Exception e) {
7271
LOG.warn("Failed to decode parameter name: {}", paramName);
7372
}
@@ -76,8 +75,7 @@ private static void validateQueryString(String queryString, String fullUrl) thro
7675
if (BLOCKED_PARAMS.contains(normalized)) {
7776
logAndThrow("blocked parameter", normalized, paramName, fullUrl);
7877
}
79-
String[] dangerPatterns = {"socketfactory", "sslfactory", "autodeserialize"};
80-
for (String danger : dangerPatterns) {
78+
for (String danger : DANGEROUS_PATTERNS) {
8179
if (normalized.contains(danger)) {
8280
logAndThrow("dangerous pattern '" + danger + "'", normalized, paramName, fullUrl);
8381
}
@@ -94,7 +92,21 @@ static String sanitizeForLog(String url) {
9492
if (url == null) {
9593
return "<null>";
9694
}
97-
return url.replaceAll("[?;].*", "?<params_redacted>");
95+
int idx = findQueryStart(url);
96+
return idx >= 0 ? url.substring(0, idx) + "?<params_redacted>" : url;
97+
}
98+
99+
private static int findQueryStart(String url) {
100+
int qIdx = url.indexOf('?');
101+
int sIdx = url.indexOf(';');
102+
if (qIdx >= 0 && sIdx >= 0) {
103+
return Math.min(qIdx, sIdx);
104+
} else if (qIdx >= 0) {
105+
return qIdx;
106+
} else if (sIdx >= 0) {
107+
return sIdx;
108+
}
109+
return -1;
98110
}
99111

100112
private static void logAndThrow(String reason, String normalized, String originalParam, String fullUrl) {

hive-agent/src/test/java/org/apache/ranger/services/hive/client/JdbcUrlValidatorTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,42 @@ public void testSanitizeForLogWithMixedSeparators() {
347347
}
348348
}
349349

350+
@Nested
351+
@DisplayName("Mixed Parameter Delimiters")
352+
class MixedDelimiters {
353+
@Test
354+
@DisplayName("Blocks dangerous param in semicolon when ? appears later")
355+
void blocksSemicolonBeforeQuestion() {
356+
String url = "jdbc:hive2://host:10000/db;socketFactory=evil?user=test";
357+
HadoopException ex = assertThrows(HadoopException.class, () -> JdbcUrlValidator.validate(url));
358+
assertTrue(ex.getMessage().contains("socketFactory"));
359+
}
360+
361+
@Test
362+
@DisplayName("Blocks dangerous param in question mark when ; appears later")
363+
void blocksQuestionBeforeSemicolon() {
364+
String url = "jdbc:hive2://host:10000/db?socketFactory=evil;user=test";
365+
HadoopException ex = assertThrows(HadoopException.class, () -> JdbcUrlValidator.validate(url));
366+
assertTrue(ex.getMessage().contains("socketFactory"));
367+
}
368+
369+
@Test
370+
@DisplayName("Handles semicolon-only Hive URLs")
371+
void handlesSemicolonOnly() {
372+
String url = "jdbc:hive2://host:10000/db;socketFactory=evil";
373+
HadoopException ex = assertThrows(HadoopException.class, () -> JdbcUrlValidator.validate(url));
374+
assertTrue(ex.getMessage().contains("socketFactory"));
375+
}
376+
377+
@Test
378+
@DisplayName("Handles question-only URLs")
379+
void handlesQuestionOnly() {
380+
String url = "jdbc:hive2://host:10000/db?socketFactory=evil";
381+
HadoopException ex = assertThrows(HadoopException.class, () -> JdbcUrlValidator.validate(url));
382+
assertTrue(ex.getMessage().contains("socketFactory"));
383+
}
384+
}
385+
350386
@Nested
351387
@DisplayName("Integration Tests")
352388
class IntegrationTests {

0 commit comments

Comments
 (0)