From 56293e941e7ecc5c93eac990243155e91c102e7a Mon Sep 17 00:00:00 2001 From: khazra Date: Thu, 28 Mar 2013 14:34:18 -0700 Subject: [PATCH] 8001318: Socket.getLocalAddress not consistent with InetAddress.getLocalHost Reviewed-by: alanb, chegar, hawtin --- src/share/classes/java/net/ServerSocket.java | 50 ++++++++++++++++--- src/share/classes/java/net/Socket.java | 38 +++++++++++--- .../classes/java/net/SocksSocketImpl.java | 9 +++- .../AsynchronousServerSocketChannel.java | 21 ++++++++ .../channels/AsynchronousSocketChannel.java | 20 ++++++++ .../java/nio/channels/DatagramChannel.java | 21 ++++++++ .../java/nio/channels/NetworkChannel.java | 3 +- .../nio/channels/ServerSocketChannel.java | 21 ++++++++ .../java/nio/channels/SocketChannel.java | 21 ++++++++ src/share/classes/sun/net/NetworkClient.java | 8 ++- .../classes/sun/net/ftp/impl/FtpClient.java | 20 ++++++-- .../sun/net/httpserver/ServerImpl.java | 11 +++- .../AsynchronousServerSocketChannelImpl.java | 6 +-- .../nio/ch/AsynchronousSocketChannelImpl.java | 9 ++-- .../sun/nio/ch/DatagramChannelImpl.java | 12 +++-- src/share/classes/sun/nio/ch/Net.java | 29 +++++++++++ .../sun/nio/ch/ServerSocketAdaptor.java | 3 +- .../sun/nio/ch/ServerSocketChannelImpl.java | 17 ++++--- .../classes/sun/nio/ch/SocketAdaptor.java | 7 +-- .../classes/sun/nio/ch/SocketChannelImpl.java | 14 +++--- .../classes/sun/rmi/server/Activation.java | 16 +++++- .../rmi/transport/proxy/WrappedSocket.java | 11 +++- .../ch/UnixAsynchronousSocketChannelImpl.java | 2 +- .../classes/sun/nio/ch/sctp/SctpNet.java | 34 +++++++++++-- .../WindowsAsynchronousSocketChannelImpl.java | 4 +- 25 files changed, 346 insertions(+), 61 deletions(-) diff --git a/src/share/classes/java/net/ServerSocket.java b/src/share/classes/java/net/ServerSocket.java index 887a1e7de..2cb24a1f5 100644 --- a/src/share/classes/java/net/ServerSocket.java +++ b/src/share/classes/java/net/ServerSocket.java @@ -390,15 +390,29 @@ class ServerSocket implements java.io.Closeable { * If the socket was bound prior to being {@link #close closed}, * then this method will continue to return the local address * after the socket is closed. + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * the {@link InetAddress#getLoopbackAddress loopback} address is returned. * * @return the address to which this socket is bound, - * or null if the socket is unbound. + * or the loopback address if denied by the security manager, + * or {@code null} if the socket is unbound. + * + * @see SecurityManager#checkConnect */ public InetAddress getInetAddress() { if (!isBound()) return null; try { - return getImpl().getInetAddress(); + InetAddress in = getImpl().getInetAddress(); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkConnect(in.getHostAddress(), -1); + return in; + } catch (SecurityException e) { + return InetAddress.getLoopbackAddress(); } catch (SocketException e) { // nothing // If we're bound, the impl has been created @@ -431,18 +445,28 @@ class ServerSocket implements java.io.Closeable { } /** - * Returns the address of the endpoint this socket is bound to, or - * null if it is not bound yet. + * Returns the address of the endpoint this socket is bound to. *

* If the socket was bound prior to being {@link #close closed}, * then this method will continue to return the address of the endpoint * after the socket is closed. + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * a {@code SocketAddress} representing the + * {@link InetAddress#getLoopbackAddress loopback} address and the local + * port to which the socket is bound is returned. + * + * @return a {@code SocketAddress} representing the local endpoint of + * this socket, or a {@code SocketAddress} representing the + * loopback address if denied by the security manager, + * or {@code null} if the socket is not bound yet. * - * @return a SocketAddress representing the local endpoint of this - * socket, or null if it is not bound yet. * @see #getInetAddress() * @see #getLocalPort() * @see #bind(SocketAddress) + * @see SecurityManager#checkConnect * @since 1.4 */ @@ -708,13 +732,25 @@ class ServerSocket implements java.io.Closeable { /** * Returns the implementation address and implementation port of * this socket as a String. + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * an {@code InetAddress} representing the + * {@link InetAddress#getLoopbackAddress loopback} address is returned as + * the implementation address. * * @return a string representation of this socket. */ public String toString() { if (!isBound()) return "ServerSocket[unbound]"; - return "ServerSocket[addr=" + impl.getInetAddress() + + InetAddress in; + if (System.getSecurityManager() != null) + in = InetAddress.getLoopbackAddress(); + else + in = impl.getInetAddress(); + return "ServerSocket[addr=" + in + ",localport=" + impl.getLocalPort() + "]"; } diff --git a/src/share/classes/java/net/Socket.java b/src/share/classes/java/net/Socket.java index d4f28e9ab..e28e86aad 100644 --- a/src/share/classes/java/net/Socket.java +++ b/src/share/classes/java/net/Socket.java @@ -682,11 +682,18 @@ class Socket implements java.io.Closeable { /** * Gets the local address to which the socket is bound. - * - * @return the local address to which the socket is bound, or - * the {@link InetAddress#isAnyLocalAddress wildcard} address - * if the socket is closed or not bound yet. + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * the {@link InetAddress#getLoopbackAddress loopback} address is returned. + * + * @return the local address to which the socket is bound, + * the loopback address if denied by the security manager, or + * the wildcard address if the socket is closed or not bound yet. * @since JDK1.1 + * + * @see SecurityManager#checkConnect */ public InetAddress getLocalAddress() { // This is for backward compatibility @@ -695,9 +702,14 @@ class Socket implements java.io.Closeable { InetAddress in = null; try { in = (InetAddress) getImpl().getOption(SocketOptions.SO_BINDADDR); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) + sm.checkConnect(in.getHostAddress(), -1); if (in.isAnyLocalAddress()) { in = InetAddress.anyLocalAddress(); } + } catch (SecurityException e) { + in = InetAddress.getLoopbackAddress(); } catch (Exception e) { in = InetAddress.anyLocalAddress(); // "0.0.0.0" } @@ -770,8 +782,7 @@ class Socket implements java.io.Closeable { } /** - * Returns the address of the endpoint this socket is bound to, or - * null if it is not bound yet. + * Returns the address of the endpoint this socket is bound to. *

* If a socket bound to an endpoint represented by an * InetSocketAddress is {@link #close closed}, @@ -780,12 +791,23 @@ class Socket implements java.io.Closeable { * InetSocketAddress's address is the * {@link InetAddress#isAnyLocalAddress wildcard} address * and its port is the local port that it was bound to. + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * a {@code SocketAddress} representing the + * {@link InetAddress#getLoopbackAddress loopback} address and the local + * port to which this socket is bound is returned. + * + * @return a {@code SocketAddress} representing the local endpoint of + * this socket, or a {@code SocketAddress} representing the + * loopback address if denied by the security manager, or + * {@code null} if the socket is not bound yet. * - * @return a SocketAddress representing the local endpoint of this - * socket, or null if it is not bound yet. * @see #getLocalAddress() * @see #getLocalPort() * @see #bind(SocketAddress) + * @see SecurityManager#checkConnect * @since 1.4 */ diff --git a/src/share/classes/java/net/SocksSocketImpl.java b/src/share/classes/java/net/SocksSocketImpl.java index dec3eb387..16155d2f1 100644 --- a/src/share/classes/java/net/SocksSocketImpl.java +++ b/src/share/classes/java/net/SocksSocketImpl.java @@ -28,6 +28,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.BufferedOutputStream; import java.security.AccessController; +import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import sun.net.SocksProxy; import sun.net.www.ParseUtil; @@ -590,7 +591,13 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { /* Test for AnyLocal */ InetAddress naddr = baddr; if (naddr.isAnyLocalAddress()) { - naddr = cmdsock.getLocalAddress(); + naddr = AccessController.doPrivileged( + new PrivilegedAction() { + public InetAddress run() { + return cmdsock.getLocalAddress(); + + } + }); addr1 = naddr.getAddress(); } out.write(PROTO_VERS4); diff --git a/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java b/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java index 471b53571..59e398223 100644 --- a/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java +++ b/src/share/classes/java/nio/channels/AsynchronousServerSocketChannel.java @@ -297,4 +297,25 @@ public abstract class AsynchronousServerSocketChannel * If this channel's socket has not yet been bound */ public abstract Future accept(); + + /** + * {@inheritDoc} + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * a {@code SocketAddress} representing the + * {@link java.net.InetAddress#getLoopbackAddress loopback} address and the + * local port of the channel's socket is returned. + * + * @return The {@code SocketAddress} that the socket is bound to, or the + * {@code SocketAddress} representing the loopback address if + * denied by the security manager, or {@code null} if the + * channel's socket is not bound + * + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + @Override + public abstract SocketAddress getLocalAddress() throws IOException; } diff --git a/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java b/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java index 8cde54dd7..74c93c872 100644 --- a/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java +++ b/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java @@ -645,4 +645,24 @@ public abstract class AsynchronousSocketChannel TimeUnit unit, A attachment, CompletionHandler handler); + + /** + * {@inheritDoc} + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * a {@code SocketAddress} representing the + * {@link java.net.InetAddress#getLoopbackAddress loopback} address and the + * local port of the channel's socket is returned. + * + * @return The {@code SocketAddress} that the socket is bound to, or the + * {@code SocketAddress} representing the loopback address if + * denied by the security manager, or {@code null} if the + * channel's socket is not bound + * + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + public abstract SocketAddress getLocalAddress() throws IOException; } diff --git a/src/share/classes/java/nio/channels/DatagramChannel.java b/src/share/classes/java/nio/channels/DatagramChannel.java index 74505d8ce..fd8b920ee 100644 --- a/src/share/classes/java/nio/channels/DatagramChannel.java +++ b/src/share/classes/java/nio/channels/DatagramChannel.java @@ -565,4 +565,25 @@ public abstract class DatagramChannel return write(srcs, 0, srcs.length); } + /** + * {@inheritDoc} + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * a {@code SocketAddress} representing the + * {@link java.net.InetAddress#getLoopbackAddress loopback} address and the + * local port of the channel's socket is returned. + * + * @return The {@code SocketAddress} that the socket is bound to, or the + * {@code SocketAddress} representing the loopback address if + * denied by the security manager, or {@code null} if the + * channel's socket is not bound + * + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + @Override + public abstract SocketAddress getLocalAddress() throws IOException; + } diff --git a/src/share/classes/java/nio/channels/NetworkChannel.java b/src/share/classes/java/nio/channels/NetworkChannel.java index b2ed0f249..3900f9d28 100644 --- a/src/share/classes/java/nio/channels/NetworkChannel.java +++ b/src/share/classes/java/nio/channels/NetworkChannel.java @@ -87,8 +87,7 @@ public interface NetworkChannel NetworkChannel bind(SocketAddress local) throws IOException; /** - * Returns the socket address that this channel's socket is bound to, or - * {@code null} if the socket is not bound. + * Returns the socket address that this channel's socket is bound to. * *

Where the channel is {@link #bind bound} to an Internet Protocol * socket address then the return value from this method is of type {@link diff --git a/src/share/classes/java/nio/channels/ServerSocketChannel.java b/src/share/classes/java/nio/channels/ServerSocketChannel.java index 598746d65..90e39b529 100644 --- a/src/share/classes/java/nio/channels/ServerSocketChannel.java +++ b/src/share/classes/java/nio/channels/ServerSocketChannel.java @@ -265,4 +265,25 @@ public abstract class ServerSocketChannel */ public abstract SocketChannel accept() throws IOException; + /** + * {@inheritDoc} + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * a {@code SocketAddress} representing the + * {@link java.net.InetAddress#getLoopbackAddress loopback} address and the + * local port of the channel's socket is returned. + * + * @return The {@code SocketAddress} that the socket is bound to, or the + * {@code SocketAddress} representing the loopback address if + * denied by the security manager, or {@code null} if the + * channel's socket is not bound + * + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + @Override + public abstract SocketAddress getLocalAddress() throws IOException; + } diff --git a/src/share/classes/java/nio/channels/SocketChannel.java b/src/share/classes/java/nio/channels/SocketChannel.java index d5f43ba77..185862cad 100644 --- a/src/share/classes/java/nio/channels/SocketChannel.java +++ b/src/share/classes/java/nio/channels/SocketChannel.java @@ -493,4 +493,25 @@ public abstract class SocketChannel return write(srcs, 0, srcs.length); } + /** + * {@inheritDoc} + *

+ * If there is a security manager set, its {@code checkConnect} method is + * called with the local address and {@code -1} as its arguments to see + * if the operation is allowed. If the operation is not allowed, + * a {@code SocketAddress} representing the + * {@link java.net.InetAddress#getLoopbackAddress loopback} address and the + * local port of the channel's socket is returned. + * + * @return The {@code SocketAddress} that the socket is bound to, or the + * {@code SocketAddress} representing the loopback address if + * denied by the security manager, or {@code null} if the + * channel's socket is not bound + * + * @throws ClosedChannelException {@inheritDoc} + * @throws IOException {@inheritDoc} + */ + @Override + public abstract SocketAddress getLocalAddress() throws IOException; + } diff --git a/src/share/classes/sun/net/NetworkClient.java b/src/share/classes/sun/net/NetworkClient.java index dc4d12b6d..87f18c4f7 100644 --- a/src/share/classes/sun/net/NetworkClient.java +++ b/src/share/classes/sun/net/NetworkClient.java @@ -200,7 +200,13 @@ public class NetworkClient { protected InetAddress getLocalAddress() throws IOException { if (serverSocket == null) throw new IOException("not connected"); - return serverSocket.getLocalAddress(); + return AccessController.doPrivileged( + new PrivilegedAction() { + public InetAddress run() { + return serverSocket.getLocalAddress(); + + } + }); } /** Close an open connection to the server. */ diff --git a/src/share/classes/sun/net/ftp/impl/FtpClient.java b/src/share/classes/sun/net/ftp/impl/FtpClient.java index babb9f599..7983a75b9 100644 --- a/src/share/classes/sun/net/ftp/impl/FtpClient.java +++ b/src/share/classes/sun/net/ftp/impl/FtpClient.java @@ -76,7 +76,10 @@ public class FtpClient extends sun.net.ftp.FtpClient { private FtpReplyCode lastReplyCode = null; /** Welcome message from the server, if any. */ private String welcomeMsg; - private boolean passiveMode = true; + /** + * Only passive mode used in JDK. See Bug 8010784. + */ + private final boolean passiveMode = true; private TransferType type = TransferType.BINARY; private long restartOffset = 0; private long lastTransSize = -1; // -1 means 'unknown size' @@ -645,9 +648,18 @@ public class FtpClient extends sun.net.ftp.FtpClient { } else { s = new Socket(); } + + InetAddress serverAddress = AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public InetAddress run() { + return server.getLocalAddress(); + } + }); + // Bind the socket to the same address as the control channel. This // is needed in case of multi-homed systems. - s.bind(new InetSocketAddress(server.getLocalAddress(), 0)); + s.bind(new InetSocketAddress(serverAddress, 0)); if (connectTimeout >= 0) { s.connect(dest, connectTimeout); } else { @@ -816,7 +828,9 @@ public class FtpClient extends sun.net.ftp.FtpClient { * @see #setActiveMode() */ public sun.net.ftp.FtpClient enablePassiveMode(boolean passive) { - passiveMode = passive; + + // Only passive mode used in JDK. See Bug 8010784. + // passiveMode = passive; return this; } diff --git a/src/share/classes/sun/net/httpserver/ServerImpl.java b/src/share/classes/sun/net/httpserver/ServerImpl.java index 69a9e6586..accc5c6a2 100644 --- a/src/share/classes/sun/net/httpserver/ServerImpl.java +++ b/src/share/classes/sun/net/httpserver/ServerImpl.java @@ -34,6 +34,8 @@ import java.util.logging.Logger; import java.util.logging.Level; import javax.net.ssl.*; import com.sun.net.httpserver.*; +import java.security.AccessController; +import java.security.PrivilegedAction; import sun.net.httpserver.HttpConnection.State; /** @@ -244,7 +246,14 @@ class ServerImpl implements TimeSource { } public InetSocketAddress getAddress() { - return (InetSocketAddress)schan.socket().getLocalSocketAddress(); + return AccessController.doPrivileged( + new PrivilegedAction() { + public InetSocketAddress run() { + return + (InetSocketAddress)schan.socket() + .getLocalSocketAddress(); + } + }); } Selector getSelector () { diff --git a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java index 09965831d..9699c8296 100644 --- a/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java @@ -51,7 +51,7 @@ abstract class AsynchronousServerSocketChannelImpl protected final FileDescriptor fd; // the local address to which the channel's socket is bound - protected volatile SocketAddress localAddress = null; + protected volatile InetSocketAddress localAddress = null; // need this lock to set local address private final Object stateLock = new Object(); @@ -173,7 +173,7 @@ abstract class AsynchronousServerSocketChannelImpl public final SocketAddress getLocalAddress() throws IOException { if (!isOpen()) throw new ClosedChannelException(); - return localAddress; + return Net.getRevealedLocalAddress(localAddress); } @Override @@ -251,7 +251,7 @@ abstract class AsynchronousServerSocketChannelImpl if (localAddress == null) { sb.append("unbound"); } else { - sb.append(localAddress.toString()); + sb.append(Net.getRevealedLocalAddressAsString(localAddress)); } } sb.append(']'); diff --git a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 52c7ab28c..273f9def3 100644 --- a/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -53,8 +53,8 @@ abstract class AsynchronousSocketChannelImpl // protects state, localAddress, and remoteAddress protected final Object stateLock = new Object(); - protected volatile SocketAddress localAddress = null; - protected volatile SocketAddress remoteAddress = null; + protected volatile InetSocketAddress localAddress = null; + protected volatile InetSocketAddress remoteAddress = null; // State, increases monotonically static final int ST_UNINITIALIZED = -1; @@ -442,7 +442,7 @@ abstract class AsynchronousSocketChannelImpl public final SocketAddress getLocalAddress() throws IOException { if (!isOpen()) throw new ClosedChannelException(); - return localAddress; + return Net.getRevealedLocalAddress(localAddress); } @Override @@ -582,7 +582,8 @@ abstract class AsynchronousSocketChannelImpl } if (localAddress != null) { sb.append(" local="); - sb.append(localAddress.toString()); + sb.append( + Net.getRevealedLocalAddressAsString(localAddress)); } if (remoteAddress != null) { sb.append(" remote="); diff --git a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java index 9ecdd43f2..b99750c4c 100644 --- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -85,8 +85,8 @@ class DatagramChannelImpl private int state = ST_UNINITIALIZED; // Binding - private SocketAddress localAddress; - private SocketAddress remoteAddress; + private InetSocketAddress localAddress; + private InetSocketAddress remoteAddress; // Our socket adaptor, if any private DatagramSocket socket; @@ -168,7 +168,8 @@ class DatagramChannelImpl synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); - return localAddress; + // Perform security check before returning address + return Net.getRevealedLocalAddress(localAddress); } } @@ -721,6 +722,7 @@ class DatagramChannelImpl } } + @Override public DatagramChannel connect(SocketAddress sa) throws IOException { int localPort = 0; @@ -742,7 +744,7 @@ class DatagramChannelImpl // Connection succeeded; disallow further invocation state = ST_CONNECTED; - remoteAddress = sa; + remoteAddress = isa; sender = isa; cachedSenderInetAddress = isa.getAddress(); cachedSenderPort = isa.getPort(); @@ -761,7 +763,7 @@ class DatagramChannelImpl synchronized (stateLock) { if (!isConnected() || !isOpen()) return this; - InetSocketAddress isa = (InetSocketAddress)remoteAddress; + InetSocketAddress isa = remoteAddress; SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), diff --git a/src/share/classes/sun/nio/ch/Net.java b/src/share/classes/sun/nio/ch/Net.java index bb0e93bda..2b68f963f 100644 --- a/src/share/classes/sun/nio/ch/Net.java +++ b/src/share/classes/sun/nio/ch/Net.java @@ -31,6 +31,7 @@ import java.nio.channels.*; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; public class Net { @@ -182,6 +183,34 @@ public class Net { translateException(x, false); } + /** + * Returns the local address after performing a SecurityManager#checkConnect. + */ + static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) { + SecurityManager sm = System.getSecurityManager(); + if (addr == null || sm == null) + return addr; + + try{ + sm.checkConnect(addr.getAddress().getHostAddress(), -1); + // Security check passed + } catch (SecurityException e) { + // Return loopback address only if security check fails + addr = getLoopbackAddress(addr.getPort()); + } + return addr; + } + + static String getRevealedLocalAddressAsString(InetSocketAddress addr) { + return System.getSecurityManager() == null ? addr.toString() : + getLoopbackAddress(addr.getPort()).toString(); + } + + private static InetSocketAddress getLoopbackAddress(int port) { + return new InetSocketAddress(InetAddress.getLoopbackAddress(), + port); + } + /** * Returns any IPv4 address of the given network interface, or * null if the interface does not have any IPv4 addresses. diff --git a/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java b/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java index d88982e63..776592db4 100644 --- a/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java +++ b/src/share/classes/sun/nio/ch/ServerSocketAdaptor.java @@ -80,7 +80,8 @@ public class ServerSocketAdaptor // package-private public InetAddress getInetAddress() { if (!ssc.isBound()) return null; - return Net.asInetSocketAddress(ssc.localAddress()).getAddress(); + return Net.getRevealedLocalAddress(ssc.localAddress()).getAddress(); + } public int getLocalPort() { diff --git a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 9bba345ba..3b3969cc1 100644 --- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -72,7 +72,7 @@ class ServerSocketChannelImpl private int state = ST_UNINITIALIZED; // Binding - private SocketAddress localAddress; // null => unbound + private InetSocketAddress localAddress; // null => unbound // set true when exclusive binding is on and SO_REUSEADDR is emulated private boolean isReuseAddress; @@ -116,7 +116,9 @@ class ServerSocketChannelImpl synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); - return localAddress; + return localAddress == null ? localAddress + : Net.getRevealedLocalAddress( + Net.asInetSocketAddress(localAddress)); } } @@ -190,7 +192,7 @@ class ServerSocketChannelImpl } } - public SocketAddress localAddress() { + public InetSocketAddress localAddress() { synchronized (stateLock) { return localAddress; } @@ -384,14 +386,15 @@ class ServerSocketChannelImpl StringBuffer sb = new StringBuffer(); sb.append(this.getClass().getName()); sb.append('['); - if (!isOpen()) + if (!isOpen()) { sb.append("closed"); - else { + } else { synchronized (stateLock) { - if (localAddress() == null) { + InetSocketAddress addr = localAddress(); + if (addr == null) { sb.append("unbound"); } else { - sb.append(localAddress().toString()); + sb.append(Net.getRevealedLocalAddressAsString(addr)); } } } diff --git a/src/share/classes/sun/nio/ch/SocketAdaptor.java b/src/share/classes/sun/nio/ch/SocketAdaptor.java index ad1240f48..2fd00ca22 100644 --- a/src/share/classes/sun/nio/ch/SocketAdaptor.java +++ b/src/share/classes/sun/nio/ch/SocketAdaptor.java @@ -149,9 +149,10 @@ public class SocketAdaptor public InetAddress getLocalAddress() { if (sc.isOpen()) { - SocketAddress local = sc.localAddress(); - if (local != null) - return ((InetSocketAddress)local).getAddress(); + InetSocketAddress local = sc.localAddress(); + if (local != null) { + return Net.getRevealedLocalAddress(local).getAddress(); + } } return new InetSocketAddress(0).getAddress(); } diff --git a/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/share/classes/sun/nio/ch/SocketChannelImpl.java index c3daa58d5..6959c1778 100644 --- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -83,8 +83,8 @@ class SocketChannelImpl private int state = ST_UNINITIALIZED; // Binding - private SocketAddress localAddress; - private SocketAddress remoteAddress; + private InetSocketAddress localAddress; + private InetSocketAddress remoteAddress; // Input/Output open private boolean isInputOpen = true; @@ -146,7 +146,7 @@ class SocketChannelImpl synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); - return localAddress; + return Net.getRevealedLocalAddress(localAddress); } } @@ -547,7 +547,7 @@ class SocketChannelImpl IOUtil.configureBlocking(fd, block); } - public SocketAddress localAddress() { + public InetSocketAddress localAddress() { synchronized (stateLock) { return localAddress; } @@ -974,6 +974,7 @@ class SocketChannelImpl return fdVal; } + @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append(this.getClass().getSuperclass().getName()); @@ -997,9 +998,10 @@ class SocketChannelImpl sb.append(" oshut"); break; } - if (localAddress() != null) { + InetSocketAddress addr = localAddress(); + if (addr != null) { sb.append(" local="); - sb.append(localAddress().toString()); + sb.append(Net.getRevealedLocalAddressAsString(addr)); } if (remoteAddress() != null) { sb.append(" remote="); diff --git a/src/share/classes/sun/rmi/server/Activation.java b/src/share/classes/sun/rmi/server/Activation.java index d1946fafc..55bc0ecc7 100644 --- a/src/share/classes/sun/rmi/server/Activation.java +++ b/src/share/classes/sun/rmi/server/Activation.java @@ -2230,7 +2230,13 @@ public class Activation implements Serializable { } public InetAddress getInetAddress() { - return serverSocket.getInetAddress(); + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public InetAddress run() { + return serverSocket.getInetAddress(); + } + }); } public int getLocalPort() { @@ -2238,7 +2244,13 @@ public class Activation implements Serializable { } public SocketAddress getLocalSocketAddress() { - return serverSocket.getLocalSocketAddress(); + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public SocketAddress run() { + return serverSocket.getLocalSocketAddress(); + } + }); } /** diff --git a/src/share/classes/sun/rmi/transport/proxy/WrappedSocket.java b/src/share/classes/sun/rmi/transport/proxy/WrappedSocket.java index 96ff38cc3..67f8fe655 100644 --- a/src/share/classes/sun/rmi/transport/proxy/WrappedSocket.java +++ b/src/share/classes/sun/rmi/transport/proxy/WrappedSocket.java @@ -28,6 +28,8 @@ import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * The WrappedSocket class provides a general wrapper for providing an @@ -78,7 +80,14 @@ class WrappedSocket extends Socket { * Get the local address to which the socket is bound. */ public InetAddress getLocalAddress() { - return socket.getLocalAddress(); + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public InetAddress run() { + return socket.getLocalAddress(); + + } + }); } /** diff --git a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java index 33859f035..8b74488f1 100644 --- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java +++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java @@ -241,7 +241,7 @@ class UnixAsynchronousSocketChannelImpl synchronized (stateLock) { state = ST_CONNECTED; localAddress = Net.localAddress(fd); - remoteAddress = pendingRemote; + remoteAddress = (InetSocketAddress)pendingRemote; } } diff --git a/src/solaris/classes/sun/nio/ch/sctp/SctpNet.java b/src/solaris/classes/sun/nio/ch/sctp/SctpNet.java index 8f02de791..8cfab7022 100644 --- a/src/solaris/classes/sun/nio/ch/sctp/SctpNet.java +++ b/src/solaris/classes/sun/nio/ch/sctp/SctpNet.java @@ -94,18 +94,44 @@ public class SctpNet { static Set getLocalAddresses(int fd) throws IOException { - HashSet set = null; + Set set = null; SocketAddress[] saa = getLocalAddresses0(fd); if (saa != null) { - set = new HashSet(saa.length); - for (SocketAddress sa : saa) - set.add(sa); + set = getRevealedLocalAddressSet(saa); } return set; } + private static Set getRevealedLocalAddressSet( + SocketAddress[] saa) + { + SecurityManager sm = System.getSecurityManager(); + Set set = new HashSet<>(saa.length); + for (SocketAddress sa : saa) { + set.add(getRevealedLocalAddress(sa, sm)); + } + return set; + } + + private static SocketAddress getRevealedLocalAddress(SocketAddress sa, + SecurityManager sm) + { + if (sm == null || sa == null) + return sa; + InetSocketAddress ia = (InetSocketAddress)sa; + try{ + sm.checkConnect(ia.getAddress().getHostAddress(), -1); + // Security check passed + } catch (SecurityException e) { + // Return loopback address + return new InetSocketAddress(InetAddress.getLoopbackAddress(), + ia.getPort()); + } + return sa; + } + static Set getRemoteAddresses(int fd, int assocId) throws IOException { HashSet set = null; diff --git a/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java b/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java index ff3c3109c..b76b68287 100644 --- a/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java +++ b/src/windows/classes/sun/nio/ch/WindowsAsynchronousSocketChannelImpl.java @@ -137,7 +137,9 @@ class WindowsAsynchronousSocketChannelImpl // invoked by WindowsAsynchronousServerSocketChannelImpl when new connection // accept - void setConnected(SocketAddress localAddress, SocketAddress remoteAddress) { + void setConnected(InetSocketAddress localAddress, + InetSocketAddress remoteAddress) + { synchronized (stateLock) { state = ST_CONNECTED; this.localAddress = localAddress; -- GitLab