Skip to content

Commit fa1632d

Browse files
Validate firewall and routed rule protocols against the list too
The firewall (port forwarding, static NAT, firewall), IPv6 firewall and routing firewall rule checks test the protocol against the provider's supported protocols with the same substring test, so "cp" or "dp,ic" passed them as well. Add NetUtils.isProtocolInList(), which matches a whole entry of the comma-separated list in any case, trimming the entries since some providers list them with a space after the comma ("tcp,udp, icmp, all"), and use it for these checks and the network ACL one. Signed-off-by: Brad House <bhouse@nexthop.ai>
1 parent c9c49d8 commit fa1632d

6 files changed

Lines changed: 38 additions & 5 deletions

File tree

‎server/src/main/java/com/cloud/network/Ipv6ServiceImpl.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ public FirewallRule createIpv6FirewallRule(CreateIpv6FirewallRuleCmd cmd) throws
583583
supportedProtocols = caps.get(Network.Capability.SupportedProtocols).toLowerCase();
584584
}
585585

586-
if (!supportedProtocols.contains(protocol.toLowerCase())) {
586+
if (!NetUtils.isProtocolInList(supportedProtocols, protocol)) {
587587
throw new InvalidParameterValueException(String.format("Protocol %s is not supported in zone", protocol));
588588
} else if (!supportedTrafficTypes.contains(trafficType.toString().toLowerCase())) {
589589
throw new InvalidParameterValueException(String.format("Traffic Type %s is currently supported by Firewall in network %s", trafficType, network));

‎server/src/main/java/com/cloud/network/firewall/FirewallManagerImpl.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ public void validateFirewallRule(Account caller, IPAddressVO ipAddress, Integer
603603
supportedProtocols = caps.get(Capability.SupportedProtocols).toLowerCase();
604604
}
605605

606-
if (!supportedProtocols.contains(proto.toLowerCase())) {
606+
if (!NetUtils.isProtocolInList(supportedProtocols, proto)) {
607607
throw new InvalidParameterValueException("Protocol " + proto + " is not supported in zone " + network.getDataCenterId());
608608
} else if (proto.equalsIgnoreCase(NetUtils.ICMP_PROTO) && purpose != Purpose.Firewall) {
609609
throw new InvalidParameterValueException("Protocol " + proto + " is currently supported only for rules with purpose " + Purpose.Firewall);

‎server/src/main/java/com/cloud/network/vpc/NetworkACLServiceImpl.java‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.cloud.network.vpc;
1818

1919
import java.util.ArrayList;
20-
import java.util.Arrays;
2120
import java.util.Collections;
2221
import java.util.Comparator;
2322
import java.util.List;
@@ -621,7 +620,7 @@ protected void validateProtocol(NetworkACLItemVO networkACLItemVO) {
621620
}
622621
} else {
623622
// one of the names, not just part of the string: "cp" or "dp,ic" must not pass
624-
if (!Arrays.asList(supportedProtocolsForAclRules.split(",")).contains(protocol.toLowerCase(Locale.ROOT))) {
623+
if (!NetUtils.isProtocolInList(supportedProtocolsForAclRules, protocol)) {
625624
throw new InvalidParameterValueException(String.format("Invalid protocol [%s]. Expected one of: [%s]", protocol, supportedProtocolsForAclRules));
626625
}
627626
}

‎server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ public FirewallRule createRoutingFirewallRule(CreateRoutingFirewallRuleCmd creat
893893
supportedProtocols = caps.get(Network.Capability.SupportedProtocols).toLowerCase();
894894
}
895895

896-
if (!supportedProtocols.contains(protocol.toLowerCase())) {
896+
if (!NetUtils.isProtocolInList(supportedProtocols, protocol)) {
897897
throw new InvalidParameterValueException(String.format("Protocol %s is not supported in zone", protocol));
898898
} else if (!supportedTrafficTypes.contains(trafficType.toString().toLowerCase())) {
899899
throw new InvalidParameterValueException("Traffic Type " + trafficType + " is currently supported by Firewall in network " + networkId);

‎utils/src/main/java/com/cloud/utils/net/NetUtils.java‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.Formatter;
3939
import java.util.Iterator;
4040
import java.util.List;
41+
import java.util.Locale;
4142
import java.util.Random;
4243
import java.util.Set;
4344
import java.util.SortedSet;
@@ -991,6 +992,24 @@ public static long getCidrSize(final String netmask) {
991992
return MAX_CIDR - count;
992993
}
993994

995+
/**
996+
* Whether the protocol is one of the comma-separated protocols, as a whole entry and in any case.
997+
* The lists come from provider capabilities, some of which have spaces after their commas; the
998+
* protocol itself is taken as given.
999+
*/
1000+
public static boolean isProtocolInList(final String protocols, final String protocol) {
1001+
if (protocols == null || protocol == null) {
1002+
return false;
1003+
}
1004+
final String p = protocol.toLowerCase(Locale.ROOT);
1005+
for (final String entry : protocols.split(",")) {
1006+
if (entry.trim().toLowerCase(Locale.ROOT).equals(p)) {
1007+
return true;
1008+
}
1009+
}
1010+
return false;
1011+
}
1012+
9941013
public static boolean isValidPort(final int p) {
9951014
return !(p > PORT_RANGE_MAX || p < PORT_RANGE_MIN);
9961015
}

‎utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,4 +955,19 @@ public void testVpnIpRange() {
955955
String cidr = NetUtils.transformCidr(startIp + "/" + cidrSize);
956956
Assert.assertEquals("10.1.2.0/28", cidr);
957957
}
958+
959+
@Test
960+
public void testIsProtocolInList() {
961+
assertTrue(NetUtils.isProtocolInList("tcp,udp,icmp,all", "tcp"));
962+
assertTrue(NetUtils.isProtocolInList("tcp,udp,icmp,all", "ICMP"));
963+
// provider capabilities with a space after the comma
964+
assertTrue(NetUtils.isProtocolInList("tcp,udp,icmp, all", "all"));
965+
assertTrue(NetUtils.isProtocolInList("tcp, udp", "udp"));
966+
// part of an entry, or of the list, is not an entry
967+
for (String protocol : new String[] {"cp", "t", "dp,ic", ",", "tcp,udp", "", "proxy", " all"}) {
968+
assertFalse(protocol, NetUtils.isProtocolInList("tcp,udp,icmp,all,tcp-proxy", protocol));
969+
}
970+
assertFalse(NetUtils.isProtocolInList(null, "tcp"));
971+
assertFalse(NetUtils.isProtocolInList("tcp", null));
972+
}
958973
}

0 commit comments

Comments
 (0)