|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.rmi.registry; |
|
|
|
import java.util.Enumeration; |
|
import java.util.Hashtable; |
|
import java.util.MissingResourceException; |
|
import java.util.ResourceBundle; |
|
import java.io.FilePermission; |
|
import java.net.*; |
|
import java.rmi.*; |
|
import java.rmi.server.ObjID; |
|
import java.rmi.server.ServerNotActiveException; |
|
import java.rmi.registry.Registry; |
|
import java.rmi.server.RMIClientSocketFactory; |
|
import java.rmi.server.RMIServerSocketFactory; |
|
import java.security.AccessControlContext; |
|
import java.security.AccessController; |
|
import java.security.CodeSource; |
|
import java.security.Policy; |
|
import java.security.PrivilegedActionException; |
|
import java.security.PrivilegedExceptionAction; |
|
import java.security.PermissionCollection; |
|
import java.security.Permissions; |
|
import java.security.PrivilegedAction; |
|
import java.security.ProtectionDomain; |
|
import java.security.Security; |
|
import java.text.MessageFormat; |
|
|
|
import sun.misc.ObjectInputFilter; |
|
|
|
import sun.rmi.runtime.Log; |
|
import sun.rmi.server.UnicastRef; |
|
import sun.rmi.server.UnicastServerRef; |
|
import sun.rmi.server.UnicastServerRef2; |
|
import sun.rmi.transport.LiveRef; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class RegistryImpl extends java.rmi.server.RemoteServer |
|
implements Registry |
|
{ |
|
|
|
|
|
private static final long serialVersionUID = 4666870661827494597L; |
|
private Hashtable<String, Remote> bindings |
|
= new Hashtable<>(101); |
|
private static Hashtable<InetAddress, InetAddress> allowedAccessCache |
|
= new Hashtable<>(3); |
|
private static RegistryImpl registry; |
|
private static ObjID id = new ObjID(ObjID.REGISTRY_ID); |
|
|
|
private static ResourceBundle resources = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static final String REGISTRY_FILTER_PROPNAME = "sun.rmi.registry.registryFilter"; |
|
|
|
|
|
private static final int REGISTRY_MAX_DEPTH = 20; |
|
|
|
|
|
private static final int REGISTRY_MAX_ARRAY_SIZE = 1_000_000; |
|
|
|
|
|
|
|
|
|
*/ |
|
private static final ObjectInputFilter registryFilter = |
|
AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)RegistryImpl::initRegistryFilter); |
|
|
|
|
|
|
|
|
|
*/ |
|
private static ObjectInputFilter initRegistryFilter() { |
|
ObjectInputFilter filter = null; |
|
String props = System.getProperty(REGISTRY_FILTER_PROPNAME); |
|
if (props == null) { |
|
props = Security.getProperty(REGISTRY_FILTER_PROPNAME); |
|
} |
|
if (props != null) { |
|
filter = ObjectInputFilter.Config.createFilter2(props); |
|
Log regLog = Log.getLog("sun.rmi.registry", "registry", -1); |
|
if (regLog.isLoggable(Log.BRIEF)) { |
|
regLog.log(Log.BRIEF, "registryFilter = " + filter); |
|
} |
|
} |
|
return filter; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public RegistryImpl(int port, |
|
RMIClientSocketFactory csf, |
|
RMIServerSocketFactory ssf) |
|
throws RemoteException |
|
{ |
|
this(port, csf, ssf, RegistryImpl::registryFilter); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public RegistryImpl(int port, |
|
RMIClientSocketFactory csf, |
|
RMIServerSocketFactory ssf, |
|
ObjectInputFilter serialFilter) |
|
throws RemoteException |
|
{ |
|
if (port == Registry.REGISTRY_PORT && System.getSecurityManager() != null) { |
|
|
|
try { |
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { |
|
public Void run() throws RemoteException { |
|
LiveRef lref = new LiveRef(id, port, csf, ssf); |
|
setup(new UnicastServerRef2(lref, serialFilter)); |
|
return null; |
|
} |
|
}, null, new SocketPermission("localhost:"+port, "listen,accept")); |
|
} catch (PrivilegedActionException pae) { |
|
throw (RemoteException)pae.getException(); |
|
} |
|
} else { |
|
LiveRef lref = new LiveRef(id, port, csf, ssf); |
|
setup(new UnicastServerRef2(lref, serialFilter)); |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public RegistryImpl(int port) |
|
throws RemoteException |
|
{ |
|
if (port == Registry.REGISTRY_PORT && System.getSecurityManager() != null) { |
|
|
|
try { |
|
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { |
|
public Void run() throws RemoteException { |
|
LiveRef lref = new LiveRef(id, port); |
|
setup(new UnicastServerRef(lref, RegistryImpl::registryFilter)); |
|
return null; |
|
} |
|
}, null, new SocketPermission("localhost:"+port, "listen,accept")); |
|
} catch (PrivilegedActionException pae) { |
|
throw (RemoteException)pae.getException(); |
|
} |
|
} else { |
|
LiveRef lref = new LiveRef(id, port); |
|
setup(new UnicastServerRef(lref, RegistryImpl::registryFilter)); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private void setup(UnicastServerRef uref) |
|
throws RemoteException |
|
{ |
|
|
|
|
|
*/ |
|
ref = uref; |
|
uref.exportObject(this, null, true); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Remote lookup(String name) |
|
throws RemoteException, NotBoundException |
|
{ |
|
synchronized (bindings) { |
|
Remote obj = bindings.get(name); |
|
if (obj == null) |
|
throw new NotBoundException(name); |
|
return obj; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void bind(String name, Remote obj) |
|
throws RemoteException, AlreadyBoundException, AccessException |
|
{ |
|
// The access check preventing remote access is done in the skeleton |
|
|
|
synchronized (bindings) { |
|
Remote curr = bindings.get(name); |
|
if (curr != null) |
|
throw new AlreadyBoundException(name); |
|
bindings.put(name, obj); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public void unbind(String name) |
|
throws RemoteException, NotBoundException, AccessException |
|
{ |
|
// The access check preventing remote access is done in the skeleton |
|
|
|
synchronized (bindings) { |
|
Remote obj = bindings.get(name); |
|
if (obj == null) |
|
throw new NotBoundException(name); |
|
bindings.remove(name); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void rebind(String name, Remote obj) |
|
throws RemoteException, AccessException |
|
{ |
|
// The access check preventing remote access is done in the skeleton |
|
|
|
bindings.put(name, obj); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public String[] list() |
|
throws RemoteException |
|
{ |
|
String[] names; |
|
synchronized (bindings) { |
|
int i = bindings.size(); |
|
names = new String[i]; |
|
Enumeration<String> enum_ = bindings.keys(); |
|
while ((--i) >= 0) |
|
names[i] = enum_.nextElement(); |
|
} |
|
return names; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static void checkAccess(String op) throws AccessException { |
|
try { |
|
|
|
|
|
*/ |
|
final String clientHostName = getClientHost(); |
|
InetAddress clientHost; |
|
|
|
try { |
|
clientHost = java.security.AccessController.doPrivileged( |
|
new java.security.PrivilegedExceptionAction<InetAddress>() { |
|
public InetAddress run() |
|
throws java.net.UnknownHostException |
|
{ |
|
return InetAddress.getByName(clientHostName); |
|
} |
|
}); |
|
} catch (PrivilegedActionException pae) { |
|
throw (java.net.UnknownHostException) pae.getException(); |
|
} |
|
|
|
|
|
if (allowedAccessCache.get(clientHost) == null) { |
|
|
|
if (clientHost.isAnyLocalAddress()) { |
|
throw new AccessException( |
|
op + " disallowed; origin unknown"); |
|
} |
|
|
|
try { |
|
final InetAddress finalClientHost = clientHost; |
|
|
|
java.security.AccessController.doPrivileged( |
|
new java.security.PrivilegedExceptionAction<Void>() { |
|
public Void run() throws java.io.IOException { |
|
|
|
|
|
|
|
*/ |
|
(new ServerSocket(0, 10, finalClientHost)).close(); |
|
allowedAccessCache.put(finalClientHost, |
|
finalClientHost); |
|
return null; |
|
} |
|
}); |
|
} catch (PrivilegedActionException pae) { |
|
// must have been an IOException |
|
|
|
throw new AccessException( |
|
op + " disallowed; origin " + |
|
clientHost + " is non-local host"); |
|
} |
|
} |
|
} catch (ServerNotActiveException ex) { |
|
/* |
|
* Local call from this VM: allow access. |
|
*/ |
|
} catch (java.net.UnknownHostException ex) { |
|
throw new AccessException(op + " disallowed; origin is unknown host"); |
|
} |
|
} |
|
|
|
public static ObjID getID() { |
|
return id; |
|
} |
|
|
|
|
|
|
|
*/ |
|
private static String getTextResource(String key) { |
|
if (resources == null) { |
|
try { |
|
resources = ResourceBundle.getBundle( |
|
"sun.rmi.registry.resources.rmiregistry"); |
|
} catch (MissingResourceException mre) { |
|
} |
|
if (resources == null) { |
|
|
|
return ("[missing resource file: " + key + "]"); |
|
} |
|
} |
|
|
|
String val = null; |
|
try { |
|
val = resources.getString(key); |
|
} catch (MissingResourceException mre) { |
|
} |
|
|
|
if (val == null) { |
|
return ("[missing resource: " + key + "]"); |
|
} else { |
|
return (val); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static ObjectInputFilter.Status registryFilter(ObjectInputFilter.FilterInfo filterInfo) { |
|
if (registryFilter != null) { |
|
ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo); |
|
if (status != ObjectInputFilter.Status.UNDECIDED) { |
|
|
|
return status; |
|
} |
|
} |
|
|
|
if (filterInfo.depth() > REGISTRY_MAX_DEPTH) { |
|
return ObjectInputFilter.Status.REJECTED; |
|
} |
|
Class<?> clazz = filterInfo.serialClass(); |
|
if (clazz != null) { |
|
if (clazz.isArray()) { |
|
|
|
return (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) |
|
? ObjectInputFilter.Status.REJECTED |
|
: ObjectInputFilter.Status.UNDECIDED; |
|
} |
|
if (String.class == clazz |
|
|| java.lang.Number.class.isAssignableFrom(clazz) |
|
|| Remote.class.isAssignableFrom(clazz) |
|
|| java.lang.reflect.Proxy.class.isAssignableFrom(clazz) |
|
|| UnicastRef.class.isAssignableFrom(clazz) |
|
|| RMIClientSocketFactory.class.isAssignableFrom(clazz) |
|
|| RMIServerSocketFactory.class.isAssignableFrom(clazz) |
|
|| java.rmi.activation.ActivationID.class.isAssignableFrom(clazz) |
|
|| java.rmi.server.UID.class.isAssignableFrom(clazz)) { |
|
return ObjectInputFilter.Status.ALLOWED; |
|
} else { |
|
return ObjectInputFilter.Status.REJECTED; |
|
} |
|
} |
|
return ObjectInputFilter.Status.UNDECIDED; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static void main(String args[]) |
|
{ |
|
// Create and install the security manager if one is not installed |
|
|
|
if (System.getSecurityManager() == null) { |
|
System.setSecurityManager(new RMISecurityManager()); |
|
} |
|
|
|
try { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
String envcp = System.getProperty("env.class.path"); |
|
if (envcp == null) { |
|
envcp = "."; |
|
} |
|
URL[] urls = sun.misc.URLClassPath.pathToURLs(envcp); |
|
ClassLoader cl = new URLClassLoader(urls); |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
sun.rmi.server.LoaderHandler.registerCodebaseLoader(cl); |
|
|
|
Thread.currentThread().setContextClassLoader(cl); |
|
|
|
final int regPort = (args.length >= 1) ? Integer.parseInt(args[0]) |
|
: Registry.REGISTRY_PORT; |
|
try { |
|
registry = AccessController.doPrivileged( |
|
new PrivilegedExceptionAction<RegistryImpl>() { |
|
public RegistryImpl run() throws RemoteException { |
|
return new RegistryImpl(regPort); |
|
} |
|
}, getAccessControlContext(regPort)); |
|
} catch (PrivilegedActionException ex) { |
|
throw (RemoteException) ex.getException(); |
|
} |
|
|
|
|
|
while (true) { |
|
try { |
|
Thread.sleep(Long.MAX_VALUE); |
|
} catch (InterruptedException e) { |
|
} |
|
} |
|
} catch (NumberFormatException e) { |
|
System.err.println(MessageFormat.format( |
|
getTextResource("rmiregistry.port.badnumber"), |
|
args[0] )); |
|
System.err.println(MessageFormat.format( |
|
getTextResource("rmiregistry.usage"), |
|
"rmiregistry" )); |
|
} catch (Exception e) { |
|
e.printStackTrace(); |
|
} |
|
System.exit(1); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static AccessControlContext getAccessControlContext(int port) { |
|
|
|
PermissionCollection perms = AccessController.doPrivileged( |
|
new java.security.PrivilegedAction<PermissionCollection>() { |
|
public PermissionCollection run() { |
|
CodeSource codesource = new CodeSource(null, |
|
(java.security.cert.Certificate[]) null); |
|
Policy p = java.security.Policy.getPolicy(); |
|
if (p != null) { |
|
return p.getPermissions(codesource); |
|
} else { |
|
return new Permissions(); |
|
} |
|
} |
|
}); |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
perms.add(new SocketPermission("*", "connect,accept")); |
|
perms.add(new SocketPermission("localhost:"+port, "listen,accept")); |
|
|
|
perms.add(new RuntimePermission("accessClassInPackage.sun.jvmstat.*")); |
|
perms.add(new RuntimePermission("accessClassInPackage.sun.jvm.hotspot.*")); |
|
|
|
perms.add(new FilePermission("<<ALL FILES>>", "read")); |
|
|
|
|
|
|
|
|
|
*/ |
|
ProtectionDomain pd = new ProtectionDomain( |
|
new CodeSource(null, |
|
(java.security.cert.Certificate[]) null), perms); |
|
return new AccessControlContext(new ProtectionDomain[] { pd }); |
|
} |
|
} |