8344220: Remove calls to SecurityManager and doPrivileged in java.net.InetAddress and sun.net.util.IPAddressUtil after JEP 486 integration
Reviewed-by: jpai, dfuchs, alanb
This commit is contained in:
parent
9527586923
commit
880f9a7b16
@ -28,8 +28,6 @@ package java.net;
|
|||||||
import java.net.spi.InetAddressResolver;
|
import java.net.spi.InetAddressResolver;
|
||||||
import java.net.spi.InetAddressResolverProvider;
|
import java.net.spi.InetAddressResolverProvider;
|
||||||
import java.net.spi.InetAddressResolver.LookupPolicy;
|
import java.net.spi.InetAddressResolver.LookupPolicy;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NavigableSet;
|
import java.util.NavigableSet;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -62,7 +60,6 @@ import jdk.internal.misc.Blocker;
|
|||||||
import jdk.internal.misc.VM;
|
import jdk.internal.misc.VM;
|
||||||
import jdk.internal.vm.annotation.Stable;
|
import jdk.internal.vm.annotation.Stable;
|
||||||
import sun.net.ResolverProviderConfiguration;
|
import sun.net.ResolverProviderConfiguration;
|
||||||
import sun.security.action.*;
|
|
||||||
import sun.net.InetAddressCachePolicy;
|
import sun.net.InetAddressCachePolicy;
|
||||||
import sun.net.util.IPAddressUtil;
|
import sun.net.util.IPAddressUtil;
|
||||||
import sun.nio.cs.UTF_8;
|
import sun.nio.cs.UTF_8;
|
||||||
@ -364,11 +361,11 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
*/
|
*/
|
||||||
static {
|
static {
|
||||||
PREFER_IPV4_STACK_VALUE =
|
PREFER_IPV4_STACK_VALUE =
|
||||||
GetPropertyAction.privilegedGetProperty("java.net.preferIPv4Stack");
|
System.getProperty("java.net.preferIPv4Stack");
|
||||||
PREFER_IPV6_ADDRESSES_VALUE =
|
PREFER_IPV6_ADDRESSES_VALUE =
|
||||||
GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses");
|
System.getProperty("java.net.preferIPv6Addresses");
|
||||||
HOSTS_FILE_NAME =
|
HOSTS_FILE_NAME =
|
||||||
GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file");
|
System.getProperty("jdk.net.hosts.file");
|
||||||
jdk.internal.loader.BootLoader.loadLibrary("net");
|
jdk.internal.loader.BootLoader.loadLibrary("net");
|
||||||
SharedSecrets.setJavaNetInetAddressAccess(
|
SharedSecrets.setJavaNetInetAddressAccess(
|
||||||
new JavaNetInetAddressAccess() {
|
new JavaNetInetAddressAccess() {
|
||||||
@ -440,19 +437,9 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
// Native method to check if IPv6 is available
|
// Native method to check if IPv6 is available
|
||||||
private static native boolean isIPv6Supported();
|
private static native boolean isIPv6Supported();
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@code RuntimePermission("inetAddressResolverProvider")} is
|
|
||||||
* necessary to subclass and instantiate the {@code InetAddressResolverProvider}
|
|
||||||
* class, as well as to obtain resolver from an instance of that class,
|
|
||||||
* and it is also required to obtain the operating system name resolution configurations.
|
|
||||||
*/
|
|
||||||
private static final RuntimePermission INET_ADDRESS_RESOLVER_PERMISSION =
|
|
||||||
new RuntimePermission("inetAddressResolverProvider");
|
|
||||||
|
|
||||||
private static final ReentrantLock RESOLVER_LOCK = new ReentrantLock();
|
private static final ReentrantLock RESOLVER_LOCK = new ReentrantLock();
|
||||||
private static volatile InetAddressResolver bootstrapResolver;
|
private static volatile InetAddressResolver bootstrapResolver;
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static InetAddressResolver resolver() {
|
private static InetAddressResolver resolver() {
|
||||||
InetAddressResolver cns = resolver;
|
InetAddressResolver cns = resolver;
|
||||||
if (cns != null) {
|
if (cns != null) {
|
||||||
@ -476,10 +463,6 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
if (HOSTS_FILE_NAME != null) {
|
if (HOSTS_FILE_NAME != null) {
|
||||||
// The default resolver service is already host file resolver
|
// The default resolver service is already host file resolver
|
||||||
cns = BUILTIN_RESOLVER;
|
cns = BUILTIN_RESOLVER;
|
||||||
} else if (System.getSecurityManager() != null) {
|
|
||||||
PrivilegedAction<InetAddressResolver> pa = InetAddress::loadResolver;
|
|
||||||
cns = AccessController.doPrivileged(
|
|
||||||
pa, null, INET_ADDRESS_RESOLVER_PERMISSION);
|
|
||||||
} else {
|
} else {
|
||||||
cns = loadResolver();
|
cns = loadResolver();
|
||||||
}
|
}
|
||||||
@ -737,25 +720,8 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
* @see InetAddress#getCanonicalHostName
|
* @see InetAddress#getCanonicalHostName
|
||||||
*/
|
*/
|
||||||
public String getHostName() {
|
public String getHostName() {
|
||||||
return getHostName(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the hostname for this address.
|
|
||||||
* If the host is equal to null, then this address refers to any
|
|
||||||
* of the local machine's available network addresses.
|
|
||||||
* this is package private so SocketPermission can make calls into
|
|
||||||
* here without a security check.
|
|
||||||
*
|
|
||||||
* @return the host name for this IP address, or if the operation
|
|
||||||
* is not allowed by the security check, the textual
|
|
||||||
* representation of the IP address.
|
|
||||||
*
|
|
||||||
* @param check make security check if true
|
|
||||||
*/
|
|
||||||
String getHostName(boolean check) {
|
|
||||||
if (holder().getHostName() == null) {
|
if (holder().getHostName() == null) {
|
||||||
holder().hostName = InetAddress.getHostFromNameService(this, check);
|
holder().hostName = InetAddress.getHostFromNameService(this);
|
||||||
}
|
}
|
||||||
return holder().getHostName();
|
return holder().getHostName();
|
||||||
}
|
}
|
||||||
@ -782,45 +748,31 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
String value = canonicalHostName;
|
String value = canonicalHostName;
|
||||||
if (value == null)
|
if (value == null)
|
||||||
canonicalHostName = value =
|
canonicalHostName = value =
|
||||||
InetAddress.getHostFromNameService(this, true);
|
InetAddress.getHostFromNameService(this);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the fully qualified domain name for the given address.
|
* Returns the fully qualified domain name for the given address.
|
||||||
*
|
*
|
||||||
* @param check make security check if true
|
|
||||||
*
|
|
||||||
* @return the fully qualified domain name for the given IP address.
|
* @return the fully qualified domain name for the given IP address.
|
||||||
* If either the operation is not allowed by the security check
|
* If the system-wide resolver wasn't able to determine the
|
||||||
* or the system-wide resolver wasn't able to determine the
|
|
||||||
* fully qualified domain name for the IP address, the textual
|
* fully qualified domain name for the IP address, the textual
|
||||||
* representation of the IP address is returned instead.
|
* representation of the IP address is returned instead.
|
||||||
*/
|
*/
|
||||||
private static String getHostFromNameService(InetAddress addr, boolean check) {
|
private static String getHostFromNameService(InetAddress addr) {
|
||||||
String host;
|
String host;
|
||||||
var resolver = resolver();
|
var resolver = resolver();
|
||||||
try {
|
try {
|
||||||
// first lookup the hostname
|
// first lookup the hostname
|
||||||
host = resolver.lookupByAddress(addr.getAddress());
|
host = resolver.lookupByAddress(addr.getAddress());
|
||||||
|
|
||||||
/* check to see if calling code is allowed to know
|
|
||||||
* the hostname for this IP address, ie, connect to the host
|
|
||||||
*/
|
|
||||||
if (check) {
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
SecurityManager sec = System.getSecurityManager();
|
|
||||||
if (sec != null) {
|
|
||||||
sec.checkConnect(host, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now get all the IP addresses for this hostname,
|
/* now get all the IP addresses for this hostname,
|
||||||
* and make sure one of them matches the original IP
|
* and make sure one of them matches the original IP
|
||||||
* address. We do this to try and prevent spoofing.
|
* address. We do this to try and prevent spoofing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
InetAddress[] arr = InetAddress.getAllByName0(host, check);
|
InetAddress[] arr = InetAddress.getAllByName0(host);
|
||||||
boolean ok = false;
|
boolean ok = false;
|
||||||
|
|
||||||
if (arr != null) {
|
if (arr != null) {
|
||||||
@ -1613,7 +1565,7 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
// and ends with square brackets, but we got something else.
|
// and ends with square brackets, but we got something else.
|
||||||
throw invalidIPv6LiteralException(host, true);
|
throw invalidIPv6LiteralException(host, true);
|
||||||
}
|
}
|
||||||
return getAllByName0(host, true, true);
|
return getAllByName0(host, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UnknownHostException invalidIPv6LiteralException(String host, boolean wrapInBrackets) {
|
private static UnknownHostException invalidIPv6LiteralException(String host, boolean wrapInBrackets) {
|
||||||
@ -1639,9 +1591,8 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
/**
|
/**
|
||||||
* package private so SocketPermission can call it
|
* package private so SocketPermission can call it
|
||||||
*/
|
*/
|
||||||
static InetAddress[] getAllByName0 (String host, boolean check)
|
static InetAddress[] getAllByName0(String host) throws UnknownHostException {
|
||||||
throws UnknownHostException {
|
return getAllByName0(host, true);
|
||||||
return getAllByName0(host, check, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1682,30 +1633,16 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
* Designated lookup method.
|
* Designated lookup method.
|
||||||
*
|
*
|
||||||
* @param host host name to look up
|
* @param host host name to look up
|
||||||
* @param check perform security check
|
|
||||||
* @param useCache use cached value if not expired else always
|
* @param useCache use cached value if not expired else always
|
||||||
* perform name service lookup (and cache the result)
|
* perform name service lookup (and cache the result)
|
||||||
* @return array of InetAddress(es)
|
* @return array of InetAddress(es)
|
||||||
* @throws UnknownHostException if host name is not found
|
* @throws UnknownHostException if host name is not found
|
||||||
*/
|
*/
|
||||||
private static InetAddress[] getAllByName0(String host,
|
private static InetAddress[] getAllByName0(String host,
|
||||||
boolean check,
|
|
||||||
boolean useCache)
|
boolean useCache)
|
||||||
throws UnknownHostException {
|
throws UnknownHostException {
|
||||||
|
|
||||||
/* If it gets here it is presumed to be a hostname */
|
/* If it gets here it is presumed to be a hostname */
|
||||||
|
|
||||||
/* make sure the connection to the host is allowed, before we
|
|
||||||
* give out a hostname
|
|
||||||
*/
|
|
||||||
if (check) {
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
SecurityManager security = System.getSecurityManager();
|
|
||||||
if (security != null) {
|
|
||||||
security.checkConnect(host, -1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove expired addresses from cache - expirySet keeps them ordered
|
// remove expired addresses from cache - expirySet keeps them ordered
|
||||||
// by expiry time so we only need to iterate the prefix of the NavigableSet...
|
// by expiry time so we only need to iterate the prefix of the NavigableSet...
|
||||||
long now = System.nanoTime();
|
long now = System.nanoTime();
|
||||||
@ -1822,48 +1759,33 @@ public sealed class InetAddress implements Serializable permits Inet4Address, In
|
|||||||
* @see java.net.InetAddress#getByName(java.lang.String)
|
* @see java.net.InetAddress#getByName(java.lang.String)
|
||||||
*/
|
*/
|
||||||
public static InetAddress getLocalHost() throws UnknownHostException {
|
public static InetAddress getLocalHost() throws UnknownHostException {
|
||||||
|
// is cached data still valid?
|
||||||
@SuppressWarnings("removal")
|
CachedLocalHost clh = cachedLocalHost;
|
||||||
SecurityManager security = System.getSecurityManager();
|
if (clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) {
|
||||||
try {
|
return clh.addr;
|
||||||
// is cached data still valid?
|
|
||||||
CachedLocalHost clh = cachedLocalHost;
|
|
||||||
if (clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) {
|
|
||||||
if (security != null) {
|
|
||||||
security.checkConnect(clh.host, -1);
|
|
||||||
}
|
|
||||||
return clh.addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
String local = impl.getLocalHostName();
|
|
||||||
|
|
||||||
if (security != null) {
|
|
||||||
security.checkConnect(local, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
InetAddress localAddr;
|
|
||||||
if (local.equals("localhost")) {
|
|
||||||
// shortcut for "localhost" host name
|
|
||||||
localAddr = impl.loopbackAddress();
|
|
||||||
} else {
|
|
||||||
// call getAllByName0 without security checks and
|
|
||||||
// without using cached data
|
|
||||||
try {
|
|
||||||
localAddr = getAllByName0(local, false, false)[0];
|
|
||||||
} catch (UnknownHostException uhe) {
|
|
||||||
// Rethrow with a more informative error message.
|
|
||||||
UnknownHostException uhe2 =
|
|
||||||
new UnknownHostException(local + ": " +
|
|
||||||
uhe.getMessage());
|
|
||||||
uhe2.initCause(uhe);
|
|
||||||
throw uhe2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cachedLocalHost = new CachedLocalHost(local, localAddr);
|
|
||||||
return localAddr;
|
|
||||||
} catch (java.lang.SecurityException e) {
|
|
||||||
return impl.loopbackAddress();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String local = impl.getLocalHostName();
|
||||||
|
|
||||||
|
InetAddress localAddr;
|
||||||
|
if (local.equals("localhost")) {
|
||||||
|
// shortcut for "localhost" host name
|
||||||
|
localAddr = impl.loopbackAddress();
|
||||||
|
} else {
|
||||||
|
// call getAllByName0 without using cached data
|
||||||
|
try {
|
||||||
|
localAddr = getAllByName0(local, false)[0];
|
||||||
|
} catch (UnknownHostException uhe) {
|
||||||
|
// Rethrow with a more informative error message.
|
||||||
|
UnknownHostException uhe2 =
|
||||||
|
new UnknownHostException(local + ": " +
|
||||||
|
uhe.getMessage());
|
||||||
|
uhe2.initCause(uhe);
|
||||||
|
throw uhe2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cachedLocalHost = new CachedLocalHost(local, localAddr);
|
||||||
|
return localAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,10 +30,8 @@ import java.io.ObjectInputStream;
|
|||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.ObjectStreamField;
|
import java.io.ObjectStreamField;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.Permission;
|
import java.security.Permission;
|
||||||
import java.security.PermissionCollection;
|
import java.security.PermissionCollection;
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -638,10 +636,10 @@ public final class SocketPermission extends Permission
|
|||||||
// we have to do this check, otherwise we might not
|
// we have to do this check, otherwise we might not
|
||||||
// get the fully qualified domain name
|
// get the fully qualified domain name
|
||||||
if (init_with_ip) {
|
if (init_with_ip) {
|
||||||
cname = addresses[0].getHostName(false).toLowerCase(Locale.ROOT);
|
cname = addresses[0].getHostName().toLowerCase(Locale.ROOT);
|
||||||
} else {
|
} else {
|
||||||
cname = InetAddress.getByName(addresses[0].getHostAddress()).
|
cname = InetAddress.getByName(addresses[0].getHostAddress()).
|
||||||
getHostName(false).toLowerCase(Locale.ROOT);
|
getHostName().toLowerCase(Locale.ROOT);
|
||||||
}
|
}
|
||||||
} catch (UnknownHostException uhe) {
|
} catch (UnknownHostException uhe) {
|
||||||
invalid = true;
|
invalid = true;
|
||||||
@ -705,7 +703,7 @@ public final class SocketPermission extends Permission
|
|||||||
// Following check seems unnecessary
|
// Following check seems unnecessary
|
||||||
// auth = InetAddress.getAllByName0(authHost, false)[0];
|
// auth = InetAddress.getAllByName0(authHost, false)[0];
|
||||||
authHost = hostname + '.' + authHost;
|
authHost = hostname + '.' + authHost;
|
||||||
auth = InetAddress.getAllByName0(authHost, false)[0];
|
auth = InetAddress.getAllByName0(authHost)[0];
|
||||||
if (auth.equals(InetAddress.getByAddress(addr))) {
|
if (auth.equals(InetAddress.getByAddress(addr))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -736,9 +734,8 @@ public final class SocketPermission extends Permission
|
|||||||
sb.append('.');
|
sb.append('.');
|
||||||
}
|
}
|
||||||
authHost = "auth." + sb.toString() + "IP6.ARPA";
|
authHost = "auth." + sb.toString() + "IP6.ARPA";
|
||||||
//auth = InetAddress.getAllByName0(authHost, false)[0];
|
|
||||||
authHost = hostname + '.' + authHost;
|
authHost = hostname + '.' + authHost;
|
||||||
auth = InetAddress.getAllByName0(authHost, false)[0];
|
auth = InetAddress.getAllByName0(authHost)[0];
|
||||||
if (auth.equals(InetAddress.getByAddress(addr)))
|
if (auth.equals(InetAddress.getByAddress(addr)))
|
||||||
return true;
|
return true;
|
||||||
Debug debug = getDebug();
|
Debug debug = getDebug();
|
||||||
@ -780,7 +777,7 @@ public final class SocketPermission extends Permission
|
|||||||
}
|
}
|
||||||
|
|
||||||
addresses =
|
addresses =
|
||||||
new InetAddress[] {InetAddress.getAllByName0(host, false)[0]};
|
new InetAddress[] {InetAddress.getAllByName0(host)[0]};
|
||||||
|
|
||||||
} catch (UnknownHostException uhe) {
|
} catch (UnknownHostException uhe) {
|
||||||
invalid = true;
|
invalid = true;
|
||||||
@ -1191,23 +1188,15 @@ public final class SocketPermission extends Permission
|
|||||||
* Check the system/security property for the ephemeral port range
|
* Check the system/security property for the ephemeral port range
|
||||||
* for this system. The suffix is either "high" or "low"
|
* for this system. The suffix is either "high" or "low"
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static int initEphemeralPorts(String suffix) {
|
private static int initEphemeralPorts(String suffix) {
|
||||||
return AccessController.doPrivileged(
|
int val = Integer.getInteger(
|
||||||
new PrivilegedAction<>(){
|
"jdk.net.ephemeralPortRange." + suffix, -1);
|
||||||
public Integer run() {
|
if (val != -1) {
|
||||||
int val = Integer.getInteger(
|
return val;
|
||||||
"jdk.net.ephemeralPortRange."+suffix, -1
|
} else {
|
||||||
);
|
return suffix.equals("low") ?
|
||||||
if (val != -1) {
|
PortConfig.getLower() : PortConfig.getUpper();
|
||||||
return val;
|
}
|
||||||
} else {
|
|
||||||
return suffix.equals("low") ?
|
|
||||||
PortConfig.getLower() : PortConfig.getUpper();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -279,8 +279,7 @@ tuning on how the cache is operating.</P>
|
|||||||
name lookups will be kept in the cache. A value of -1, or any other
|
name lookups will be kept in the cache. A value of -1, or any other
|
||||||
negative value for that matter, indicates a “cache forever”
|
negative value for that matter, indicates a “cache forever”
|
||||||
policy, while a value of 0 (zero) means no caching. The default value
|
policy, while a value of 0 (zero) means no caching. The default value
|
||||||
is -1 (forever) if a security manager is installed, and implementation-specific
|
is implementation-specific.</P>
|
||||||
when no security manager is installed.</P>
|
|
||||||
<LI><P><B>{@code networkaddress.cache.stale.ttl}</B> (default: see below)<BR>
|
<LI><P><B>{@code networkaddress.cache.stale.ttl}</B> (default: see below)<BR>
|
||||||
Value is an integer corresponding to the number of seconds that stale names
|
Value is an integer corresponding to the number of seconds that stale names
|
||||||
will be kept in the cache. A name is considered stale if the TTL has expired
|
will be kept in the cache. A name is considered stale if the TTL has expired
|
||||||
|
@ -98,15 +98,6 @@ public abstract class InetAddressResolverProvider {
|
|||||||
*/
|
*/
|
||||||
public abstract String name();
|
public abstract String name();
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@code RuntimePermission("inetAddressResolverProvider")} is
|
|
||||||
* necessary to subclass and instantiate the {@code InetAddressResolverProvider} class,
|
|
||||||
* as well as to obtain resolver from an instance of that class,
|
|
||||||
* and it is also required to obtain the operating system name resolution configurations.
|
|
||||||
*/
|
|
||||||
private static final RuntimePermission INET_ADDRESS_RESOLVER_PERMISSION =
|
|
||||||
new RuntimePermission("inetAddressResolverProvider");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance of {@code InetAddressResolverProvider}.
|
* Creates a new instance of {@code InetAddressResolverProvider}.
|
||||||
*
|
*
|
||||||
@ -116,19 +107,6 @@ public abstract class InetAddressResolverProvider {
|
|||||||
* service provider.
|
* service provider.
|
||||||
*/
|
*/
|
||||||
protected InetAddressResolverProvider() {
|
protected InetAddressResolverProvider() {
|
||||||
this(checkPermission());
|
|
||||||
}
|
|
||||||
|
|
||||||
private InetAddressResolverProvider(Void unused) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static Void checkPermission() {
|
|
||||||
final SecurityManager sm = System.getSecurityManager();
|
|
||||||
if (sm != null) {
|
|
||||||
sm.checkPermission(INET_ADDRESS_RESOLVER_PERMISSION);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,11 +25,8 @@
|
|||||||
|
|
||||||
package sun.net;
|
package sun.net;
|
||||||
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
public final class InetAddressCachePolicy {
|
public final class InetAddressCachePolicy {
|
||||||
|
|
||||||
// Controls the cache policy for successful lookups only
|
// Controls the cache policy for successful lookups only
|
||||||
@ -60,11 +57,9 @@ public final class InetAddressCachePolicy {
|
|||||||
* -1: caching forever
|
* -1: caching forever
|
||||||
* any positive value: the number of seconds to cache an address for
|
* any positive value: the number of seconds to cache an address for
|
||||||
*
|
*
|
||||||
* default value is forever (FOREVER), as we let the platform do the
|
* default value is 30 seconds
|
||||||
* caching. For security reasons, this caching is made forever when
|
|
||||||
* a security manager is set.
|
|
||||||
*/
|
*/
|
||||||
private static volatile int cachePolicy = FOREVER;
|
private static volatile int cachePolicy = DEFAULT_POSITIVE;
|
||||||
|
|
||||||
/* The Java-level namelookup cache stale policy:
|
/* The Java-level namelookup cache stale policy:
|
||||||
*
|
*
|
||||||
@ -85,40 +80,22 @@ public final class InetAddressCachePolicy {
|
|||||||
*/
|
*/
|
||||||
private static volatile int negativeCachePolicy = NEVER;
|
private static volatile int negativeCachePolicy = NEVER;
|
||||||
|
|
||||||
/*
|
|
||||||
* Whether or not the cache policy for successful lookups was set
|
|
||||||
* using a property (cmd line).
|
|
||||||
*/
|
|
||||||
private static boolean propertySet;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Whether or not the cache policy for negative lookups was set
|
|
||||||
* using a property (cmd line).
|
|
||||||
*/
|
|
||||||
private static boolean propertyNegativeSet;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize
|
* Initialize
|
||||||
*/
|
*/
|
||||||
static {
|
static {
|
||||||
|
/* If the cache policy property is not specified
|
||||||
|
* then the default positive cache value is used.
|
||||||
|
*/
|
||||||
Integer tmp = getProperty(cachePolicyProp, cachePolicyPropFallback);
|
Integer tmp = getProperty(cachePolicyProp, cachePolicyPropFallback);
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
cachePolicy = tmp < 0 ? FOREVER : tmp;
|
cachePolicy = tmp < 0 ? FOREVER : tmp;
|
||||||
propertySet = true;
|
|
||||||
} else {
|
|
||||||
/* No properties defined for positive caching. If there is no
|
|
||||||
* security manager then use the default positive cache value.
|
|
||||||
*/
|
|
||||||
if (System.getSecurityManager() == null) {
|
|
||||||
cachePolicy = DEFAULT_POSITIVE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tmp = getProperty(negativeCachePolicyProp,
|
tmp = getProperty(negativeCachePolicyProp,
|
||||||
negativeCachePolicyPropFallback);
|
negativeCachePolicyPropFallback);
|
||||||
|
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
negativeCachePolicy = tmp < 0 ? FOREVER : tmp;
|
negativeCachePolicy = tmp < 0 ? FOREVER : tmp;
|
||||||
propertyNegativeSet = true;
|
|
||||||
}
|
}
|
||||||
if (cachePolicy > 0) {
|
if (cachePolicy > 0) {
|
||||||
tmp = getProperty(cacheStalePolicyProp,
|
tmp = getProperty(cacheStalePolicyProp,
|
||||||
@ -130,33 +107,25 @@ public final class InetAddressCachePolicy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Integer getProperty(String cachePolicyProp,
|
private static Integer getProperty(String cachePolicyProp,
|
||||||
String cachePolicyPropFallback)
|
String cachePolicyPropFallback) {
|
||||||
{
|
try {
|
||||||
return java.security.AccessController.doPrivileged(
|
String tmpString = Security.getProperty(cachePolicyProp);
|
||||||
new PrivilegedAction<Integer>() {
|
if (tmpString != null) {
|
||||||
public Integer run() {
|
return Integer.valueOf(tmpString);
|
||||||
try {
|
}
|
||||||
String tmpString = Security.getProperty(
|
} catch (NumberFormatException ignored) {
|
||||||
cachePolicyProp);
|
// Ignore
|
||||||
if (tmpString != null) {
|
}
|
||||||
return Integer.valueOf(tmpString);
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String tmpString = System.getProperty(
|
String tmpString = System.getProperty(cachePolicyPropFallback);
|
||||||
cachePolicyPropFallback);
|
if (tmpString != null) {
|
||||||
if (tmpString != null) {
|
return Integer.decode(tmpString);
|
||||||
return Integer.decode(tmpString);
|
}
|
||||||
}
|
} catch (NumberFormatException ignored) {
|
||||||
} catch (NumberFormatException ignored) {
|
// Ignore
|
||||||
// Ignore
|
}
|
||||||
}
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int get() {
|
public static int get() {
|
||||||
@ -170,63 +139,4 @@ public final class InetAddressCachePolicy {
|
|||||||
public static int getNegative() {
|
public static int getNegative() {
|
||||||
return negativeCachePolicy;
|
return negativeCachePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the cache policy for successful lookups if the user has not
|
|
||||||
* already specified a cache policy for it using a
|
|
||||||
* command-property.
|
|
||||||
* @param newPolicy the value in seconds for how long the lookup
|
|
||||||
* should be cached
|
|
||||||
*/
|
|
||||||
public static synchronized void setIfNotSet(int newPolicy) {
|
|
||||||
/*
|
|
||||||
* When setting the new value we may want to signal that the
|
|
||||||
* cache should be flushed, though this doesn't seem strictly
|
|
||||||
* necessary.
|
|
||||||
*/
|
|
||||||
if (!propertySet) {
|
|
||||||
checkValue(newPolicy, cachePolicy);
|
|
||||||
cachePolicy = newPolicy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the cache policy for negative lookups if the user has not
|
|
||||||
* already specified a cache policy for it using a
|
|
||||||
* command-property.
|
|
||||||
* @param newPolicy the value in seconds for how long the lookup
|
|
||||||
* should be cached
|
|
||||||
*/
|
|
||||||
public static void setNegativeIfNotSet(int newPolicy) {
|
|
||||||
/*
|
|
||||||
* When setting the new value we may want to signal that the
|
|
||||||
* cache should be flushed, though this doesn't seem strictly
|
|
||||||
* necessary.
|
|
||||||
*/
|
|
||||||
if (!propertyNegativeSet) {
|
|
||||||
// Negative caching does not seem to have any security
|
|
||||||
// implications.
|
|
||||||
// checkValue(newPolicy, negativeCachePolicy);
|
|
||||||
// but we should normalize negative policy
|
|
||||||
negativeCachePolicy = newPolicy < 0 ? FOREVER : newPolicy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void checkValue(int newPolicy, int oldPolicy) {
|
|
||||||
/*
|
|
||||||
* If malicious code gets a hold of this method, prevent
|
|
||||||
* setting the cache policy to something laxer or some
|
|
||||||
* invalid negative value.
|
|
||||||
*/
|
|
||||||
if (newPolicy == FOREVER)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((oldPolicy == FOREVER) ||
|
|
||||||
(newPolicy < oldPolicy) ||
|
|
||||||
(newPolicy < FOREVER)) {
|
|
||||||
|
|
||||||
throw new
|
|
||||||
SecurityException("can't make InetAddress cache more lax");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
package sun.net.util;
|
package sun.net.util;
|
||||||
|
|
||||||
import sun.security.action.GetPropertyAction;
|
|
||||||
|
|
||||||
import java.io.UncheckedIOException;
|
import java.io.UncheckedIOException;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@ -35,9 +33,6 @@ import java.net.NetworkInterface;
|
|||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.CharBuffer;
|
import java.nio.CharBuffer;
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.PrivilegedExceptionAction;
|
|
||||||
import java.security.PrivilegedActionException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
@ -396,25 +391,23 @@ public class IPAddressUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("removal")
|
|
||||||
private static InetAddress findScopedAddress(InetAddress address) {
|
private static InetAddress findScopedAddress(InetAddress address) {
|
||||||
PrivilegedExceptionAction<List<InetAddress>> pa = () -> NetworkInterface.networkInterfaces()
|
|
||||||
.flatMap(NetworkInterface::inetAddresses)
|
|
||||||
.filter(a -> (a instanceof Inet6Address)
|
|
||||||
&& address.equals(a)
|
|
||||||
&& ((Inet6Address) a).getScopeId() != 0)
|
|
||||||
.toList();
|
|
||||||
List<InetAddress> result;
|
|
||||||
try {
|
try {
|
||||||
result = AccessController.doPrivileged(pa);
|
List<InetAddress> result = NetworkInterface.networkInterfaces()
|
||||||
|
.flatMap(NetworkInterface::inetAddresses)
|
||||||
|
.filter(a -> (a instanceof Inet6Address)
|
||||||
|
&& address.equals(a)
|
||||||
|
&& ((Inet6Address) a).getScopeId() != 0)
|
||||||
|
.toList();
|
||||||
|
|
||||||
var sz = result.size();
|
var sz = result.size();
|
||||||
if (sz == 0)
|
if (sz == 0)
|
||||||
return null;
|
return null;
|
||||||
if (sz > 1)
|
if (sz > 1)
|
||||||
throw new UncheckedIOException(new SocketException(
|
throw new UncheckedIOException(new SocketException(
|
||||||
"Duplicate link local addresses: must specify scope-id"));
|
"Duplicate link local addresses: must specify scope-id"));
|
||||||
return result.get(0);
|
return result.get(0);
|
||||||
} catch (PrivilegedActionException pae) {
|
} catch (SocketException socketException) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -927,8 +920,8 @@ public class IPAddressUtil {
|
|||||||
private static final long TERMINAL_PARSE_ERROR = -2L;
|
private static final long TERMINAL_PARSE_ERROR = -2L;
|
||||||
|
|
||||||
private static final String ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP = "jdk.net.allowAmbiguousIPAddressLiterals";
|
private static final String ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP = "jdk.net.allowAmbiguousIPAddressLiterals";
|
||||||
private static final boolean ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP_VALUE = Boolean.valueOf(
|
private static final boolean ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP_VALUE =
|
||||||
GetPropertyAction.privilegedGetProperty(ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP, "false"));
|
Boolean.getBoolean(ALLOW_AMBIGUOUS_IPADDRESS_LITERALS_SP);
|
||||||
private static class MASKS {
|
private static class MASKS {
|
||||||
private static final String DELAY_URL_PARSING_SP = "jdk.net.url.delayParsing";
|
private static final String DELAY_URL_PARSING_SP = "jdk.net.url.delayParsing";
|
||||||
private static final boolean DELAY_URL_PARSING_SP_VALUE;
|
private static final boolean DELAY_URL_PARSING_SP_VALUE;
|
||||||
@ -939,8 +932,7 @@ public class IPAddressUtil {
|
|||||||
static final long L_SCOPE_MASK;
|
static final long L_SCOPE_MASK;
|
||||||
static final long H_SCOPE_MASK;
|
static final long H_SCOPE_MASK;
|
||||||
static {
|
static {
|
||||||
var value = GetPropertyAction.privilegedGetProperty(
|
var value = System.getProperty(DELAY_URL_PARSING_SP, "false");
|
||||||
DELAY_URL_PARSING_SP, "false");
|
|
||||||
DELAY_URL_PARSING_SP_VALUE = value.isEmpty()
|
DELAY_URL_PARSING_SP_VALUE = value.isEmpty()
|
||||||
|| Boolean.parseBoolean(value);
|
|| Boolean.parseBoolean(value);
|
||||||
if (DELAY_URL_PARSING_SP_VALUE) {
|
if (DELAY_URL_PARSING_SP_VALUE) {
|
||||||
|
Loading…
Reference in New Issue
Block a user