Skip to content

Commit cf00060

Browse files
authored
Handle validation for Composite URIs without parens (#2004)
Parentheses are optional when creating composite and nested URIs so this updates the validation to handle missing parens as well. Follow on to #1847
1 parent 103962e commit cf00060

3 files changed

Lines changed: 92 additions & 12 deletions

File tree

activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -614,26 +614,39 @@ private static void validateAllowedUrl(String uriString) throws URISyntaxExcepti
614614
// Validate the URI does not contain a denied transport scheme
615615
private static void validateAllowedUri(URI uri, int depth) throws URISyntaxException {
616616
// Don't allow more than 5 nested URIs to prevent blowing the stack
617-
// If we are greater than 4 then this is the 5th level of composite
618-
if (depth > 4) {
617+
if (depth > 5) {
619618
throw new IllegalArgumentException("URI can't contain more than 5 nested composite URIs");
620619
}
621620

622621
// First check the main URI scheme
623622
validateAllowedScheme(uri.getScheme());
624623

625-
// If composite, iterate and check each of the composite URIs
626-
if (URISupport.isCompositeURI(uri)) {
627-
URISupport.CompositeData data = URISupport.parseComposite(uri);
624+
// We need to check if the URI is composite and/or contains nested URIs
625+
// The utility method URISupport#isCompositeURI is not good enough here
626+
// because it misses if there are no parentheses and also is primarily meant
627+
// for checking comma separated URIs and not nested URIs.
628+
//
629+
// The best way to handle all cases is to use the same logic that the transports
630+
// use to process the URIs and that is to simply attempt to parse it and check each
631+
// of the parsed components. This wll correctly handle the case when there
632+
// are parentheses and also when the parentheses are skipped.
633+
final URISupport.CompositeData data;
634+
try {
635+
data = URISupport.parseComposite(uri);
636+
} catch (URISyntaxException e) {
637+
// If this is not a valid URI then we can stop checking
638+
// This can happen when parsing a nested URI and at the last portion
639+
return;
640+
}
641+
642+
if (data.getComponents() != null) {
628643
depth++;
629644
for (URI component : data.getComponents()) {
630-
// Each URI could be a nested composite URI so call validateAllowedUri()
631-
// to validate it. This check if composite first so we don't add to
632-
// the recursive stack depth if there's a lot of URIs that are not composite
633-
if (URISupport.isCompositeURI(component)) {
645+
// Each URI could be a nested and/or composite URI so call validateAllowedUri()
646+
// to validate it. If the scheme is null then the original URI is not composite
647+
// or nested so we can skip the check, and we are finished.
648+
if (component.getScheme() != null) {
634649
validateAllowedUri(component, depth);
635-
} else {
636-
validateAllowedScheme(component.getScheme());
637650
}
638651
}
639652
}

activemq-unit-tests/src/test/java/org/apache/activemq/broker/jmx/MBeanTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,6 +2084,14 @@ protected void testAddTransportConnectorBlockedBrokerView(String scheme) throws
20842084
assertEquals("Transport scheme '" + scheme + "' is not allowed", e.getMessage());
20852085
}
20862086

2087+
try {
2088+
// verify any composite URI is blocked as well without parens
2089+
brokerView.addConnector("static:tcp://0.0.0.0:0," + scheme + "://" + brokerName);
2090+
fail("Should have failed trying to add connector with scheme: " + scheme);
2091+
} catch (IllegalArgumentException e) {
2092+
assertEquals("Transport scheme '" + scheme + "' is not allowed", e.getMessage());
2093+
}
2094+
20872095
try {
20882096
// verify nested composite URI is blocked
20892097
brokerView.addConnector("static:(static:(static:(" + scheme + "://localhost)))");
@@ -2106,6 +2114,15 @@ public void testNestedAddTransportConnector() throws Exception {
21062114
} catch (IllegalArgumentException e) {
21072115
assertEquals("URI can't contain more than 5 nested composite URIs", e.getMessage());
21082116
}
2117+
2118+
try {
2119+
// verify nested composite URI with more than 5 levels is blocked without parens
2120+
brokerView.addConnector(
2121+
"static:static:static:static:static:static:tcp://localhost:0");
2122+
fail("Should have failed trying to add vm connector bridge");
2123+
} catch (IllegalArgumentException e) {
2124+
assertEquals("URI can't contain more than 5 nested composite URIs", e.getMessage());
2125+
}
21092126
}
21102127

21112128
}

activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxCreateNCTest.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,31 @@ public void testBridgeRegistration() throws Exception {
8282
assertEquals("NC", nc.getName());
8383
}
8484

85+
@Test
86+
public void testTransportSchemeBridgeAllowed() throws Exception {
87+
// Test composite network connector uri
88+
String name = proxy.addNetworkConnector("static:(tcp://localhost,amqp://localhost)");
89+
proxy.removeNetworkConnector(name);
90+
91+
// Test composite with missing parens
92+
name = proxy.addNetworkConnector("static:amqp://localhost,tcp://127.0.0.1:0");
93+
proxy.removeNetworkConnector(name);
94+
95+
// verify direct connector as well
96+
name = proxy.addNetworkConnector("static:stomp://localhost");
97+
proxy.removeNetworkConnector(name);
98+
99+
// verify nested composite URI
100+
name = proxy.addNetworkConnector(
101+
"static:(static:(static:(tcp+ssl://localhost:0,auto+nio+ssl://localhost)))");
102+
proxy.removeNetworkConnector(name);
103+
104+
// verify nested composite URI is not blocked when not using parens
105+
name = proxy.addNetworkConnector(
106+
"static:static:static:123://localhost:0,auto+nio+ssl://localhost");
107+
proxy.removeNetworkConnector(name);
108+
}
109+
85110
@Test
86111
public void testTransportSchemeBridgeBlocked() throws Exception {
87112
for (String deniedScheme : DENIED_TRANSPORT_SCHEMES) {
@@ -99,6 +124,14 @@ protected void testTransportSchemeBridgeBlocked(String scheme) throws Exception
99124
assertEquals("Transport scheme '" + scheme + "' is not allowed", e.getMessage());
100125
}
101126

127+
// Test composite with missing parens
128+
try {
129+
proxy.addNetworkConnector("static:" + scheme + "://localhost,tcp://127.0.0.1:0");
130+
fail("Should have failed trying to add connector bridge with scheme: " + scheme);
131+
} catch (IllegalArgumentException e) {
132+
assertEquals("Transport scheme '" + scheme + "' is not allowed", e.getMessage());
133+
}
134+
102135
// verify direct connector as well
103136
try {
104137
proxy.addNetworkConnector(scheme + "://localhost");
@@ -114,6 +147,14 @@ protected void testTransportSchemeBridgeBlocked(String scheme) throws Exception
114147
} catch (IllegalArgumentException e) {
115148
assertEquals("Transport scheme '" + scheme + "' is not allowed", e.getMessage());
116149
}
150+
151+
try {
152+
// verify nested composite URI is blocked when not using parens
153+
proxy.addNetworkConnector("static:static:static:tcp://localhost:0," + scheme + "://localhost");
154+
fail("Should have failed trying to add connector bridge with scheme: " + scheme);
155+
} catch (IllegalArgumentException e) {
156+
assertEquals("Transport scheme '" + scheme + "' is not allowed", e.getMessage());
157+
}
117158
}
118159

119160
@Test
@@ -124,12 +165,21 @@ public void testAddNetworkConnectorMaxComposite() throws Exception {
124165

125166
try {
126167
// verify nested composite URI with more than 5 levels is blocked. This has 6 nested
127-
// (not including first wrapper url
168+
// (not including first wrapper url)
128169
proxy.addNetworkConnector(
129170
"static:(static:(static:(static:(static:(static:(tcp://localhost:0))))))");
130171
fail("Should have failed trying to add more than 5 connector bridges");
131172
} catch (IllegalArgumentException e) {
132173
assertEquals("URI can't contain more than 5 nested composite URIs", e.getMessage());
133174
}
175+
176+
try {
177+
// verify nested composite URI with more than 5 levels is blocked without parens
178+
proxy.addNetworkConnector(
179+
"static:static:static:static:static:static:tcp://localhost:0");
180+
fail("Should have failed trying to add more than 5 connector bridges");
181+
} catch (IllegalArgumentException e) {
182+
assertEquals("URI can't contain more than 5 nested composite URIs", e.getMessage());
183+
}
134184
}
135185
}

0 commit comments

Comments
 (0)