Skip to content

Commit fcbdc96

Browse files
idodeclareVladimir Kotal
authored andcommitted
Also validate canonicalRoot when deserializing Configuration
1 parent c34ee2e commit fcbdc96

File tree

4 files changed

+147
-5
lines changed

4 files changed

+147
-5
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2019, Chris Fraire <[email protected]>.
22+
*/
23+
24+
package org.opengrok.indexer.configuration;
25+
26+
import java.io.File;
27+
28+
/**
29+
* Represents a validator of a --canonicalRoot value.
30+
*/
31+
public class CanonicalRootValidator {
32+
33+
/**
34+
* Validates the specified setting, returning an error message if validation
35+
* fails.
36+
* @return a defined instance if not valid or {@code null} otherwise
37+
*/
38+
public static String validate(String setting, String elementDescription) {
39+
// Test that the value ends with the system separator.
40+
if (!setting.endsWith(File.separator)) {
41+
return elementDescription + " must end with a separator";
42+
}
43+
// Test that the value is not like a Windows root (e.g. C:\ or Z:/).
44+
if (setting.matches("\\w:(?:[/\\\\]*)")) {
45+
return elementDescription + " cannot be a root directory";
46+
}
47+
// Test that some character other than separators is in the value.
48+
if (!setting.matches(".*[^/\\\\].*")) {
49+
return elementDescription + " cannot be the root directory";
50+
}
51+
52+
/*
53+
* There is no need to validate that the caller has not specified e.g.
54+
* "/./" (i.e. an alias to the root "/") because --canonicalRoot values
55+
* are matched via string comparison against true canonical values got
56+
* via File.getCanonicalPath(). An alias like "/./" is therefore a
57+
* never-matching value and hence inactive.
58+
*/
59+
return null;
60+
}
61+
62+
/** Private to enforce static. */
63+
private CanonicalRootValidator() {
64+
65+
}
66+
}

opengrok-indexer/src/main/java/org/opengrok/indexer/configuration/Configuration.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353
import java.util.logging.Logger;
5454
import java.util.regex.Pattern;
5555
import java.util.regex.PatternSyntaxException;
56+
import java.util.stream.Collectors;
57+
5658
import org.opengrok.indexer.authorization.AuthControlFlag;
5759
import org.opengrok.indexer.authorization.AuthorizationStack;
5860
import org.opengrok.indexer.history.RepositoryInfo;
@@ -1359,6 +1361,22 @@ public boolean test(Group g) {
13591361
}
13601362
conf.setGroups(copy);
13611363

1364+
/*
1365+
* Validate any defined canonicalRoot entries, and only include where
1366+
* validation succeeds.
1367+
*/
1368+
if (conf.canonicalRoots != null) {
1369+
conf.canonicalRoots = conf.canonicalRoots.stream().filter(s -> {
1370+
String problem = CanonicalRootValidator.validate(s, "canonicalRoot element");
1371+
if (problem == null) {
1372+
return true;
1373+
} else {
1374+
LOGGER.warning(problem);
1375+
return false;
1376+
}
1377+
}).collect(Collectors.toCollection(HashSet::new));
1378+
}
1379+
13621380
return conf;
13631381
}
13641382
}

opengrok-indexer/src/main/java/org/opengrok/indexer/index/Indexer.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
import org.opengrok.indexer.analysis.AnalyzerGuru;
5454
import org.opengrok.indexer.analysis.AnalyzerGuruHelp;
5555
import org.opengrok.indexer.analysis.Ctags;
56+
import org.opengrok.indexer.configuration.CanonicalRootValidator;
5657
import org.opengrok.indexer.configuration.Configuration;
5758
import org.opengrok.indexer.configuration.ConfigurationHelp;
5859
import org.opengrok.indexer.configuration.LuceneLockName;
@@ -494,11 +495,9 @@ public static String[] parseOptions(String[] argv) throws ParseException {
494495
"canonical root must end with a file separator. For security, a canonical",
495496
"root cannot be the root directory. Option may be repeated.").Do(v -> {
496497
String root = (String) v;
497-
if (!root.endsWith("/") && !root.endsWith("\\")) {
498-
die("--canonicalRoot must end with a separator");
499-
}
500-
if (root.equals("/") || root.equals("\\")) {
501-
die("--canonicalRoot cannot be the root directory");
498+
String problem = CanonicalRootValidator.validate(root, "--canonicalRoot");
499+
if (problem != null) {
500+
die(problem);
502501
}
503502
canonicalRoots.add(root);
504503
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* CDDL HEADER START
3+
*
4+
* The contents of this file are subject to the terms of the
5+
* Common Development and Distribution License (the "License").
6+
* You may not use this file except in compliance with the License.
7+
*
8+
* See LICENSE.txt included in this distribution for the specific
9+
* language governing permissions and limitations under the License.
10+
*
11+
* When distributing Covered Code, include this CDDL HEADER in each
12+
* file and include the License file at LICENSE.txt.
13+
* If applicable, add the following below this CDDL HEADER, with the
14+
* fields enclosed by brackets "[]" replaced with your own identifying
15+
* information: Portions Copyright [yyyy] [name of copyright owner]
16+
*
17+
* CDDL HEADER END
18+
*/
19+
20+
/*
21+
* Copyright (c) 2019, Chris Fraire <[email protected]>.
22+
*/
23+
24+
package org.opengrok.indexer.configuration;
25+
26+
import static org.junit.Assert.assertEquals;
27+
import static org.junit.Assert.assertNull;
28+
29+
import org.junit.Test;
30+
31+
import java.io.File;
32+
33+
public class CanonicalRootValidatorTest {
34+
35+
@Test
36+
public void testRejectUnseparated() {
37+
assertEquals("test value must end with a separator",
38+
CanonicalRootValidator.validate("test", "test value"));
39+
}
40+
41+
@Test
42+
public void testRejectRoot() {
43+
assertEquals("should reject root", "test value cannot be the root directory",
44+
CanonicalRootValidator.validate("/", "test value"));
45+
}
46+
47+
@Test
48+
public void testRejectWindowsRoot() {
49+
assertEquals("should reject Windows root", "--canonicalRoot cannot be a root directory",
50+
CanonicalRootValidator.validate("C:" + File.separator, "--canonicalRoot"));
51+
}
52+
53+
@Test
54+
public void testSlashVar() {
55+
assertNull("should allow /var/",
56+
CanonicalRootValidator.validate(File.separator + "var" + File.separator,
57+
"--canonicalRoot"));
58+
}
59+
}

0 commit comments

Comments
 (0)