23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package sun.rmi.registry; |
26 package sun.rmi.registry; |
27 |
27 |
|
28 import java.io.ObjectInputFilter; |
28 import java.nio.file.Path; |
29 import java.nio.file.Path; |
29 import java.nio.file.Paths; |
30 import java.nio.file.Paths; |
|
31 import java.rmi.server.LogStream; |
|
32 import java.security.PrivilegedAction; |
|
33 import java.security.Security; |
30 import java.util.ArrayList; |
34 import java.util.ArrayList; |
31 import java.util.Enumeration; |
35 import java.util.Enumeration; |
32 import java.util.Hashtable; |
36 import java.util.Hashtable; |
33 import java.util.List; |
37 import java.util.List; |
34 import java.util.MissingResourceException; |
38 import java.util.MissingResourceException; |
37 import java.io.FilePermission; |
41 import java.io.FilePermission; |
38 import java.io.IOException; |
42 import java.io.IOException; |
39 import java.net.*; |
43 import java.net.*; |
40 import java.rmi.*; |
44 import java.rmi.*; |
41 import java.rmi.server.ObjID; |
45 import java.rmi.server.ObjID; |
42 import java.rmi.server.RemoteServer; |
|
43 import java.rmi.server.ServerNotActiveException; |
46 import java.rmi.server.ServerNotActiveException; |
44 import java.rmi.registry.Registry; |
47 import java.rmi.registry.Registry; |
45 import java.rmi.server.RMIClientSocketFactory; |
48 import java.rmi.server.RMIClientSocketFactory; |
46 import java.rmi.server.RMIServerSocketFactory; |
49 import java.rmi.server.RMIServerSocketFactory; |
47 import java.security.AccessControlContext; |
50 import java.security.AccessControlContext; |
52 import java.security.PrivilegedExceptionAction; |
55 import java.security.PrivilegedExceptionAction; |
53 import java.security.PermissionCollection; |
56 import java.security.PermissionCollection; |
54 import java.security.Permissions; |
57 import java.security.Permissions; |
55 import java.security.ProtectionDomain; |
58 import java.security.ProtectionDomain; |
56 import java.text.MessageFormat; |
59 import java.text.MessageFormat; |
57 import sun.rmi.server.LoaderHandler; |
60 |
|
61 import sun.rmi.runtime.Log; |
|
62 import sun.rmi.server.UnicastRef; |
58 import sun.rmi.server.UnicastServerRef; |
63 import sun.rmi.server.UnicastServerRef; |
59 import sun.rmi.server.UnicastServerRef2; |
64 import sun.rmi.server.UnicastServerRef2; |
60 import sun.rmi.transport.LiveRef; |
65 import sun.rmi.transport.LiveRef; |
61 import sun.rmi.transport.ObjectTable; |
|
62 import sun.rmi.transport.Target; |
|
63 |
66 |
64 /** |
67 /** |
65 * A "registry" exists on every node that allows RMI connections to |
68 * A "registry" exists on every node that allows RMI connections to |
66 * servers on that node. The registry on a particular node contains a |
69 * servers on that node. The registry on a particular node contains a |
67 * transient database that maps names to remote objects. When the |
70 * transient database that maps names to remote objects. When the |
89 private static ObjID id = new ObjID(ObjID.REGISTRY_ID); |
92 private static ObjID id = new ObjID(ObjID.REGISTRY_ID); |
90 |
93 |
91 private static ResourceBundle resources = null; |
94 private static ResourceBundle resources = null; |
92 |
95 |
93 /** |
96 /** |
|
97 * Property name of the RMI Registry serial filter to augment |
|
98 * the built-in list of allowed types. |
|
99 * Setting the property in the {@code conf/security/java.security} file |
|
100 * will enable the augmented filter. |
|
101 */ |
|
102 private static final String REGISTRY_FILTER_PROPNAME = "sun.rmi.registry.registryFilter"; |
|
103 |
|
104 /** Registry max depth of remote invocations. **/ |
|
105 private static int REGISTRY_MAX_DEPTH = 5; |
|
106 |
|
107 /** Registry maximum array size in remote invocations. **/ |
|
108 private static int REGISTRY_MAX_ARRAY_SIZE = 10000; |
|
109 |
|
110 /** |
|
111 * The registryFilter created from the value of the {@code "sun.rmi.registry.registryFilter"} |
|
112 * property. |
|
113 */ |
|
114 private static final ObjectInputFilter registryFilter = |
|
115 AccessController.doPrivileged((PrivilegedAction<ObjectInputFilter>)RegistryImpl::initRegistryFilter); |
|
116 |
|
117 /** |
|
118 * Initialize the registryFilter from the security properties or system property; if any |
|
119 * @return an ObjectInputFilter, or null |
|
120 */ |
|
121 @SuppressWarnings("deprecation") |
|
122 private static ObjectInputFilter initRegistryFilter() { |
|
123 ObjectInputFilter filter = null; |
|
124 String props = System.getProperty(REGISTRY_FILTER_PROPNAME); |
|
125 if (props == null) { |
|
126 props = Security.getProperty(REGISTRY_FILTER_PROPNAME); |
|
127 } |
|
128 if (props != null) { |
|
129 filter = ObjectInputFilter.Config.createFilter(props); |
|
130 Log regLog = Log.getLog("sun.rmi.registry", "registry", -1); |
|
131 if (regLog.isLoggable(Log.BRIEF)) { |
|
132 regLog.log(Log.BRIEF, "registryFilter = " + filter); |
|
133 } |
|
134 } |
|
135 return filter; |
|
136 } |
|
137 |
|
138 /** |
94 * Construct a new RegistryImpl on the specified port with the |
139 * Construct a new RegistryImpl on the specified port with the |
95 * given custom socket factory pair. |
140 * given custom socket factory pair. |
96 */ |
141 */ |
97 public RegistryImpl(int port, |
142 public RegistryImpl(int port, |
98 RMIClientSocketFactory csf, |
143 RMIClientSocketFactory csf, |
103 // grant permission for default port only. |
148 // grant permission for default port only. |
104 try { |
149 try { |
105 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { |
150 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { |
106 public Void run() throws RemoteException { |
151 public Void run() throws RemoteException { |
107 LiveRef lref = new LiveRef(id, port, csf, ssf); |
152 LiveRef lref = new LiveRef(id, port, csf, ssf); |
108 setup(new UnicastServerRef2(lref)); |
153 setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter)); |
109 return null; |
154 return null; |
110 } |
155 } |
111 }, null, new SocketPermission("localhost:"+port, "listen,accept")); |
156 }, null, new SocketPermission("localhost:"+port, "listen,accept")); |
112 } catch (PrivilegedActionException pae) { |
157 } catch (PrivilegedActionException pae) { |
113 throw (RemoteException)pae.getException(); |
158 throw (RemoteException)pae.getException(); |
114 } |
159 } |
115 } else { |
160 } else { |
116 LiveRef lref = new LiveRef(id, port, csf, ssf); |
161 LiveRef lref = new LiveRef(id, port, csf, ssf); |
117 setup(new UnicastServerRef2(lref)); |
162 setup(new UnicastServerRef2(lref, RegistryImpl::registryFilter)); |
118 } |
163 } |
119 } |
164 } |
120 |
165 |
121 /** |
166 /** |
122 * Construct a new RegistryImpl on the specified port. |
167 * Construct a new RegistryImpl on the specified port. |
128 // grant permission for default port only. |
173 // grant permission for default port only. |
129 try { |
174 try { |
130 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { |
175 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { |
131 public Void run() throws RemoteException { |
176 public Void run() throws RemoteException { |
132 LiveRef lref = new LiveRef(id, port); |
177 LiveRef lref = new LiveRef(id, port); |
133 setup(new UnicastServerRef(lref)); |
178 setup(new UnicastServerRef(lref, RegistryImpl::registryFilter)); |
134 return null; |
179 return null; |
135 } |
180 } |
136 }, null, new SocketPermission("localhost:"+port, "listen,accept")); |
181 }, null, new SocketPermission("localhost:"+port, "listen,accept")); |
137 } catch (PrivilegedActionException pae) { |
182 } catch (PrivilegedActionException pae) { |
138 throw (RemoteException)pae.getException(); |
183 throw (RemoteException)pae.getException(); |
139 } |
184 } |
140 } else { |
185 } else { |
141 LiveRef lref = new LiveRef(id, port); |
186 LiveRef lref = new LiveRef(id, port); |
142 setup(new UnicastServerRef(lref)); |
187 setup(new UnicastServerRef(lref, RegistryImpl::registryFilter)); |
143 } |
188 } |
144 } |
189 } |
145 |
190 |
146 /* |
191 /* |
147 * Create the export the object using the parameter |
192 * Create the export the object using the parameter |
357 } catch (MalformedURLException e) { |
402 } catch (MalformedURLException e) { |
358 //ignore / skip entry |
403 //ignore / skip entry |
359 } |
404 } |
360 } |
405 } |
361 return paths.toArray(new URL[0]); |
406 return paths.toArray(new URL[0]); |
|
407 } |
|
408 |
|
409 /** |
|
410 * ObjectInputFilter to filter Registry input objects. |
|
411 * The list of acceptable classes is limited to classes normally |
|
412 * stored in a registry. |
|
413 * |
|
414 * @param filterInfo access to the class, array length, etc. |
|
415 * @return {@link ObjectInputFilter.Status#ALLOWED} if allowed, |
|
416 * {@link ObjectInputFilter.Status#REJECTED} if rejected, |
|
417 * otherwise {@link ObjectInputFilter.Status#UNDECIDED} |
|
418 */ |
|
419 private static ObjectInputFilter.Status registryFilter(ObjectInputFilter.FilterInfo filterInfo) { |
|
420 if (registryFilter != null) { |
|
421 ObjectInputFilter.Status status = registryFilter.checkInput(filterInfo); |
|
422 if (status != ObjectInputFilter.Status.UNDECIDED) { |
|
423 // The Registry filter can override the built-in white-list |
|
424 return status; |
|
425 } |
|
426 } |
|
427 |
|
428 if (filterInfo.depth() > REGISTRY_MAX_DEPTH) { |
|
429 return ObjectInputFilter.Status.REJECTED; |
|
430 } |
|
431 Class<?> clazz = filterInfo.serialClass(); |
|
432 if (clazz != null) { |
|
433 if (clazz.isArray()) { |
|
434 if (filterInfo.arrayLength() >= 0 && filterInfo.arrayLength() > REGISTRY_MAX_ARRAY_SIZE) { |
|
435 return ObjectInputFilter.Status.REJECTED; |
|
436 } |
|
437 do { |
|
438 // Arrays are allowed depending on the component type |
|
439 clazz = clazz.getComponentType(); |
|
440 } while (clazz.isArray()); |
|
441 } |
|
442 if (clazz.isPrimitive()) { |
|
443 // Arrays of primitives are allowed |
|
444 return ObjectInputFilter.Status.ALLOWED; |
|
445 } |
|
446 if (String.class == clazz |
|
447 || java.lang.Number.class.isAssignableFrom(clazz) |
|
448 || Remote.class.isAssignableFrom(clazz) |
|
449 || java.lang.reflect.Proxy.class.isAssignableFrom(clazz) |
|
450 || UnicastRef.class.isAssignableFrom(clazz) |
|
451 || RMIClientSocketFactory.class.isAssignableFrom(clazz) |
|
452 || RMIServerSocketFactory.class.isAssignableFrom(clazz) |
|
453 || java.rmi.activation.ActivationID.class.isAssignableFrom(clazz) |
|
454 || java.rmi.server.UID.class.isAssignableFrom(clazz)) { |
|
455 return ObjectInputFilter.Status.ALLOWED; |
|
456 } else { |
|
457 return ObjectInputFilter.Status.REJECTED; |
|
458 } |
|
459 } |
|
460 return ObjectInputFilter.Status.UNDECIDED; |
362 } |
461 } |
363 |
462 |
364 /** |
463 /** |
365 * Return a new RegistryImpl on the requested port and export it to serve |
464 * Return a new RegistryImpl on the requested port and export it to serve |
366 * registry requests. A classloader is initialized from the system property |
465 * registry requests. A classloader is initialized from the system property |