From 9988c269b259b84c0b8436bad17f88dbc1d706e7 Mon Sep 17 00:00:00 2001 From: Wido den Hollander Date: Thu, 4 Jan 2018 06:26:30 +0100 Subject: [PATCH] CLOUDSTACK-7958: Add configuration for limit to CIDRs for Admin API calls (#2046) * Cleanup and Improve NetUtils This class had many unused methods, inconsistent names and redundant code. This commit cleans up code, renames a few methods and constants. The global/account setting 'api.allowed.source.cidr.list' is set to 0.0.0.0/0,::/0 by default preserve the current behavior and thus allow API calls for accounts from all IPv4 and IPv6 subnets. Users can set it to a comma-separated list of IPv4/IPv6 subnets to restrict API calls for Admin accounts to certain parts of their network(s). This is to improve Security. Should an attacker steal the Access/Secret key of an account he/she still needs to be in a subnet from where accounts are allowed to perform API calls. This is a good security measure for APIs which are connected to the public internet. Signed-off-by: Wido den Hollander --- .../consoleproxy/ConsoleProxyResource.java | 4 +- .../cloudstack/api/ApiServerService.java | 2 +- .../firewall/CreateEgressFirewallRuleCmd.java | 6 +- .../user/firewall/CreateFirewallRuleCmd.java | 4 +- .../firewall/CreatePortForwardingRuleCmd.java | 2 +- .../AssignToLoadBalancerRuleCmd.java | 2 +- .../user/network/CreateNetworkACLCmd.java | 2 +- .../api/command/user/vm/AddIpToVmNicCmd.java | 2 +- .../api/command/user/vm/UpdateVmNicIpCmd.java | 2 +- .../config/ApiServiceConfiguration.java | 7 +- .../cloud/network/HAProxyConfigurator.java | 10 +- .../alert/snmp/SnmpTrapAppender.java | 2 +- .../syslog/AlertsSyslogAppender.java | 2 +- .../LibvirtGetVmIpAddressCommandWrapper.java | 4 +- .../resources/helpers/Ovm3Configuration.java | 2 +- .../CitrixGetVmIpAddressCommandWrapper.java | 2 +- .../network/resource/NetscalerResource.java | 4 +- server/src/com/cloud/api/ApiServer.java | 62 +++-- server/src/com/cloud/api/ApiServlet.java | 33 ++- .../ConfigurationManagerImpl.java | 58 ++-- .../consoleproxy/ConsoleProxyManagerImpl.java | 2 +- .../com/cloud/network/NetworkModelImpl.java | 10 +- .../com/cloud/network/NetworkServiceImpl.java | 18 +- .../network/StorageNetworkManagerImpl.java | 6 +- .../network/firewall/FirewallManagerImpl.java | 4 +- .../VirtualNetworkApplianceManagerImpl.java | 4 +- .../security/SecurityGroupManagerImpl.java | 2 +- .../network/vpc/NetworkACLServiceImpl.java | 2 +- .../com/cloud/network/vpc/VpcManagerImpl.java | 4 +- .../vpn/RemoteAccessVpnManagerImpl.java | 4 +- .../network/vpn/Site2SiteVpnManagerImpl.java | 6 +- server/src/com/cloud/test/PodZoneConfig.java | 4 +- .../com/cloud/user/AccountManagerImpl.java | 28 +- .../src/com/cloud/vm/UserVmManagerImpl.java | 4 +- server/test/com/cloud/api/ApiServletTest.java | 24 +- .../SecondaryStorageManagerImpl.java | 4 +- .../resource/NfsSecondaryStorageResource.java | 4 +- ui/l10n/en.js | 2 +- .../java/com/cloud/utils/net/NetUtils.java | 251 ++++++------------ .../com/cloud/utils/net/NetUtilsTest.java | 114 ++++++-- .../vmware/mo/HypervisorHostHelper.java | 2 +- 41 files changed, 369 insertions(+), 342 deletions(-) diff --git a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java index 86d3bebb38be..b3b17e7d970b 100644 --- a/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java +++ b/agent/src/com/cloud/agent/resource/consoleproxy/ConsoleProxyResource.java @@ -276,12 +276,12 @@ private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String et s_logger.debug("addRouteToInternalIp: destIp is null"); return; } - if (!NetUtils.isValidIp(destIpOrCidr) && !NetUtils.isValidCIDR(destIpOrCidr)) { + if (!NetUtils.isValidIp4(destIpOrCidr) && !NetUtils.isValidIp4Cidr(destIpOrCidr)) { s_logger.warn(" destIp is not a valid ip address or cidr destIp=" + destIpOrCidr); return; } boolean inSameSubnet = false; - if (NetUtils.isValidIp(destIpOrCidr)) { + if (NetUtils.isValidIp4(destIpOrCidr)) { if (eth1ip != null && eth1mask != null) { inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask); } else { diff --git a/api/src/org/apache/cloudstack/api/ApiServerService.java b/api/src/org/apache/cloudstack/api/ApiServerService.java index 2b5768261b55..382b48a5e026 100644 --- a/api/src/org/apache/cloudstack/api/ApiServerService.java +++ b/api/src/org/apache/cloudstack/api/ApiServerService.java @@ -24,7 +24,7 @@ import com.cloud.exception.CloudAuthenticationException; public interface ApiServerService { - public boolean verifyRequest(Map requestParameters, Long userId) throws ServerApiException; + public boolean verifyRequest(Map requestParameters, Long userId, InetAddress remoteAddress) throws ServerApiException; public Long fetchDomainId(String domainUUID); diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java index 1f14abf4a5a8..9299c3ddd2c8 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateEgressFirewallRuleCmd.java @@ -246,10 +246,10 @@ public void create() { String guestCidr = _networkService.getNetwork(getNetworkId()).getCidr(); for (String cidr : getSourceCidrList()) { - if (!NetUtils.isValidCIDR(cidr)) { + if (!NetUtils.isValidIp4Cidr(cidr) && !NetUtils.isValidIp6Cidr(cidr)) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source cidrs formatting error " + cidr); } - if (cidr.equals(NetUtils.ALL_CIDRS)) { + if (cidr.equals(NetUtils.ALL_IP4_CIDRS)) { continue; } if (!NetUtils.isNetworkAWithinNetworkB(cidr, guestCidr)) { @@ -261,7 +261,7 @@ public void create() { //Destination CIDR formatting check. Since it's optional param, no need to set a default as in the case of source. if(destCidrList != null){ for(String cidr : destCidrList){ - if(!NetUtils.isValidCIDR(cidr)) { + if(!NetUtils.isValidIp4Cidr(cidr) && !NetUtils.isValidIp6Cidr(cidr)) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Destination cidrs formatting error" + cidr); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java index 548b81447fe7..fab7d9eef29a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreateFirewallRuleCmd.java @@ -108,7 +108,7 @@ public List getSourceCidrList() { return cidrlist; } else { List oneCidrList = new ArrayList(); - oneCidrList.add(NetUtils.ALL_CIDRS); + oneCidrList.add(NetUtils.ALL_IP4_CIDRS); return oneCidrList; } @@ -242,7 +242,7 @@ public long getDomainId() { public void create() { if (getSourceCidrList() != null) { for (String cidr : getSourceCidrList()) { - if (!NetUtils.isValidCIDR(cidr)) { + if (!NetUtils.isValidIp4Cidr(cidr) && !NetUtils.isValidIp6Cidr(cidr)) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source CIDRs formatting error " + cidr); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java index 69360608df1d..ea0cb00301a0 100644 --- a/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/firewall/CreatePortForwardingRuleCmd.java @@ -348,7 +348,7 @@ public void create() { Ip privateIp = getVmSecondaryIp(); if (privateIp != null) { - if (!NetUtils.isValidIp(privateIp.toString())) { + if (!NetUtils.isValidIp4(privateIp.toString())) { throw new InvalidParameterValueException("Invalid vm ip address"); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java index fdc8a31c59a5..1e7303708014 100644 --- a/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/loadbalancer/AssignToLoadBalancerRuleCmd.java @@ -140,7 +140,7 @@ public Map> getVmIdIpListMap() { } //check wether the given ip is valid ip or not - if (vmIp == null || !NetUtils.isValidIp(vmIp)) { + if (vmIp == null || !NetUtils.isValidIp4(vmIp)) { throw new InvalidParameterValueException("Invalid ip address "+ vmIp +" passed in vmidipmap for " + "vmid " + vmId); } diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java index c8a8f8cae394..4b6a836f32a8 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkACLCmd.java @@ -134,7 +134,7 @@ public List getSourceCidrList() { return cidrlist; } else { List oneCidrList = new ArrayList(); - oneCidrList.add(NetUtils.ALL_CIDRS); + oneCidrList.add(NetUtils.ALL_IP4_CIDRS); return oneCidrList; } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java index 4b805acc396f..41481c8ff54e 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/AddIpToVmNicCmd.java @@ -173,7 +173,7 @@ public void create() throws ResourceAllocationException { NicSecondaryIp result; String secondaryIp = null; if ((ip = getIpaddress()) != null) { - if (!NetUtils.isValidIp(ip)) { + if (!NetUtils.isValidIp4(ip)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Invalid ip address " + ip); } } diff --git a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVmNicIpCmd.java b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVmNicIpCmd.java index c6fbedbf6318..83fe72e70430 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVmNicIpCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vm/UpdateVmNicIpCmd.java @@ -150,7 +150,7 @@ public void execute() throws ResourceUnavailableException, ResourceAllocationExc CallContext.current().setEventDetails("Nic Id: " + getNicId() ); String ip; if ((ip = getIpaddress()) != null) { - if (!NetUtils.isValidIp(ip)) { + if (!NetUtils.isValidIp4(ip)) { throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Invalid ip address " + ip); } } diff --git a/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java b/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java index d5df8c342190..485688a37691 100644 --- a/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java +++ b/api/src/org/apache/cloudstack/config/ApiServiceConfiguration.java @@ -25,7 +25,10 @@ public class ApiServiceConfiguration implements Configurable { "API end point. Can be used by CS components/services deployed remotely, for sending CS API requests", true); public static final ConfigKey DefaultUIPageSize = new ConfigKey("Advanced", Long.class, "default.ui.page.size", "20", "The default pagesize to be used by UI and other clients when making list* API calls", true, ConfigKey.Scope.Global); - + public static final ConfigKey ApiSourceCidrChecksEnabled = new ConfigKey<>("Advanced", Boolean.class, "api.source.cidr.checks.enabled", + "true", "Are the source checks on API calls enabled (true) or not (false)? See api.allowed.source.cidr.list", true, ConfigKey.Scope.Global); + public static final ConfigKey ApiAllowedSourceCidrList = new ConfigKey("Advanced", String.class, "api.allowed.source.cidr.list", + "0.0.0.0/0,::/0", "Comma separated list of IPv4/IPv6 CIDRs from which API calls can be performed. Can be set on Global and Account levels.", true, ConfigKey.Scope.Account); @Override public String getConfigComponentName() { return ApiServiceConfiguration.class.getSimpleName(); @@ -33,7 +36,7 @@ public String getConfigComponentName() { @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {ManagementHostIPAdr, ApiServletPath, DefaultUIPageSize}; + return new ConfigKey[] {ManagementHostIPAdr, ApiServletPath, DefaultUIPageSize, ApiSourceCidrChecksEnabled, ApiAllowedSourceCidrList}; } } diff --git a/core/src/com/cloud/network/HAProxyConfigurator.java b/core/src/com/cloud/network/HAProxyConfigurator.java index 3b5f23faac1c..7bf3bb8ca57f 100644 --- a/core/src/com/cloud/network/HAProxyConfigurator.java +++ b/core/src/com/cloud/network/HAProxyConfigurator.java @@ -94,7 +94,7 @@ public String[] generateConfiguration(final List fwRules) private List getRulesForPool(final String poolName, final List fwRules) { final PortForwardingRuleTO firstRule = fwRules.get(0); final String publicIP = firstRule.getSrcIp(); - final String publicPort = Integer.toString(firstRule.getSrcPortRange()[0]); + final int publicPort = firstRule.getSrcPortRange()[0]; // FIXEME: String algorithm = firstRule.getAlgorithm(); final List result = new ArrayList(); @@ -108,9 +108,7 @@ private List getRulesForPool(final String poolName, final List getRulesForPool(final LoadBalancerTO lbTO, final boolean ke StringBuilder sb = new StringBuilder(); final String poolName = sb.append(lbTO.getSrcIp().replace(".", "_")).append('-').append(lbTO.getSrcPort()).toString(); final String publicIP = lbTO.getSrcIp(); - final String publicPort = Integer.toString(lbTO.getSrcPort()); + final int publicPort = lbTO.getSrcPort(); final String algorithm = lbTO.getAlgorithm(); final List result = new ArrayList(); @@ -544,7 +542,7 @@ private List getRulesForPool(final LoadBalancerTO lbTO, final boolean ke if (stickinessSubRule != null && !destsAvailable) { s_logger.warn("Haproxy stickiness policy for lb rule: " + lbTO.getSrcIp() + ":" + lbTO.getSrcPort() + ": Not Applied, cause: backends are unavailable"); } - if (publicPort.equals(NetUtils.HTTP_PORT) && !keepAliveEnabled || httpbasedStickiness) { + if (publicPort == NetUtils.HTTP_PORT && !keepAliveEnabled || httpbasedStickiness) { sb = new StringBuilder(); sb.append("\t").append("mode http"); result.add(sb.toString()); diff --git a/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapAppender.java b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapAppender.java index 3579e245c181..0c9fcf9f68c3 100644 --- a/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapAppender.java +++ b/plugins/alert-handlers/snmp-alerts/src/org/apache/cloudstack/alert/snmp/SnmpTrapAppender.java @@ -161,7 +161,7 @@ private boolean validateIpAddresses() { if (ipAddress.trim().equalsIgnoreCase("localhost")) { continue; } - if (!NetUtils.isValidIp(ipAddress)) { + if (!NetUtils.isValidIp4(ipAddress)) { return false; } } diff --git a/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java b/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java index 7324c2008827..b73da2fd4219 100644 --- a/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java +++ b/plugins/alert-handlers/syslog-alerts/src/org/apache/cloudstack/syslog/AlertsSyslogAppender.java @@ -168,7 +168,7 @@ private boolean validateIpAddresses() { if (ip.equalsIgnoreCase("localhost")) { continue; } - if (!NetUtils.isValidIp(ip)) { + if (!NetUtils.isValidIp4(ip)) { return false; } } else diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmIpAddressCommandWrapper.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmIpAddressCommandWrapper.java index 1545214781c7..1d3a60b75e35 100644 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmIpAddressCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtGetVmIpAddressCommandWrapper.java @@ -49,7 +49,7 @@ public Answer execute(final GetVmIpAddressCommand command, final LibvirtComputin String ipAddr = Script.runSimpleBashScript(new StringBuilder().append("virt-cat ").append(command.getVmName()) .append(" /var/lib/dhclient/" + leaseFile + " | tail -16 | grep 'fixed-address' | awk '{print $2}' | sed -e 's/;//'").toString()); // Check if the IP belongs to the network - if((ipAddr != null) && NetUtils.isIpWithtInCidrRange(ipAddr, networkCidr)){ + if((ipAddr != null) && NetUtils.isIpWithInCidrRange(ipAddr, networkCidr)){ ip = ipAddr; break; } @@ -65,7 +65,7 @@ public Answer execute(final GetVmIpAddressCommand command, final LibvirtComputin String[] ips = ipList.split("\n"); for (String ipAddr : ips){ // Check if the IP belongs to the network - if((ipAddr != null) && NetUtils.isIpWithtInCidrRange(ipAddr, networkCidr)){ + if((ipAddr != null) && NetUtils.isIpWithInCidrRange(ipAddr, networkCidr)){ ip = ipAddr; break; } diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3Configuration.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3Configuration.java index 6775a146aeb6..ba31236a7a80 100644 --- a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3Configuration.java +++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3Configuration.java @@ -130,7 +130,7 @@ private void validatePoolAndCluster() { LOGGER.debug("Clustering requires a pool, setting pool to true"); agentInOvm3Pool = true; } - if (!NetUtils.isValidIp(ovm3PoolVip)) { + if (!NetUtils.isValidIp4(ovm3PoolVip)) { LOGGER.debug("No VIP, Setting ovm3pool and ovm3cluster to false"); agentInOvm3Pool = false; agentInOvm3Cluster = false; diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmIpAddressCommandWrapper.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmIpAddressCommandWrapper.java index dd1ee28de317..e425fa70c848 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmIpAddressCommandWrapper.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/wrapper/xenbase/CitrixGetVmIpAddressCommandWrapper.java @@ -56,7 +56,7 @@ public Answer execute(final GetVmIpAddressCommand command, final CitrixResourceB Map vmIpsMap = rec.networks; for (String ipAddr: vmIpsMap.values()) { - if (NetUtils.isIpWithtInCidrRange(ipAddr, networkCidr)) { + if (NetUtils.isIpWithInCidrRange(ipAddr, networkCidr)) { vmIp = ipAddr; break; } diff --git a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java index 15fbdebe50d8..f93aaaf96f20 100644 --- a/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java +++ b/plugins/network-elements/netscaler/src/com/cloud/network/resource/NetscalerResource.java @@ -2574,7 +2574,7 @@ private void deleteServersInGuestVlan(final long vlanTag, final String vlanSelfI } private String getNetScalerProtocol(final LoadBalancerTO loadBalancer) throws ExecutionException { - final String port = Integer.toString(loadBalancer.getSrcPort()); + final int port = loadBalancer.getSrcPort(); String lbProtocol = loadBalancer.getLbProtocol(); final StickinessPolicyTO[] stickyPolicies = loadBalancer.getStickinessPolicies(); String nsProtocol = "TCP"; @@ -2596,7 +2596,7 @@ private String getNetScalerProtocol(final LoadBalancerTO loadBalancer) throws Ex return lbProtocol.toUpperCase(); } - if (port.equals(NetUtils.HTTP_PORT)) { + if (port == NetUtils.HTTP_PORT) { nsProtocol = "HTTP"; } else if (NetUtils.TCP_PROTO.equalsIgnoreCase(lbProtocol)) { nsProtocol = "TCP"; diff --git a/server/src/com/cloud/api/ApiServer.java b/server/src/com/cloud/api/ApiServer.java index 9e237741c969..d9671e9b4b71 100644 --- a/server/src/com/cloud/api/ApiServer.java +++ b/server/src/com/cloud/api/ApiServer.java @@ -46,6 +46,7 @@ import com.cloud.utils.Pair; import com.cloud.utils.ReflectUtil; import com.cloud.utils.StringUtils; +import com.cloud.utils.net.NetUtils; import com.cloud.utils.component.ComponentContext; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.component.PluggableService; @@ -97,6 +98,7 @@ import org.apache.cloudstack.api.response.ExceptionResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.LoginCmdResponse; +import org.apache.cloudstack.config.ApiServiceConfiguration; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; @@ -795,7 +797,7 @@ private void buildAuditTrail(final StringBuilder auditTrailSb, final String comm } @Override - public boolean verifyRequest(final Map requestParameters, final Long userId) throws ServerApiException { + public boolean verifyRequest(final Map requestParameters, final Long userId, InetAddress remoteAddress) throws ServerApiException { try { String apiKey = null; String secretKey = null; @@ -814,21 +816,18 @@ public boolean verifyRequest(final Map requestParameters, fina if (userId != null) { final User user = ApiDBUtils.findUserById(userId); - try { - checkCommandAvailable(user, commandName); - } catch (final RequestLimitException ex) { - s_logger.debug(ex.getMessage()); - throw new ServerApiException(ApiErrorCode.API_LIMIT_EXCEED, ex.getMessage()); - } catch (final PermissionDeniedException ex) { - s_logger.debug("The user with id:" + userId + " is not allowed to request the API command or the API command does not exist: " + commandName); - throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The user is not allowed to request the API command or the API command does not exist"); + if (!commandAvailable(remoteAddress, commandName, user)) { + return false; } + return true; } else { // check against every available command to see if the command exists or not if (!s_apiNameCmdClassMap.containsKey(commandName) && !commandName.equals("login") && !commandName.equals("logout")) { - s_logger.debug("The user with id:" + userId + " is not allowed to request the API command or the API command does not exist: " + commandName); - throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The user is not allowed to request the API command or the API command does not exist"); + final String errorMessage = "The given command " + commandName + " either does not exist, is not available" + + " for user, or not available from ip address '" + remoteAddress.getHostAddress() + "'."; + s_logger.debug(errorMessage); + return false; } } @@ -916,15 +915,8 @@ public boolean verifyRequest(final Map requestParameters, fina return false; } - try { - checkCommandAvailable(user, commandName); - } catch (final RequestLimitException ex) { - s_logger.debug(ex.getMessage()); - throw new ServerApiException(ApiErrorCode.API_LIMIT_EXCEED, ex.getMessage()); - } catch (final PermissionDeniedException ex) { - s_logger.debug("The given command:" + commandName + " does not exist or it is not available for user"); - throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, "The given command:" + commandName + " does not exist or it is not available for user with id:" - + userId); + if (!commandAvailable(remoteAddress, commandName, user)) { + return false; } // verify secret key exists @@ -959,6 +951,21 @@ public boolean verifyRequest(final Map requestParameters, fina return false; } + private boolean commandAvailable(final InetAddress remoteAddress, final String commandName, final User user) { + try { + checkCommandAvailable(user, commandName, remoteAddress); + } catch (final RequestLimitException ex) { + s_logger.debug(ex.getMessage()); + throw new ServerApiException(ApiErrorCode.API_LIMIT_EXCEED, ex.getMessage()); + } catch (final PermissionDeniedException ex) { + final String errorMessage = "The given command '" + commandName + "' either does not exist, is not available" + + " for user, or not available from ip address '" + remoteAddress + "'."; + s_logger.debug(errorMessage); + return false; + } + return true; + } + @Override public Long fetchDomainId(final String domainUUID) { final Domain domain = domainMgr.getDomain(domainUUID); @@ -1113,11 +1120,24 @@ public boolean verifyUser(final Long userId) { return true; } - private void checkCommandAvailable(final User user, final String commandName) throws PermissionDeniedException { + private void checkCommandAvailable(final User user, final String commandName, final InetAddress remoteAddress) throws PermissionDeniedException { if (user == null) { throw new PermissionDeniedException("User is null for role based API access check for command" + commandName); } + final Account account = accountMgr.getAccount(user.getAccountId()); + final String accessAllowedCidrs = ApiServiceConfiguration.ApiAllowedSourceCidrList.valueIn(account.getId()).replaceAll("\\s",""); + final Boolean apiSourceCidrChecksEnabled = ApiServiceConfiguration.ApiSourceCidrChecksEnabled.value(); + + if (apiSourceCidrChecksEnabled) { + s_logger.debug("CIDRs from which account '" + account.toString() + "' is allowed to perform API calls: " + accessAllowedCidrs); + if (!NetUtils.isIpInCidrList(remoteAddress, accessAllowedCidrs.split(","))) { + s_logger.warn("Request by account '" + account.toString() + "' was denied since " + remoteAddress + " does not match " + accessAllowedCidrs); + throw new PermissionDeniedException("Calls for domain '" + account.getAccountName() + "' are not allowed from ip address '" + remoteAddress.getHostAddress()); + } + } + + for (final APIChecker apiChecker : apiAccessCheckers) { apiChecker.checkAccess(user, commandName); } diff --git a/server/src/com/cloud/api/ApiServlet.java b/server/src/com/cloud/api/ApiServlet.java index 7a607fde773e..4002ff8d99b1 100644 --- a/server/src/com/cloud/api/ApiServlet.java +++ b/server/src/com/cloud/api/ApiServlet.java @@ -19,6 +19,7 @@ import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.URLDecoder; +import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -132,9 +133,21 @@ public void run() { } void processRequestInContext(final HttpServletRequest req, final HttpServletResponse resp) { - final String remoteAddress = getClientAddress(req); + InetAddress remoteAddress = null; + try { + remoteAddress = getClientAddress(req); + } catch (UnknownHostException e) { + s_logger.warn("UnknownHostException when trying to lookup remote IP-Address. This should never happen. Blocking request.", e); + final String response = apiServer.getSerializedApiError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + "UnknownHostException when trying to lookup remote IP-Address", null, + HttpUtils.RESPONSE_TYPE_XML); + HttpUtils.writeHttpResponse(resp, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + HttpUtils.RESPONSE_TYPE_XML, ApiServer.JSONcontentType.value()); + return; + } + final StringBuilder auditTrailSb = new StringBuilder(128); - auditTrailSb.append(" ").append(remoteAddress); + auditTrailSb.append(" ").append(remoteAddress.getHostAddress()); auditTrailSb.append(" -- ").append(req.getMethod()).append(' '); // get the response format since we'll need it in a couple of places String responseType = HttpUtils.RESPONSE_TYPE_XML; @@ -198,7 +211,7 @@ void processRequestInContext(final HttpServletRequest req, final HttpServletResp } try { - responseString = apiAuthenticator.authenticate(command, params, session, InetAddress.getByName(remoteAddress), responseType, auditTrailSb, req, resp); + responseString = apiAuthenticator.authenticate(command, params, session, remoteAddress, responseType, auditTrailSb, req, resp); if (session != null && session.getAttribute(ApiConstants.SESSIONKEY) != null) { resp.addHeader("SET-COOKIE", String.format("%s=%s;HttpOnly", ApiConstants.SESSIONKEY, session.getAttribute(ApiConstants.SESSIONKEY))); } @@ -288,12 +301,12 @@ void processRequestInContext(final HttpServletRequest req, final HttpServletResp CallContext.register(accountMgr.getSystemUser(), accountMgr.getSystemAccount()); } - if (apiServer.verifyRequest(params, userId)) { + if (apiServer.verifyRequest(params, userId, remoteAddress)) { auditTrailSb.insert(0, "(userId=" + CallContext.current().getCallingUserId() + " accountId=" + CallContext.current().getCallingAccount().getId() + " sessionId=" + (session != null ? session.getId() : null) + ")"); // Add the HTTP method (GET/POST/PUT/DELETE) as well into the params map. - params.put("httpmethod", new String[] {req.getMethod()}); + params.put("httpmethod", new String[]{req.getMethod()}); final String response = apiServer.handleRequest(params, responseType, auditTrailSb); HttpUtils.writeHttpResponse(resp, response != null ? response : "", HttpServletResponse.SC_OK, responseType, ApiServer.JSONcontentType.value()); } else { @@ -330,29 +343,29 @@ void processRequestInContext(final HttpServletRequest req, final HttpServletResp } //This method will try to get login IP of user even if servlet is behind reverseProxy or loadBalancer - static String getClientAddress(final HttpServletRequest request) { + static InetAddress getClientAddress(final HttpServletRequest request) throws UnknownHostException { for(final String header : s_clientAddressHeaders) { final String ip = getCorrectIPAddress(request.getHeader(header)); if (ip != null) { - return ip; + return InetAddress.getByName(ip); } } - return request.getRemoteAddr(); + return InetAddress.getByName(request.getRemoteAddr()); } private static String getCorrectIPAddress(String ip) { if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { return null; } - if(NetUtils.isValidIp(ip) || NetUtils.isValidIpv6(ip)) { + if(NetUtils.isValidIp4(ip) || NetUtils.isValidIp6(ip)) { return ip; } //it could be possible to have multiple IPs in HTTP header, this happens if there are multiple proxy in between //the client and the servlet, so parse the client IP String[] ips = ip.split(","); for(String i : ips) { - if(NetUtils.isValidIp(i.trim()) || NetUtils.isValidIpv6(i.trim())) { + if(NetUtils.isValidIp4(i.trim()) || NetUtils.isValidIp6(i.trim())) { return i.trim(); } } diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index dfc7c372d484..9cbe30597a92 100755 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -872,7 +872,7 @@ private String validateConfigurationValue(final String name, String value, final throw new InvalidParameterValueException("Error parsing ip address"); } } else if (range.equals("netmask")) { - if (!NetUtils.isValidNetmask(value)) { + if (!NetUtils.isValidIp4Netmask(value)) { s_logger.error("netmask " + value + " is not a valid net mask for configuration variable " + name); return "Please enter a valid netmask."; } @@ -904,7 +904,7 @@ private String validateConfigurationValue(final String name, String value, final for (final String route : routes) { if (route != null) { final String routeToVerify = route.trim(); - if (!NetUtils.isValidCIDR(routeToVerify)) { + if (!NetUtils.isValidIp4Cidr(routeToVerify)) { throw new InvalidParameterValueException("Invalid value for blacklisted route: " + route + ". Valid format is list" + " of cidrs separated by coma. Example: 10.1.1.0/24,192.168.0.0/24"); } @@ -989,7 +989,7 @@ private void checkPodAttributes(final long podId, final String podName, final lo long cidrSize; // Get the individual cidrAddress and cidrSize values, if the CIDR is // valid. If it's not valid, return an error. - if (NetUtils.isValidCIDR(cidr)) { + if (NetUtils.isValidIp4Cidr(cidr)) { cidrAddress = getCidrAddress(cidr); cidrSize = getCidrSize(cidr); } else { @@ -1005,7 +1005,7 @@ private void checkPodAttributes(final long podId, final String podName, final lo } // Check if the gateway is a valid IP address - if (!NetUtils.isValidIp(gateway)) { + if (!NetUtils.isValidIp4(gateway)) { throw new InvalidParameterValueException("The gateway is not a valid IP address."); } @@ -1119,11 +1119,11 @@ public Pod createPodIpRange(final CreateManagementNetworkIpRangeCmd cmd) { final long zoneId = pod.getDataCenterId(); - if(!NetUtils.isValidIp(gateway)) { + if(!NetUtils.isValidIp4(gateway)) { throw new InvalidParameterValueException("The gateway IP address is invalid."); } - if(!NetUtils.isValidNetmask(netmask)) { + if(!NetUtils.isValidIp4Netmask(netmask)) { throw new InvalidParameterValueException("The netmask IP address is invalid."); } @@ -1133,7 +1133,7 @@ public Pod createPodIpRange(final CreateManagementNetworkIpRangeCmd cmd) { final String cidr = NetUtils.ipAndNetMaskToCidr(gateway, netmask); - if(!NetUtils.isValidCIDR(cidr)) { + if(!NetUtils.isValidIp4Cidr(cidr)) { throw new InvalidParameterValueException("The CIDR is invalid " + cidr); } @@ -1170,7 +1170,7 @@ public Pod createPodIpRange(final CreateManagementNetworkIpRangeCmd cmd) { final String[] existingPodIpRange = podIpRange.split("-"); if (existingPodIpRange.length > 1) { - if (!NetUtils.isValidIp(existingPodIpRange[0]) || !NetUtils.isValidIp(existingPodIpRange[1])) { + if (!NetUtils.isValidIp4(existingPodIpRange[0]) || !NetUtils.isValidIp4(existingPodIpRange[1])) { continue; } // Check if the range overlaps with any existing range. @@ -1236,11 +1236,11 @@ public void deletePodIpRange(final DeleteManagementNetworkIpRangeCmd cmd) throws throw new InvalidParameterValueException("Unable to find pod by id " + podId); } - if (startIp == null || !NetUtils.isValidIp(startIp)) { + if (startIp == null || !NetUtils.isValidIp4(startIp)) { throw new InvalidParameterValueException("The start address of the IP range is not a valid IP address."); } - if (endIp == null || !NetUtils.isValidIp(endIp)) { + if (endIp == null || !NetUtils.isValidIp4(endIp)) { throw new InvalidParameterValueException("The end address of the IP range is not a valid IP address."); } @@ -1390,7 +1390,7 @@ public Pod editPod(final long id, String name, String startIp, String endIp, Str final String[] existingPodIpRange = podIpRange.split("-"); if (existingPodIpRange.length > 1) { - if (!NetUtils.isValidIp(existingPodIpRange[0]) || !NetUtils.isValidIp(existingPodIpRange[1])) { + if (!NetUtils.isValidIp4(existingPodIpRange[0]) || !NetUtils.isValidIp4(existingPodIpRange[1])) { continue; } @@ -1443,11 +1443,11 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { @Override public Pod createPod(final long zoneId, final String name, final String startIp, final String endIp, final String gateway, final String netmask, String allocationState) { // Check if the gateway is a valid IP address - if (!NetUtils.isValidIp(gateway)) { + if (!NetUtils.isValidIp4(gateway)) { throw new InvalidParameterValueException("The gateway is invalid"); } - if (!NetUtils.isValidNetmask(netmask)) { + if (!NetUtils.isValidIp4Netmask(netmask)) { throw new InvalidParameterValueException("The netmask is invalid"); } @@ -1601,27 +1601,27 @@ private void checkZoneParameters(final String zoneName, final String dns1, final // Check IP validity for DNS addresses // Empty strings is a valid input -- hence the length check - if (dns1 != null && dns1.length() > 0 && !NetUtils.isValidIp(dns1)) { + if (dns1 != null && dns1.length() > 0 && !NetUtils.isValidIp4(dns1)) { throw new InvalidParameterValueException("Please enter a valid IP address for DNS1"); } - if (dns2 != null && dns2.length() > 0 && !NetUtils.isValidIp(dns2)) { + if (dns2 != null && dns2.length() > 0 && !NetUtils.isValidIp4(dns2)) { throw new InvalidParameterValueException("Please enter a valid IP address for DNS2"); } - if (internalDns1 != null && internalDns1.length() > 0 && !NetUtils.isValidIp(internalDns1)) { + if (internalDns1 != null && internalDns1.length() > 0 && !NetUtils.isValidIp4(internalDns1)) { throw new InvalidParameterValueException("Please enter a valid IP address for internal DNS1"); } - if (internalDns2 != null && internalDns2.length() > 0 && !NetUtils.isValidIp(internalDns2)) { + if (internalDns2 != null && internalDns2.length() > 0 && !NetUtils.isValidIp4(internalDns2)) { throw new InvalidParameterValueException("Please enter a valid IP address for internal DNS2"); } - if (ip6Dns1 != null && ip6Dns1.length() > 0 && !NetUtils.isValidIpv6(ip6Dns1)) { + if (ip6Dns1 != null && ip6Dns1.length() > 0 && !NetUtils.isValidIp6(ip6Dns1)) { throw new InvalidParameterValueException("Please enter a valid IPv6 address for IP6 DNS1"); } - if (ip6Dns2 != null && ip6Dns2.length() > 0 && !NetUtils.isValidIpv6(ip6Dns2)) { + if (ip6Dns2 != null && ip6Dns2.length() > 0 && !NetUtils.isValidIp6(ip6Dns2)) { throw new InvalidParameterValueException("Please enter a valid IPv6 address for IP6 DNS2"); } @@ -1637,11 +1637,11 @@ private void checkZoneParameters(final String zoneName, final String dns1, final private void checkIpRange(final String startIp, final String endIp, final String cidrAddress, final long cidrSize) { //Checking not null for start IP as well. Previously we assumed to be not null always. //But the check is required for the change in updatePod API. - if (!Strings.isNullOrEmpty(startIp) && !NetUtils.isValidIp(startIp)) { + if (!Strings.isNullOrEmpty(startIp) && !NetUtils.isValidIp4(startIp)) { throw new InvalidParameterValueException("The start address of the IP range is not a valid IP address."); } - if (!Strings.isNullOrEmpty(endIp) && !NetUtils.isValidIp(endIp)) { + if (!Strings.isNullOrEmpty(endIp) && !NetUtils.isValidIp4(endIp)) { throw new InvalidParameterValueException("The end address of the IP range is not a valid IP address."); } @@ -1683,7 +1683,7 @@ private void checkOverlapPrivateIpRange(final Long zoneId, final String startIp, final String[] existingPodIpRange = podIpRange.split("-"); if (existingPodIpRange.length > 1) { - if (!NetUtils.isValidIp(existingPodIpRange[0]) || !NetUtils.isValidIp(existingPodIpRange[1])) { + if (!NetUtils.isValidIp4(existingPodIpRange[0]) || !NetUtils.isValidIp4(existingPodIpRange[1])) { continue; } @@ -3299,18 +3299,18 @@ public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId, if (ipv4) { // Make sure the gateway is valid - if (!NetUtils.isValidIp(vlanGateway)) { + if (!NetUtils.isValidIp4(vlanGateway)) { throw new InvalidParameterValueException("Please specify a valid gateway"); } // Make sure the netmask is valid - if (!NetUtils.isValidNetmask(vlanNetmask)) { + if (!NetUtils.isValidIp4Netmask(vlanNetmask)) { throw new InvalidParameterValueException("Please specify a valid netmask"); } } if (ipv6) { - if (!NetUtils.isValidIpv6(vlanIp6Gateway)) { + if (!NetUtils.isValidIp6(vlanIp6Gateway)) { throw new InvalidParameterValueException("Please specify a valid IPv6 gateway"); } if (!NetUtils.isValidIp6Cidr(vlanIp6Cidr)) { @@ -3322,7 +3322,7 @@ public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId, final String newCidr = NetUtils.getCidrFromGatewayAndNetmask(vlanGateway, vlanNetmask); //Make sure start and end ips are with in the range of cidr calculated for this gateway and netmask { - if (!NetUtils.isIpWithtInCidrRange(vlanGateway, newCidr) || !NetUtils.isIpWithtInCidrRange(startIP, newCidr) || !NetUtils.isIpWithtInCidrRange(endIP, newCidr)) { + if (!NetUtils.isIpWithInCidrRange(vlanGateway, newCidr) || !NetUtils.isIpWithInCidrRange(startIP, newCidr) || !NetUtils.isIpWithInCidrRange(endIP, newCidr)) { throw new InvalidParameterValueException("Please specify a valid IP range or valid netmask or valid gateway"); } @@ -3819,11 +3819,11 @@ public List doInTransaction(final TransactionStatus status) { private void checkPublicIpRangeErrors(final long zoneId, final String vlanId, final String vlanGateway, final String vlanNetmask, final String startIP, final String endIP) { // Check that the start and end IPs are valid - if (!NetUtils.isValidIp(startIP)) { + if (!NetUtils.isValidIp4(startIP)) { throw new InvalidParameterValueException("Please specify a valid start IP"); } - if (endIP != null && !NetUtils.isValidIp(endIP)) { + if (endIP != null && !NetUtils.isValidIp4(endIP)) { throw new InvalidParameterValueException("Please specify a valid end IP"); } @@ -5422,7 +5422,7 @@ public PortableIpRange createPortableIpRange(final CreatePortableIpRangeCmd cmd) throw new InvalidParameterValueException("Invalid region ID: " + regionId); } - if (!NetUtils.isValidIp(startIP) || !NetUtils.isValidIp(endIP) || !NetUtils.validIpRange(startIP, endIP)) { + if (!NetUtils.isValidIp4(startIP) || !NetUtils.isValidIp4(endIP) || !NetUtils.validIpRange(startIP, endIP)) { throw new InvalidParameterValueException("Invalid portable ip range: " + startIP + "-" + endIP); } diff --git a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java index cee07455d3a0..28fff3c7219c 100644 --- a/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java +++ b/server/src/com/cloud/consoleproxy/ConsoleProxyManagerImpl.java @@ -1395,7 +1395,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl if (nic.getTrafficType() == TrafficType.Management) { String mgmt_cidr = _configDao.getValue(Config.ManagementNetwork.key()); - if (NetUtils.isValidCIDR(mgmt_cidr)) { + if (NetUtils.isValidIp4Cidr(mgmt_cidr)) { buf.append(" mgmtcidr=").append(mgmt_cidr); } buf.append(" localgw=").append(dest.getPod().getGateway()); diff --git a/server/src/com/cloud/network/NetworkModelImpl.java b/server/src/com/cloud/network/NetworkModelImpl.java index 0495a350d3d1..efa9ffbde6b6 100644 --- a/server/src/com/cloud/network/NetworkModelImpl.java +++ b/server/src/com/cloud/network/NetworkModelImpl.java @@ -2148,10 +2148,10 @@ public boolean isNetworkInlineMode(Network network) { @Override public void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gateway, String ip6Cidr) throws InvalidParameterValueException { - if (!NetUtils.isValidIpv6(startIPv6)) { + if (!NetUtils.isValidIp6(startIPv6)) { throw new InvalidParameterValueException("Invalid format for the startIPv6 parameter"); } - if (!NetUtils.isValidIpv6(endIPv6)) { + if (!NetUtils.isValidIp6(endIPv6)) { throw new InvalidParameterValueException("Invalid format for the endIPv6 parameter"); } @@ -2159,7 +2159,7 @@ public void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gatew throw new InvalidParameterValueException("ip6Gateway and ip6Cidr should be defined when startIPv6/endIPv6 are passed in"); } - if (!NetUtils.isValidIpv6(ip6Gateway)) { + if (!NetUtils.isValidIp6(ip6Gateway)) { throw new InvalidParameterValueException("Invalid ip6Gateway"); } if (!NetUtils.isValidIp6Cidr(ip6Cidr)) { @@ -2188,13 +2188,13 @@ public void checkRequestedIpAddresses(long networkId, IpAddresses ips) throws In String ip6 = ips.getIp6Address(); String mac = ips.getMacAddress(); if (ip4 != null) { - if (!NetUtils.isValidIp(ip4)) { + if (!NetUtils.isValidIp4(ip4)) { throw new InvalidParameterValueException("Invalid specified IPv4 address " + ip4); } //Other checks for ipv4 are done in assignPublicIpAddress() } if (ip6 != null) { - if (!NetUtils.isValidIpv6(ip6)) { + if (!NetUtils.isValidIp6(ip6)) { throw new InvalidParameterValueException("Invalid specified IPv6 address " + ip6); } if (_ipv6Dao.findByNetworkIdAndIp(networkId, ip6) != null) { diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index 81ab2b141e13..6b431f43a7ee 100644 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -1169,12 +1169,12 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac if (ipv4) { // if end ip is not specified, default it to startIp if (startIP != null) { - if (!NetUtils.isValidIp(startIP)) { + if (!NetUtils.isValidIp4(startIP)) { throw new InvalidParameterValueException("Invalid format for the startIp parameter"); } if (endIP == null) { endIP = startIP; - } else if (!NetUtils.isValidIp(endIP)) { + } else if (!NetUtils.isValidIp4(endIP)) { throw new InvalidParameterValueException("Invalid format for the endIp parameter"); } } @@ -1193,10 +1193,10 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac throw new InvalidParameterValueException("Invalid gateway IP provided. Either the IP is broadcast or network IP."); } - if (!NetUtils.isValidIp(gateway)) { + if (!NetUtils.isValidIp4(gateway)) { throw new InvalidParameterValueException("Invalid gateway"); } - if (!NetUtils.isValidNetmask(netmask)) { + if (!NetUtils.isValidIp4Netmask(netmask)) { throw new InvalidParameterValueException("Invalid netmask"); } @@ -2129,7 +2129,7 @@ public Network updateGuestNetwork(final long networkId, String name, String disp throw new InvalidParameterValueException("The network must be in " + Network.State.Implemented + " state. IP Reservation cannot be applied in " + network.getState() + " state"); } - if (!NetUtils.isValidCIDR(guestVmCidr)) { + if (!NetUtils.isValidIp4Cidr(guestVmCidr)) { throw new InvalidParameterValueException("Invalid format of Guest VM CIDR."); } if (!NetUtils.validateGuestCidr(guestVmCidr)) { @@ -4296,19 +4296,19 @@ public Network createPrivateNetwork(final String networkName, final String displ // VALIDATE IP INFO // if end ip is not specified, default it to startIp - if (!NetUtils.isValidIp(startIp)) { + if (!NetUtils.isValidIp4(startIp)) { throw new InvalidParameterValueException("Invalid format for the ip address parameter"); } if (endIp == null) { endIp = startIp; - } else if (!NetUtils.isValidIp(endIp)) { + } else if (!NetUtils.isValidIp4(endIp)) { throw new InvalidParameterValueException("Invalid format for the endIp address parameter"); } - if (!NetUtils.isValidIp(gateway)) { + if (!NetUtils.isValidIp4(gateway)) { throw new InvalidParameterValueException("Invalid gateway"); } - if (!NetUtils.isValidNetmask(netmask)) { + if (!NetUtils.isValidIp4Netmask(netmask)) { throw new InvalidParameterValueException("Invalid netmask"); } diff --git a/server/src/com/cloud/network/StorageNetworkManagerImpl.java b/server/src/com/cloud/network/StorageNetworkManagerImpl.java index 020f7b1b044a..ac43c11fbe2f 100644 --- a/server/src/com/cloud/network/StorageNetworkManagerImpl.java +++ b/server/src/com/cloud/network/StorageNetworkManagerImpl.java @@ -84,7 +84,7 @@ private void checkOverlapPrivateIpRange(long podId, String startIp, String endIp final String[] existingPodIpRange = podIpRange.split("-"); if (existingPodIpRange.length > 1) { - if (!NetUtils.isValidIp(existingPodIpRange[0]) || !NetUtils.isValidIp(existingPodIpRange[1])) { + if (!NetUtils.isValidIp4(existingPodIpRange[0]) || !NetUtils.isValidIp4(existingPodIpRange[1])) { continue; } @@ -137,7 +137,7 @@ public StorageNetworkIpRange updateIpRange(UpdateStorageNetworkIpRangeCmd cmd) { String endIp = cmd.getEndIp(); final String netmask = cmd.getNetmask(); - if (netmask != null && !NetUtils.isValidNetmask(netmask)) { + if (netmask != null && !NetUtils.isValidIp4Netmask(netmask)) { throw new CloudRuntimeException("Invalid netmask:" + netmask); } @@ -207,7 +207,7 @@ public StorageNetworkIpRange createIpRange(final CreateStorageNetworkIpRangeCmd endIp = startIp; } - if (!NetUtils.isValidNetmask(netmask)) { + if (!NetUtils.isValidIp4Netmask(netmask)) { throw new CloudRuntimeException("Invalid netmask:" + netmask); } diff --git a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java index a8f4b1714bd3..cf72ff28f0cf 100644 --- a/server/src/com/cloud/network/firewall/FirewallManagerImpl.java +++ b/server/src/com/cloud/network/firewall/FirewallManagerImpl.java @@ -704,7 +704,7 @@ public boolean applyDefaultEgressFirewallRule(Long networkId, boolean defaultPol sourceCidr.add(network.getCidr()); - destCidr.add(NetUtils.ALL_CIDRS); + destCidr.add(NetUtils.ALL_IP4_CIDRS); FirewallRuleVO ruleVO = new FirewallRuleVO(null, null, null, null, "all", networkId, network.getAccountId(), network.getDomainId(), Purpose.Firewall, sourceCidr, destCidr, null, null, null, @@ -905,7 +905,7 @@ public FirewallRule createRuleForAllCidrs(long ipAddrId, Account caller, Integer } List oneCidr = new ArrayList(); - oneCidr.add(NetUtils.ALL_CIDRS); + oneCidr.add(NetUtils.ALL_IP4_CIDRS); return createFirewallRule(ipAddrId, caller, null, startPort, endPort, protocol, oneCidr, null, icmpCode, icmpType, relatedRuleId, FirewallRule.FirewallRuleType.User, networkId, FirewallRule.TrafficType.Ingress, true); } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index e0b08d1a70ff..f3035d05e612 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -1383,7 +1383,7 @@ public boolean finalizeVirtualMachineProfile(final VirtualMachineProfile profile // networking setup, DomR may have two interfaces while both // are on the same subnet _mgmtCidr = _configDao.getValue(Config.ManagementNetwork.key()); - if (NetUtils.isValidCIDR(_mgmtCidr)) { + if (NetUtils.isValidIp4Cidr(_mgmtCidr)) { buf.append(" mgmtcidr=").append(_mgmtCidr); buf.append(" localgw=").append(dest.getPod().getGateway()); } @@ -1955,7 +1955,7 @@ private void createDefaultEgressFirewallRule(final List rules, fin final List destCidr = new ArrayList(); sourceCidr.add(network.getCidr()); - destCidr.add(NetUtils.ALL_CIDRS); + destCidr.add(NetUtils.ALL_IP4_CIDRS); final FirewallRule rule = new FirewallRuleVO(null, null, null, null, "all", networkId, network.getAccountId(), network.getDomainId(), Purpose.Firewall, sourceCidr, destCidr, null, null, null, FirewallRule.TrafficType.Egress, FirewallRule.FirewallRuleType.System); diff --git a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java index f60395bcac43..07d7e4d1b8fe 100644 --- a/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java +++ b/server/src/com/cloud/network/security/SecurityGroupManagerImpl.java @@ -611,7 +611,7 @@ private List authorizeSecurityGroupRule(final Long security if (cidrList != null) { for (String cidr : cidrList) { - if (!NetUtils.isValidCIDR(cidr)) { + if (!NetUtils.isValidIp4Cidr(cidr) && !NetUtils.isValidIp6Cidr(cidr)) { throw new InvalidParameterValueException("Invalid cidr " + cidr); } } diff --git a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java index 4132b606d4ef..1743f5c322e4 100644 --- a/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java +++ b/server/src/com/cloud/network/vpc/NetworkACLServiceImpl.java @@ -406,7 +406,7 @@ private void validateNetworkACLItem(final Integer portStart, final Integer portE if (sourceCidrList != null) { for (final String cidr : sourceCidrList) { - if (!NetUtils.isValidCIDR(cidr)) { + if (!NetUtils.isValidIp4Cidr(cidr)) { throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Source cidrs formatting error " + cidr); } } diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 1f0753a9509c..5622482b0b70 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -792,7 +792,7 @@ public Vpc createVpc(final long zoneId, final long vpcOffId, final long vpcOwner protected Vpc createVpc(final Boolean displayVpc, final VpcVO vpc) { final String cidr = vpc.getCidr(); // Validate CIDR - if (!NetUtils.isValidCIDR(cidr)) { + if (!NetUtils.isValidIp4Cidr(cidr)) { throw new InvalidParameterValueException("Invalid CIDR specified " + cidr); } @@ -2030,7 +2030,7 @@ public StaticRoute createStaticRoute(final long gatewayId, final String cidr) th } _accountMgr.checkAccess(caller, null, false, vpc); - if (!NetUtils.isValidCIDR(cidr)) { + if (!NetUtils.isValidIp4Cidr(cidr)) { throw new InvalidParameterValueException("Invalid format for cidr " + cidr); } diff --git a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java index 491fb4741098..2030a5a4ee55 100644 --- a/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/RemoteAccessVpnManagerImpl.java @@ -194,7 +194,7 @@ public RemoteAccessVpn createRemoteAccessVpn(final long publicIpId, String ipRan if (range.length != 2) { throw new InvalidParameterValueException("Invalid ip range"); } - if (!NetUtils.isValidIp(range[0]) || !NetUtils.isValidIp(range[1])) { + if (!NetUtils.isValidIp4(range[0]) || !NetUtils.isValidIp4(range[1])) { throw new InvalidParameterValueException("Invalid ip in range specification " + ipRange); } if (!NetUtils.validIpRange(range[0], range[1])) { @@ -271,7 +271,7 @@ private void validateRemoteAccessVpnConfiguration() throws ConfigurationExceptio if (range.length != 2) { throw new ConfigurationException("Remote Access VPN: Invalid ip range " + ipRange); } - if (!NetUtils.isValidIp(range[0]) || !NetUtils.isValidIp(range[1])) { + if (!NetUtils.isValidIp4(range[0]) || !NetUtils.isValidIp4(range[1])) { throw new ConfigurationException("Remote Access VPN: Invalid ip in range specification " + ipRange); } if (!NetUtils.validIpRange(range[0], range[1])) { diff --git a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java index f188ad3545bd..aebc87174850 100644 --- a/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java +++ b/server/src/com/cloud/network/vpn/Site2SiteVpnManagerImpl.java @@ -177,7 +177,8 @@ public Site2SiteCustomerGateway createCustomerGateway(CreateVpnCustomerGatewayCm String name = cmd.getName(); String gatewayIp = cmd.getGatewayIp(); - if (!NetUtils.isValidIp(gatewayIp) && !NetUtils.verifyDomainName(gatewayIp)) { + + if (!NetUtils.isValidIp4(gatewayIp) && !NetUtils.verifyDomainName(gatewayIp)) { throw new InvalidParameterValueException("The customer gateway ip/Domain " + gatewayIp + " is invalid!"); } if (name == null) { @@ -428,7 +429,8 @@ public Site2SiteCustomerGateway updateCustomerGateway(UpdateVpnCustomerGatewayCm } String name = cmd.getName(); String gatewayIp = cmd.getGatewayIp(); - if (!NetUtils.isValidIp(gatewayIp) && !NetUtils.verifyDomainName(gatewayIp)) { + + if (!NetUtils.isValidIp4(gatewayIp) && !NetUtils.verifyDomainName(gatewayIp)) { throw new InvalidParameterValueException("The customer gateway ip/Domain " + gatewayIp + " is invalid!"); } if (name == null) { diff --git a/server/src/com/cloud/test/PodZoneConfig.java b/server/src/com/cloud/test/PodZoneConfig.java index 16bc0a064038..c55178f3f79d 100644 --- a/server/src/com/cloud/test/PodZoneConfig.java +++ b/server/src/com/cloud/test/PodZoneConfig.java @@ -221,11 +221,11 @@ public List modifyVlan(String zone, boolean add, String vlanId, String v if (add) { // Make sure the gateway is valid - if (!NetUtils.isValidIp(vlanGateway)) + if (!NetUtils.isValidIp4(vlanGateway)) return genReturnList("false", "Please specify a valid gateway."); // Make sure the netmask is valid - if (!NetUtils.isValidIp(vlanNetmask)) + if (!NetUtils.isValidIp4(vlanNetmask)) return genReturnList("false", "Please specify a valid netmask."); // Check if a vlan with the same vlanId already exists in the specified zone diff --git a/server/src/com/cloud/user/AccountManagerImpl.java b/server/src/com/cloud/user/AccountManagerImpl.java index aaaa92ba3c15..fea8b47a0c53 100644 --- a/server/src/com/cloud/user/AccountManagerImpl.java +++ b/server/src/com/cloud/user/AccountManagerImpl.java @@ -172,6 +172,8 @@ import com.cloud.vm.snapshot.VMSnapshotManager; import com.cloud.vm.snapshot.VMSnapshotVO; import com.cloud.vm.snapshot.dao.VMSnapshotDao; +import org.apache.cloudstack.config.ApiServiceConfiguration; + public class AccountManagerImpl extends ManagerBase implements AccountManager, Manager { public static final Logger s_logger = Logger.getLogger(AccountManagerImpl.class); @@ -179,6 +181,8 @@ public class AccountManagerImpl extends ManagerBase implements AccountManager, M @Inject private AccountDao _accountDao; @Inject + private AccountManager _accountMgr; + @Inject ConfigurationDao _configDao; @Inject private ResourceCountDao _resourceCountDao; @@ -2076,7 +2080,8 @@ public void logoutUser(long userId) { } @Override - public UserAccount authenticateUser(String username, String password, Long domainId, InetAddress loginIpAddress, Map requestParameters) { + public UserAccount authenticateUser(final String username, final String password, final Long domainId, final InetAddress loginIpAddress, final Map + requestParameters) { UserAccount user = null; if (password != null && !password.isEmpty()) { user = getUserAccount(username, password, domainId, requestParameters); @@ -2186,6 +2191,27 @@ public UserAccount authenticateUser(String username, String password, Long domai return null; } + // We authenticated successfully by now, let's check if we are allowed to login from the ip address the reqest comes from + final Account account = _accountMgr.getAccount(user.getAccountId()); + final DomainVO domain = (DomainVO) _domainMgr.getDomain(account.getDomainId()); + + // Get the CIDRs from where this account is allowed to make calls + final String accessAllowedCidrs = ApiServiceConfiguration.ApiAllowedSourceCidrList.valueIn(account.getId()).replaceAll("\\s",""); + final Boolean ApiSourceCidrChecksEnabled = ApiServiceConfiguration.ApiSourceCidrChecksEnabled.value(); + + if (ApiSourceCidrChecksEnabled) { + s_logger.debug("CIDRs from which account '" + account.toString() + "' is allowed to perform API calls: " + accessAllowedCidrs); + + // Block when is not in the list of allowed IPs + if (!NetUtils.isIpInCidrList(loginIpAddress, accessAllowedCidrs.split(","))) { + s_logger.warn("Request by account '" + account.toString() + "' was denied since " + loginIpAddress.toString().replaceAll("/","") + + " does not match " + accessAllowedCidrs); + throw new CloudAuthenticationException("Failed to authenticate user '" + username + "' in domain '" + domain.getPath() + "' from ip " + + loginIpAddress.toString().replaceAll("/","") + "; please provide valid credentials"); + } + } + + // Here all is fine! if (s_logger.isDebugEnabled()) { s_logger.debug("User: " + username + " in domain " + domainId + " has successfully logged in"); } diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java b/server/src/com/cloud/vm/UserVmManagerImpl.java index 72c479310573..df50f5a91622 100644 --- a/server/src/com/cloud/vm/UserVmManagerImpl.java +++ b/server/src/com/cloud/vm/UserVmManagerImpl.java @@ -649,7 +649,7 @@ protected void runInContext() { if (answer.getResult()) { String vmIp = answer.getDetails(); - if (NetUtils.isValidIp(vmIp)) { + if (NetUtils.isValidIp4(vmIp)) { // set this vm ip addr in vm nic. if (nic != null) { nic.setIPv4Address(vmIp); @@ -1184,7 +1184,7 @@ public UserVm addNicToVirtualMachine(AddNicToVMCmd cmd) throws InvalidParameterV NicProfile profile = new NicProfile(ipAddress, null, macAddress); if (ipAddress != null) { - if (!(NetUtils.isValidIp(ipAddress) || NetUtils.isValidIpv6(ipAddress))) { + if (!(NetUtils.isValidIp4(ipAddress) || NetUtils.isValidIp6(ipAddress))) { throw new InvalidParameterValueException("Invalid format for IP address parameter: " + ipAddress); } } diff --git a/server/test/com/cloud/api/ApiServletTest.java b/server/test/com/cloud/api/ApiServletTest.java index e7cdf41a38e0..037c36e3b95b 100644 --- a/server/test/com/cloud/api/ApiServletTest.java +++ b/server/test/com/cloud/api/ApiServletTest.java @@ -174,7 +174,7 @@ public void utf8FixupUtf() throws UnsupportedEncodingException { public void processRequestInContextUnauthorizedGET() { Mockito.when(request.getMethod()).thenReturn("GET"); Mockito.when( - apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong())) + apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong(), Mockito.any(InetAddress.class))) .thenReturn(false); servlet.processRequestInContext(request, response); Mockito.verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED); @@ -188,7 +188,7 @@ public void processRequestInContextUnauthorizedGET() { public void processRequestInContextAuthorizedGet() { Mockito.when(request.getMethod()).thenReturn("GET"); Mockito.when( - apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong())) + apiServer.verifyRequest(Mockito.anyMap(), Mockito.anyLong(), Mockito.any(InetAddress.class))) .thenReturn(true); servlet.processRequestInContext(request, response); Mockito.verify(response).setStatus(HttpServletResponse.SC_OK); @@ -242,33 +242,33 @@ public void processRequestInContextLogin() throws UnknownHostException { } @Test - public void getClientAddressWithXForwardedFor() { + public void getClientAddressWithXForwardedFor() throws UnknownHostException { Mockito.when(request.getHeader(Mockito.eq("X-Forwarded-For"))).thenReturn("192.168.1.1"); - Assert.assertEquals("192.168.1.1", ApiServlet.getClientAddress(request)); + Assert.assertEquals(InetAddress.getByName("192.168.1.1"), ApiServlet.getClientAddress(request)); } @Test - public void getClientAddressWithHttpXForwardedFor() { + public void getClientAddressWithHttpXForwardedFor() throws UnknownHostException { Mockito.when(request.getHeader(Mockito.eq("HTTP_X_FORWARDED_FOR"))).thenReturn("192.168.1.1"); - Assert.assertEquals("192.168.1.1", ApiServlet.getClientAddress(request)); + Assert.assertEquals(InetAddress.getByName("192.168.1.1"), ApiServlet.getClientAddress(request)); } @Test - public void getClientAddressWithXRemoteAddr() { + public void getClientAddressWithXRemoteAddr() throws UnknownHostException { Mockito.when(request.getHeader(Mockito.eq("Remote_Addr"))).thenReturn("192.168.1.1"); - Assert.assertEquals("192.168.1.1", ApiServlet.getClientAddress(request)); + Assert.assertEquals(InetAddress.getByName("192.168.1.1"), ApiServlet.getClientAddress(request)); } @Test - public void getClientAddressWithHttpClientIp() { + public void getClientAddressWithHttpClientIp() throws UnknownHostException { Mockito.when(request.getHeader(Mockito.eq("HTTP_CLIENT_IP"))).thenReturn("192.168.1.1"); - Assert.assertEquals("192.168.1.1", ApiServlet.getClientAddress(request)); + Assert.assertEquals(InetAddress.getByName("192.168.1.1"), ApiServlet.getClientAddress(request)); } @Test - public void getClientAddressDefault() { + public void getClientAddressDefault() throws UnknownHostException { Mockito.when(request.getRemoteAddr()).thenReturn("127.0.0.1"); - Assert.assertEquals("127.0.0.1", ApiServlet.getClientAddress(request)); + Assert.assertEquals(InetAddress.getByName("127.0.0.1"), ApiServlet.getClientAddress(request)); } } diff --git a/services/secondary-storage/controller/src/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java b/services/secondary-storage/controller/src/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java index 273fdd0d1167..a158c9c0e682 100644 --- a/services/secondary-storage/controller/src/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java +++ b/services/secondary-storage/controller/src/org/apache/cloudstack/secondarystorage/SecondaryStorageManagerImpl.java @@ -388,7 +388,7 @@ public boolean generateVMSetupCommand(Long ssAHostId) { List allowedCidrs = new ArrayList(); String[] cidrs = _allowedInternalSites.split(","); for (String cidr : cidrs) { - if (NetUtils.isValidCIDR(cidr) || NetUtils.isValidIp(cidr) || !cidr.startsWith("0.0.0.0")) { + if (NetUtils.isValidIp4Cidr(cidr) || NetUtils.isValidIp4(cidr) || !cidr.startsWith("0.0.0.0")) { allowedCidrs.add(cidr); } } @@ -1170,7 +1170,7 @@ public boolean finalizeVirtualMachineProfile(VirtualMachineProfile profile, Depl } if (nic.getTrafficType() == TrafficType.Management) { String mgmt_cidr = _configDao.getValue(Config.ManagementNetwork.key()); - if (NetUtils.isValidCIDR(mgmt_cidr)) { + if (NetUtils.isValidIp4Cidr(mgmt_cidr)) { buf.append(" mgmtcidr=").append(mgmt_cidr); } buf.append(" localgw=").append(dest.getPod().getGateway()); diff --git a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java index 655f11508d7f..dd97872d32d7 100644 --- a/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java +++ b/services/secondary-storage/server/src/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java @@ -2293,12 +2293,12 @@ private void addRouteToInternalIpOrCidr(String localgw, String eth1ip, String et s_logger.debug("addRouteToInternalIp: destIp is null"); return; } - if (!NetUtils.isValidIp(destIpOrCidr) && !NetUtils.isValidCIDR(destIpOrCidr)) { + if (!NetUtils.isValidIp4(destIpOrCidr) && !NetUtils.isValidIp4Cidr(destIpOrCidr)) { s_logger.warn(" destIp is not a valid ip address or cidr destIp=" + destIpOrCidr); return; } boolean inSameSubnet = false; - if (NetUtils.isValidIp(destIpOrCidr)) { + if (NetUtils.isValidIp4(destIpOrCidr)) { if (eth1ip != null && eth1mask != null) { inSameSubnet = NetUtils.sameSubnet(eth1ip, destIpOrCidr, eth1mask); } else { diff --git a/ui/l10n/en.js b/ui/l10n/en.js index afd950063450..1f31dce7e731 100644 --- a/ui/l10n/en.js +++ b/ui/l10n/en.js @@ -22,7 +22,7 @@ var dictionary = {"ICMP.code":"ICMP Code", "error.could.not.change.your.password.because.non.native.user":"Error could not change your password because user is not a native CloudStack user.", "error.could.not.enable.zone":"Could not enable zone", "error.installWizard.message":"Something went wrong; you may go back and correct any errors", -"error.invalid.username.password":"Invalid username or password", +"error.invalid.username.password": "Invalid username or password.

This could also be a restriction on the IP address you are connecting from.", "error.login":"Your username/password does not match our records.", "error.menu.select":"Unable to perform action due to no items being selected.", "error.mgmt.server.inaccessible":"The Management Server is unaccessible. Please try again later.", diff --git a/utils/src/main/java/com/cloud/utils/net/NetUtils.java b/utils/src/main/java/com/cloud/utils/net/NetUtils.java index c28739a91bdc..1bd08a32b259 100644 --- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java +++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java @@ -24,6 +24,8 @@ import java.io.InputStreamReader; import java.math.BigInteger; import java.net.InetAddress; +import java.net.Inet4Address; +import java.net.Inet6Address; import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.SocketException; @@ -35,7 +37,6 @@ import java.util.Random; import java.util.Set; import java.util.SortedSet; -import java.util.StringTokenizer; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -61,8 +62,8 @@ public class NetUtils { private static final int MAX_CIDR = 32; private static final int RFC_3021_31_BIT_CIDR = 31; - public final static String HTTP_PORT = "80"; - public final static String HTTPS_PORT = "443"; + public final static int HTTP_PORT = 80; + public final static int HTTPS_PORT = 443; public final static int VPN_PORT = 500; public final static int VPN_NATT_PORT = 4500; public final static int VPN_L2TP_PORT = 1701; @@ -76,7 +77,8 @@ public class NetUtils { public final static String HTTP_PROTO = "http"; public final static String SSL_PROTO = "ssl"; - public final static String ALL_CIDRS = "0.0.0.0/0"; + public final static String ALL_IP4_CIDRS = "0.0.0.0/0"; + public final static String ALL_IP6_CIDRS = "::/0"; public final static int PORT_RANGE_MIN = 0; public final static int PORT_RANGE_MAX = 65535; @@ -123,7 +125,7 @@ public static InetAddress getLocalInetAddress() { public static String resolveToIp(final String host) { try { final InetAddress addr = InetAddress.getByName(host); - return ipFromInetAddress(addr); + return addr.getHostAddress(); } catch (final UnknownHostException e) { s_logger.warn("Unable to resolve " + host + " to IP due to UnknownHostException"); return null; @@ -162,7 +164,7 @@ public static String[] getLocalCidrs() { final InetAddress addr = address.getAddress(); final int prefixLength = address.getNetworkPrefixLength(); if (prefixLength < MAX_CIDR && prefixLength > 0) { - final String ip = ipFromInetAddress(addr); + final String ip = addr.getHostAddress(); if (ip.equalsIgnoreCase(defaultHostIp)) { cidrList.add(ipAndNetMaskToCidr(ip, getCidrNetmask(prefixLength))); } @@ -243,67 +245,15 @@ public static String getDefaultEthDevice() { return defaultRouteList[7]; } - public static InetAddress getFirstNonLoopbackLocalInetAddress() { - final InetAddress[] addrs = getAllLocalInetAddresses(); - if (addrs != null) { - for (final InetAddress addr : addrs) { - if (s_logger.isInfoEnabled()) { - s_logger.info("Check local InetAddress : " + addr.toString() + ", total count :" + addrs.length); - } - - if (!addr.isLoopbackAddress()) { - return addr; - } - } - } - - s_logger.warn("Unable to determine a non-loopback address, local inet address count :" + addrs.length); - return null; - } - - public static InetAddress[] getInterfaceInetAddresses(final String ifName) { - final List addrList = new ArrayList(); - try { - for (final NetworkInterface ifc : IteratorUtil.enumerationAsIterable(NetworkInterface.getNetworkInterfaces())) { - if (ifc.isUp() && !ifc.isVirtual() && ifc.getName().equals(ifName)) { - for (final InetAddress addr : IteratorUtil.enumerationAsIterable(ifc.getInetAddresses())) { - addrList.add(addr); - } - } - } - } catch (final SocketException e) { - s_logger.warn("SocketException in getAllLocalInetAddresses().", e); - } - - final InetAddress[] addrs = new InetAddress[addrList.size()]; - if (addrList.size() > 0) { - System.arraycopy(addrList.toArray(), 0, addrs, 0, addrList.size()); - } - return addrs; - } - public static String getLocalIPString() { final InetAddress addr = getLocalInetAddress(); if (addr != null) { - return ipFromInetAddress(addr); + return addr.getHostAddress(); } return "127.0.0.1"; } - public static String ipFromInetAddress(final InetAddress addr) { - assert addr != null; - - final byte[] ipBytes = addr.getAddress(); - final StringBuffer sb = new StringBuffer(); - sb.append(ipBytes[0] & 0xff).append("."); - sb.append(ipBytes[1] & 0xff).append("."); - sb.append(ipBytes[2] & 0xff).append("."); - sb.append(ipBytes[3] & 0xff); - - return sb.toString(); - } - public static boolean isLocalAddress(final InetAddress addr) { final InetAddress[] addrs = getAllLocalInetAddresses(); @@ -318,10 +268,8 @@ public static boolean isLocalAddress(final InetAddress addr) { } public static boolean isLocalAddress(final String strAddress) { - - InetAddress addr; try { - addr = InetAddress.getByName(strAddress); + InetAddress addr = InetAddress.getByName(strAddress); return isLocalAddress(addr); } catch (final UnknownHostException e) { } @@ -346,23 +294,6 @@ public static String getMacAddress(final InetAddress address) { return sb.toString(); } - public static long getMacAddressAsLong(final InetAddress address) { - long macAddressAsLong = 0; - try { - final NetworkInterface ni = NetworkInterface.getByInetAddress(address); - final byte[] mac = ni.getHardwareAddress(); - - for (int i = 0; i < mac.length; i++) { - macAddressAsLong |= (long)(mac[i] & 0xff) << (mac.length - i - 1) * 8; - } - - } catch (final SocketException e) { - s_logger.error("SocketException when trying to retrieve MAC address", e); - } - - return macAddressAsLong; - } - /** * This method will fail in case we have a 31 Bit prefix network * See RFC 3021. @@ -498,40 +429,15 @@ public static String long2Mac(final long macAddress) { return result.toString(); } - public static boolean isValidPrivateIp(final String ipAddress, final String guestIPAddress) { - - final InetAddress privIp = parseIpAddress(ipAddress); - if (privIp == null) { - return false; - } - if (!privIp.isSiteLocalAddress()) { - return false; - } - - String firstGuestOctet = "10"; - if (guestIPAddress != null && !guestIPAddress.isEmpty()) { - final String[] guestIPList = guestIPAddress.split("\\."); - firstGuestOctet = guestIPList[0]; - } - - final String[] ipList = ipAddress.split("\\."); - if (!ipList[0].equals(firstGuestOctet)) { - return false; - } - - return true; - } - public static boolean isSiteLocalAddress(final String ipAddress) { - if (ipAddress == null) { - return false; - } else { - final InetAddress ip = parseIpAddress(ipAddress); - if(ip != null) { + try { + final InetAddress ip = InetAddress.getByName(ipAddress); + if (ip != null) { return ip.isSiteLocalAddress(); } - return false; - } + } catch (UnknownHostException e) {} + + return false; } public static boolean validIpRange(final String startIP, final String endIP) { @@ -544,14 +450,16 @@ public static boolean validIpRange(final String startIP, final String endIP) { return startIPLong <= endIPLong; } - public static boolean isValidIp(final String ip) { - final InetAddressValidator validator = InetAddressValidator.getInstance(); + public static boolean isValidIp4(final String ip) { + if (ip == null) + return false; + final InetAddressValidator validator = InetAddressValidator.getInstance(); return validator.isValidInet4Address(ip); } public static boolean is31PrefixCidr(final String cidr) { - final boolean isValidCird = isValidCIDR(cidr); + final boolean isValidCird = isValidIp4Cidr(cidr); if (isValidCird){ final String[] cidrPair = cidr.split("\\/"); final String cidrSize = cidrPair[1]; @@ -564,23 +472,18 @@ public static boolean is31PrefixCidr(final String cidr) { return false; } - public static boolean isValidCIDR(final String cidr) { + public static boolean isValidIp4Cidr(final String cidr) { if (cidr == null || cidr.isEmpty()) { return false; } - try { - IPv6Network.fromString(cidr); - return true; - } catch (IllegalArgumentException e) {} - final String[] cidrPair = cidr.split("\\/"); if (cidrPair.length != 2) { return false; } final String cidrAddress = cidrPair[0]; final String cidrSize = cidrPair[1]; - if (!isValidIp(cidrAddress)) { + if (!isValidIp4(cidrAddress)) { return false; } int cidrSizeNum = -1; @@ -598,8 +501,8 @@ public static boolean isValidCIDR(final String cidr) { return true; } - public static boolean isValidNetmask(final String netmask) { - if (!isValidIp(netmask)) { + public static boolean isValidIp4Netmask(final String netmask) { + if (!isValidIp4(netmask)) { return false; } @@ -624,25 +527,6 @@ public static boolean isValidNetmask(final String netmask) { return true; } - private static InetAddress parseIpAddress(final String address) { - final StringTokenizer st = new StringTokenizer(address, "."); - final byte[] bytes = new byte[4]; - - if (st.countTokens() == 4) { - try { - for (int i = 0; i < 4; i++) { - bytes[i] = (byte)Integer.parseInt(st.nextToken()); - } - return InetAddress.getByAddress(address, bytes); - } catch (final NumberFormatException nfe) { - return null; - } catch (final UnknownHostException uhe) { - return null; - } - } - return null; - } - public static String getCidrFromGatewayAndNetmask(final String gatewayStr, final String netmaskStr) { final long netmask = ip2Long(netmaskStr); final long gateway = ip2Long(gatewayStr); @@ -808,11 +692,11 @@ static long netMaskFromCidr(final long cidrSize) { } public static String ipAndNetMaskToCidr(final String ip, final String netmask) { - if (!isValidIp(ip)) { + if (!isValidIp4(ip)) { return null; } - if (!isValidNetmask(netmask)) { + if (!isValidIp4Netmask(netmask)) { return null; } @@ -909,7 +793,7 @@ public static Long[] cidrToLong(final String cidr) { } final String cidrAddress = cidrPair[0]; final String cidrSize = cidrPair[1]; - if (!isValidIp(cidrAddress)) { + if (!isValidIp4(cidrAddress)) { throw new CloudRuntimeException("cidr is not valid in ip space" + cidr); } long cidrSizeNum = getCidrSizeFromString(cidrSize); @@ -949,7 +833,7 @@ public static String getCidrSubNet(final String cidr) { } final String cidrAddress = cidrPair[0]; final String cidrSize = cidrPair[1]; - if (!isValidIp(cidrAddress)) { + if (!isValidIp4(cidrAddress)) { return null; } long cidrSizeNum = getCidrSizeFromString(cidrSize); @@ -988,23 +872,13 @@ public static long getCidrSize(final String netmask) { return MAX_CIDR - count; } - public static boolean isValidPort(final String p) { - try { - final int port = Integer.parseInt(p); - return !(port > 65535 || port < 1); - } catch (final NumberFormatException e) { - return false; - } - } - public static boolean isValidPort(final int p) { - return !(p > 65535 || p < 1); + return !(p > PORT_RANGE_MAX || p < PORT_RANGE_MIN); } - public static boolean isValidLBPort(final String p) { + public static boolean isValidPort(final String p) { try { - final int port = Integer.parseInt(p); - return !(port > 65535 || port < 1); + return isValidPort(Integer.parseInt(p)); } catch (final NumberFormatException e) { return false; } @@ -1126,11 +1000,11 @@ public static String getDhcpRange(final String cidr) { // Check if 2 CIDRs have exactly same IP Range public static boolean isSameIpRange(final String cidrA, final String cidrB) { - if (!NetUtils.isValidCIDR(cidrA)) { + if (!NetUtils.isValidIp4Cidr(cidrA)) { s_logger.info("Invalid value of cidr " + cidrA); return false; } - if (!NetUtils.isValidCIDR(cidrB)) { + if (!NetUtils.isValidIp4Cidr(cidrB)) { s_logger.info("Invalid value of cidr " + cidrB); return false; } @@ -1164,7 +1038,7 @@ public static boolean validateGuestCidr(final String cidr) { // The allocated address block is 100.64.0.0/10 final String[] allowedNetBlocks = {"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10"}; - if (!isValidCIDR(cidr)) { + if (!isValidIp4Cidr(cidr)) { s_logger.warn("Cidr " + cidr + " is not valid"); return false; } @@ -1261,7 +1135,7 @@ public static boolean isValidS2SVpnPolicy(final String policyType, final String public static boolean isValidCidrList(final String cidrList) { for (final String guestCidr : cidrList.split(",")) { - if (!isValidCIDR(guestCidr)) { + if (!isValidIp4Cidr(guestCidr)) { return false; } } @@ -1297,13 +1171,12 @@ public static boolean validateIcmpCode(final long icmpCode) { return true; } - public static boolean isValidIpv6(final String ip) { - try { - IPv6Address.fromString(ip); - } catch (final IllegalArgumentException ex) { - return false; - } - return true; + public static boolean isValidIp6(final String ip) { + if (ip == null) + return false; + + final InetAddressValidator validator = InetAddressValidator.getInstance(); + return validator.isValidInet6Address(ip); } public static boolean isValidIp6Cidr(final String ip6Cidr) { @@ -1410,15 +1283,16 @@ public static boolean isIp6InRange(final String ip6, final String ip6Range) { return false; } + public static boolean isIp6InNetwork(final IPv6Address ip, final IPv6Network network) { + return network.contains(ip); + } + public static boolean isIp6InNetwork(final String ip6, final String ip6Cidr) { - IPv6Network network = null; try { - network = IPv6Network.fromString(ip6Cidr); + return isIp6InNetwork(IPv6Address.fromString(ip6), IPv6Network.fromString(ip6Cidr)); } catch (final IllegalArgumentException ex) { return false; } - final IPv6Address ip = IPv6Address.fromString(ip6); - return network.contains(ip); } public static boolean isIp6RangeOverlap(final String ipRange1, final String ipRange2) { @@ -1580,11 +1454,11 @@ public static String generateMacOnIncrease(final String baseMac, final long l) { return long2Mac(mac); } - public static boolean isIpWithtInCidrRange(final String ipAddress, final String cidr) { - if (!isValidIp(ipAddress)) { + public static boolean isIpWithInCidrRange(final String ipAddress, final String cidr) { + if (!isValidIp4(ipAddress)) { return false; } - if (!isValidCIDR(cidr)) { + if (!isValidIp4Cidr(cidr)) { return false; } @@ -1602,6 +1476,29 @@ public static boolean isIpWithtInCidrRange(final String ipAddress, final String return isInRange; } + public static boolean isIpInCidrList(final InetAddress address, final String[] cidrlist) { + boolean match = false; + + for (String cidr: cidrlist) { + try { + if (address instanceof Inet6Address && isValidIp6Cidr(cidr)) { + if (isIp6InNetwork(IPv6Address.fromInetAddress(address), IPv6Network.fromString(cidr))) { + match = true; + break; + } + } else if (address instanceof Inet4Address && isValidIp4Cidr(cidr)) { + if (NetUtils.isIpWithInCidrRange(address.getHostAddress(), cidr)) { + match = true; + break; + } + } + } catch (IllegalArgumentException e) { + continue; + } + } + return match; + } + public static Boolean IsIpEqualToNetworkOrBroadCastIp(final String requestedIp, final String cidr, final long size) { assert size < MAX_CIDR : "You do know this is not for ipv6 right? Keep it smaller than 32 but you have " + size; @@ -1647,7 +1544,7 @@ public static IPv6Address EUI64Address(final String cidr, final String macAddres } public static IPv6Address ipv6LinkLocal(final String macAddress) { - return EUI64Address(IPv6Network.fromString("fe80::/64"), macAddress); + return EUI64Address(IPv6Network.LINK_LOCAL_NETWORK, macAddress); } } diff --git a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java index eaa9c29088e7..bec22098b49b 100644 --- a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java +++ b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java @@ -32,9 +32,12 @@ import static org.junit.Assert.assertTrue; import java.math.BigInteger; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.SortedSet; import java.util.TreeSet; +import com.googlecode.ipv6.IPv6Network; import org.apache.log4j.Logger; import org.junit.Test; @@ -198,10 +201,10 @@ public void testIsUnicastMac() { @Test public void testIsValidIpv6() { - assertTrue(NetUtils.isValidIpv6("fc00::1")); - assertFalse(NetUtils.isValidIpv6("")); - assertFalse(NetUtils.isValidIpv6(null)); - assertFalse(NetUtils.isValidIpv6("1234:5678::1/64")); + assertTrue(NetUtils.isValidIp6("fc00::1")); + assertFalse(NetUtils.isValidIp6("")); + assertFalse(NetUtils.isValidIp6(null)); + assertFalse(NetUtils.isValidIp6("1234:5678::1/64")); } @Test @@ -214,10 +217,10 @@ public void testIsIp6InRange() { @Test public void testIsIp6InNetwork() { - assertFalse(NetUtils.isIp6InNetwork("1234:5678:abcd::1", "1234:5678::/64")); - assertTrue(NetUtils.isIp6InNetwork("1234:5678::1", "1234:5678::/64")); - assertTrue(NetUtils.isIp6InNetwork("1234:5678::ffff:ffff:ffff:ffff", "1234:5678::/64")); - assertTrue(NetUtils.isIp6InNetwork("1234:5678::", "1234:5678::/64")); + assertFalse(NetUtils.isIp6InNetwork(IPv6Address.fromString("1234:5678:abcd::1"), IPv6Network.fromString("1234:5678::/64"))); + assertTrue(NetUtils.isIp6InNetwork(IPv6Address.fromString("1234:5678::1"), IPv6Network.fromString("1234:5678::/64"))); + assertTrue(NetUtils.isIp6InNetwork(IPv6Address.fromString("1234:5678::ffff:ffff:ffff:ffff"), IPv6Network.fromString("1234:5678::/64"))); + assertTrue(NetUtils.isIp6InNetwork(IPv6Address.fromString("1234:5678::"), IPv6Network.fromString("1234:5678::/64"))); } @Test @@ -267,13 +270,9 @@ public void testIsValidCIDR() throws Exception { final String cidrSecond = "10.0.151.0/20"; final String cidrThird = "10.0.144.0/21"; - assertTrue(NetUtils.isValidCIDR(cidrFirst)); - assertTrue(NetUtils.isValidCIDR(cidrSecond)); - assertTrue(NetUtils.isValidCIDR(cidrThird)); - assertTrue(NetUtils.isValidCIDR("2001:db8::/64")); - assertTrue(NetUtils.isValidCIDR("2001:db8::/48")); - assertTrue(NetUtils.isValidCIDR("2001:db8:fff::/56")); - assertFalse(NetUtils.isValidCIDR("2001:db8:gggg::/56")); + assertTrue(NetUtils.isValidIp4Cidr(cidrFirst)); + assertTrue(NetUtils.isValidIp4Cidr(cidrSecond)); + assertTrue(NetUtils.isValidIp4Cidr(cidrThird));; } @Test @@ -285,8 +284,6 @@ public void testIsValidCidrList() throws Exception { assertTrue(NetUtils.isValidCidrList(cidrFirst)); assertTrue(NetUtils.isValidCidrList(cidrSecond)); assertTrue(NetUtils.isValidCidrList(cidrThird)); - assertTrue(NetUtils.isValidCidrList("2001:db8::/64,2001:db8:ffff::/48")); - assertTrue(NetUtils.isValidCidrList("2001:db8::/64,2001:db8:ffff::/48,192.168.0.0/24")); } @Test @@ -386,7 +383,7 @@ public void test31BitPrefixStart() { final String ipAddress = "192.168.0.0"; final String cidr = "192.168.0.0/31"; - final boolean isInRange = NetUtils.isIpWithtInCidrRange(ipAddress, cidr); + final boolean isInRange = NetUtils.isIpWithInCidrRange(ipAddress, cidr); assertTrue("Check if the subnetUtils.setInclusiveHostCount(true) has been called.", isInRange); } @@ -396,7 +393,7 @@ public void test31BitPrefixEnd() { final String ipAddress = "192.168.0.1"; final String cidr = "192.168.0.0/31"; - final boolean isInRange = NetUtils.isIpWithtInCidrRange(ipAddress, cidr); + final boolean isInRange = NetUtils.isIpWithInCidrRange(ipAddress, cidr); assertTrue("Check if the subnetUtils.setInclusiveHostCount(true) has been called.", isInRange); } @@ -406,7 +403,7 @@ public void test31BitPrefixFail() { final String ipAddress = "192.168.0.2"; final String cidr = "192.168.0.0/31"; - final boolean isInRange = NetUtils.isIpWithtInCidrRange(ipAddress, cidr); + final boolean isInRange = NetUtils.isIpWithInCidrRange(ipAddress, cidr); assertFalse("Out of the range. Why did it return true?", isInRange); } @@ -462,21 +459,21 @@ public void testIs31PrefixCidr() { public void testGetCidrNetMask() { final String cidr = "10.10.0.0/16"; String netmask = NetUtils.getCidrNetmask("10.10.10.10/16"); - assertTrue(cidr + " does not generate valid netmask " + netmask,NetUtils.isValidNetmask(netmask)); + assertTrue(cidr + " does not generate valid netmask " + netmask,NetUtils.isValidIp4Netmask(netmask)); } @Test public void testGetCidrSubNet() { final String cidr = "10.10.0.0/16"; String subnet = NetUtils.getCidrSubNet("10.10.10.10/16"); - assertTrue(cidr + " does not contain " + subnet,NetUtils.isIpWithtInCidrRange(subnet, cidr)); + assertTrue(cidr + " does not contain " + subnet,NetUtils.isIpWithInCidrRange(subnet, cidr)); } @Test public void testGetCidrSubNetWithWidth() { final String cidr = "10.10.0.0/16"; String subnet = NetUtils.getCidrSubNet("10.10.10.10", 16); - assertTrue(cidr + " does not contain " + subnet,NetUtils.isIpWithtInCidrRange(subnet, cidr)); + assertTrue(cidr + " does not contain " + subnet,NetUtils.isIpWithInCidrRange(subnet, cidr)); } @Test @@ -610,4 +607,75 @@ public void testIPv6LinkLocal() { assertEquals(IPv6Address.fromString("fe80::42:e0ff:fee8:d6a3"), NetUtils.ipv6LinkLocal("02:42:e0:e8:d6:a3")); assertEquals(IPv6Address.fromString("fe80::47a:88ff:fe00:8b"), NetUtils.ipv6LinkLocal("06:7a:88:00:00:8b")); } + + @Test + public void testIsIpInCidrList() throws UnknownHostException { + String[] cidrs = "0.0.0.0/0,::/0".split(","); + System.out.println(NetUtils.isIpInCidrList(InetAddress.getByName("192.168.1.1"), cidrs)); + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("192.168.1.1"), cidrs)); + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("172.16.8.9"), cidrs)); + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("127.0.0.1"), cidrs)); + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("2001:db8:100::1"), cidrs)); + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("::1"), cidrs)); + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("2a01:4f8:130:2192::2"), cidrs)); + + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("127.0.0.1"), "127.0.0.1/8".split(","))); + assertFalse(NetUtils.isIpInCidrList(InetAddress.getByName("192.168.1.1"), "127.0.0.1/8".split(","))); + + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("127.0.0.1"), "127.0.0.1/8,::1/128".split(","))); + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("::1"), "127.0.0.1/8,::1/128".split(","))); + + assertFalse(NetUtils.isIpInCidrList(InetAddress.getByName("192.168.29.47"), "127.0.0.1/8,::1/128".split(","))); + assertFalse(NetUtils.isIpInCidrList(InetAddress.getByName("2001:db8:1938:3ff1::1"), "127.0.0.1/8,::1/128".split(","))); + + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("2a01:4f8:130:2192::2"), "::/0,127.0.0.1".split(","))); + assertTrue(NetUtils.isIpInCidrList(InetAddress.getByName("2001:db8:200:300::1"), "2001:db8:200::/48,127.0.0.1".split(","))); + assertFalse(NetUtils.isIpInCidrList(InetAddress.getByName("2001:db8:200:300::1"), "2001:db8:300::/64,127.0.0.1".split(","))); + assertFalse(NetUtils.isIpInCidrList(InetAddress.getByName("2a01:4f8:130:2192::2"), "2001:db8::/64,127.0.0.1".split(","))); + } + + @Test + public void testIsSiteLocalAddress() { + assertTrue(NetUtils.isSiteLocalAddress("192.168.0.1")); + assertTrue(NetUtils.isSiteLocalAddress("10.0.0.1")); + assertTrue(NetUtils.isSiteLocalAddress("172.16.0.1")); + assertTrue(NetUtils.isSiteLocalAddress("192.168.254.56")); + assertTrue(NetUtils.isSiteLocalAddress("10.254.254.254")); + assertFalse(NetUtils.isSiteLocalAddress("8.8.8.8")); + assertFalse(NetUtils.isSiteLocalAddress("8.8.4.4")); + assertFalse(NetUtils.isSiteLocalAddress("")); + assertFalse(NetUtils.isSiteLocalAddress(null)); + } + + @Test + public void testStaticVariables() { + assertEquals(80, NetUtils.HTTP_PORT); + assertEquals(443, NetUtils.HTTPS_PORT); + assertEquals(500, NetUtils.VPN_PORT); + assertEquals(4500, NetUtils.VPN_NATT_PORT); + assertEquals(1701, NetUtils.VPN_L2TP_PORT); + assertEquals(8081, NetUtils.HAPROXY_STATS_PORT); + + assertEquals("udp", NetUtils.UDP_PROTO); + assertEquals("tcp", NetUtils.TCP_PROTO); + assertEquals("any", NetUtils.ANY_PROTO); + assertEquals("icmp", NetUtils.ICMP_PROTO); + assertEquals("http", NetUtils.HTTP_PROTO); + assertEquals("ssl", NetUtils.SSL_PROTO); + + assertEquals("0.0.0.0/0", NetUtils.ALL_IP4_CIDRS); + assertEquals("::/0", NetUtils.ALL_IP6_CIDRS); + } + + @Test + public void testIsValidPort() { + assertTrue(NetUtils.isValidPort(80)); + assertTrue(NetUtils.isValidPort("80")); + assertTrue(NetUtils.isValidPort(443)); + assertTrue(NetUtils.isValidPort("443")); + assertTrue(NetUtils.isValidPort(0)); + assertTrue(NetUtils.isValidPort(65535)); + assertFalse(NetUtils.isValidPort(-1)); + assertFalse(NetUtils.isValidPort(65536)); + } } diff --git a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java index bece91a98f55..f448741fe54d 100644 --- a/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java +++ b/vmware-base/src/com/cloud/hypervisor/vmware/mo/HypervisorHostHelper.java @@ -1618,7 +1618,7 @@ public static String resolveHostNameInUrl(DatacenterMO dcMo, String url) { } String host = uri.getHost(); - if (NetUtils.isValidIp(host)) { + if (NetUtils.isValidIp4(host)) { s_logger.info("host name in url is already in IP address, url: " + url); return url; }