/hg/icedtea-web: PR861: Allow loading from non codebase hosts. A...

Jiri Vanek jvanek at redhat.com
Wed Jun 6 06:22:56 PDT 2012


Hi!

This patch have broken most of javaws reproducers. I'm suggesting to revert it until it is 
discovered why. Blame is on my head.
Sorry.

J.
On 06/05/2012 05:00 PM, dbhole at icedtea.classpath.org wrote:
> changeset 954131311826 in /hg/icedtea-web
> details: http://icedtea.classpath.org/hg/icedtea-web?cmd=changeset;node=954131311826
> author: Deepak Bhole<dbhole at redhat.com>
> date: Tue Jun 05 10:11:09 2012 -0400
>
> 	PR861: Allow loading from non codebase hosts. Allow code to connect to hosting server
>
>
> diffstat:
>
>   ChangeLog                                              |   20 ++
>   NEWS                                                   |    1 +
>   netx/net/sourceforge/jnlp/SecurityDesc.java            |    2 +-
>   netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java |  149 +++++++++++++++-
>   4 files changed, 155 insertions(+), 17 deletions(-)
>
> diffs (285 lines):
>
> diff -r 67c462561ee3 -r 954131311826 ChangeLog
> --- a/ChangeLog	Tue Jun 05 16:39:27 2012 +0200
> +++ b/ChangeLog	Tue Jun 05 10:11:09 2012 -0400
> @@ -1,3 +1,23 @@
> +2012-06-05  Deepak Bhole<dbhole at redhat.com>
> +
> +	PR861: Allow loading from non codebase hosts. Allow code to connect to
> +	hosting server.
> +	* netx/net/sourceforge/jnlp/SecurityDesc.java
> +	(getSandBoxPermissions): Only add host if it is not empty.
> +	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
> +	(getPermissions): Add SocketPermission for code source host.
> +	(findLoadedClassAll): Call super methods privileged so that connection to
> +	non codebase hosts can be made.
> +	(findClass): Same.
> +	(findResourcesBySearching): Same. Also use privileged context for enum
> +	operations because the enum is defined on the fly by URLClassLoader and
> +	checks for hosting server connectivity via next().
> +	(getAccessControlContextForClassLoading): New method. Returns a control
> +	context for classloader operations like find/load/etc.
> +	(CodeBaseClassLoader::findClass): Call super methods privileged so that
> +	connection to non codebase hosts can be made.
> +	(CodeBaseClassLoader::findResource): Same.
> +
>   2012-06-05  Jiri Vanek<jvanek at redhat.com>
>
>   	* tests/netx/jnlp_testsengine/net/sourceforge/jnlp/annotations/KnownToFail.java
> diff -r 67c462561ee3 -r 954131311826 NEWS
> --- a/NEWS	Tue Jun 05 16:39:27 2012 +0200
> +++ b/NEWS	Tue Jun 05 10:11:09 2012 -0400
> @@ -16,6 +16,7 @@
>     - PR820: IcedTea-Web 1.1.3 crashing Firefox when loading Citrix XenApp
>     - PR863: Error passing strings to applet methods in Chromium
>     - PR895: IcedTea-Web searches for missing classes on each loadClass or findClass
> +  - PR861: Allow loading from non codebase hosts. Allow code to connect to hosting server
>   * Common
>     - PR918: java applet windows uses a low resulution black/white icon
>
> diff -r 67c462561ee3 -r 954131311826 netx/net/sourceforge/jnlp/SecurityDesc.java
> --- a/netx/net/sourceforge/jnlp/SecurityDesc.java	Tue Jun 05 16:39:27 2012 +0200
> +++ b/netx/net/sourceforge/jnlp/SecurityDesc.java	Tue Jun 05 10:11:09 2012 -0400
> @@ -238,7 +238,7 @@
>               for (int i = 0; i<  jnlpRIAPermissions.length; i++)
>                   permissions.add(jnlpRIAPermissions[i]);
>
> -        if (downloadHost != null)
> +        if (downloadHost != null&&  downloadHost.length()>  0)
>               permissions.add(new SocketPermission(downloadHost,
>                                                    "connect, accept"));
>
> diff -r 67c462561ee3 -r 954131311826 netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
> --- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Tue Jun 05 16:39:27 2012 +0200
> +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Tue Jun 05 10:11:09 2012 -0400
> @@ -25,9 +25,11 @@
>   import java.io.InputStream;
>   import java.io.InputStreamReader;
>   import java.net.MalformedURLException;
> +import java.net.SocketPermission;
>   import java.net.URL;
>   import java.net.URLClassLoader;
>   import java.security.AccessControlContext;
> +import java.security.AccessControlException;
>   import java.security.AccessController;
>   import java.security.AllPermission;
>   import java.security.CodeSource;
> @@ -35,9 +37,12 @@
>   import java.security.PermissionCollection;
>   import java.security.Permissions;
>   import java.security.PrivilegedAction;
> +import java.security.PrivilegedActionException;
>   import java.security.PrivilegedExceptionAction;
> +import java.security.ProtectionDomain;
>   import java.util.ArrayList;
>   import java.util.Arrays;
> +import java.util.Collection;
>   import java.util.Collections;
>   import java.util.Enumeration;
>   import java.util.HashMap;
> @@ -952,6 +957,11 @@
>                   result.add(runtimePermissions.get(i));
>               }
>
> +            // Class from host X should be allowed to connect to host X
> +            if (cs.getLocation().getHost().length()>  0)
> +                result.add(new SocketPermission(cs.getLocation().getHost(),
> +                        "connect, accept"));
> +
>               return result;
>           } catch (RuntimeException ex) {
>               if (JNLPRuntime.isDebug()) {
> @@ -1320,10 +1330,21 @@
>           for (int i = 0; i<  loaders.length; i++) {
>               Class result = null;
>
> -            if (loaders[i] == this)
> -                result = super.findLoadedClass(name);
> -            else
> +            if (loaders[i] == this) {
> +                final String fName = name;
> +                try {
> +                    result = AccessController.doPrivileged(
> +                            new PrivilegedExceptionAction<Class<?>>() {
> +                                public Class<?>  run() {
> +                                    return JNLPClassLoader.super.findLoadedClass(fName);
> +                                }
> +                            }, getAccessControlContextForClassLoading());
> +                } catch (PrivilegedActionException pae) {
> +                    result = null;
> +                }
> +            } else {
>                   result = loaders[i].findLoadedClassAll(name);
> +            }
>
>               if (result != null)
>                   return result;
> @@ -1521,12 +1542,20 @@
>       protected Class findClass(String name) throws ClassNotFoundException {
>           for (int i = 0; i<  loaders.length; i++) {
>               try {
> -                if (loaders[i] == this)
> -                    return super.findClass(name);
> -                else
> +                if (loaders[i] == this) {
> +                    final String fName = name;
> +                    return AccessController.doPrivileged(
> +                            new PrivilegedExceptionAction<Class<?>>() {
> +                                public Class<?>  run() throws ClassNotFoundException {
> +                                    return JNLPClassLoader.super.findClass(fName);
> +                                }
> +                            }, getAccessControlContextForClassLoading());
> +                } else {
>                       return loaders[i].findClass(name);
> +                }
>               } catch (ClassNotFoundException ex) {
>               } catch (ClassFormatError cfe) {
> +            } catch (PrivilegedActionException pae) {
>               }
>           }
>
> @@ -1635,20 +1664,42 @@
>        */
>       private Enumeration<URL>  findResourcesBySearching(String name) throws IOException {
>           List<URL>  resources = new ArrayList<URL>();
> -        Enumeration<URL>  e;
> +        Enumeration<URL>  e = null;
>
>           for (int i = 0; i<  loaders.length; i++) {
>               // TODO check if this will blow up or not
>               // if loaders[1].getResource() is called, wont it call getResource() on
>               // the original caller? infinite recursion?
>
> -            if (loaders[i] == this)
> -                e = super.findResources(name);
> -            else
> +            if (loaders[i] == this) {
> +                final String fName = name;
> +                try {
> +                    e = AccessController.doPrivileged(
> +                            new PrivilegedExceptionAction<Enumeration<URL>>() {
> +                                public Enumeration<URL>  run() throws IOException {
> +                                    return JNLPClassLoader.super.findResources(fName);
> +                                }
> +                            }, getAccessControlContextForClassLoading());
> +                } catch (PrivilegedActionException pae) {
> +                }
> +            } else {
>                   e = loaders[i].findResources(name);
> +            }
>
> -            while (e.hasMoreElements())
> -                resources.add(e.nextElement());
> +            final Enumeration<URL>  fURLEnum = e;
> +            try {
> +                resources.addAll(AccessController.doPrivileged(
> +                    new PrivilegedExceptionAction<Collection<URL>>() {
> +                        public Collection<URL>  run() {
> +                            List<URL>  resources = new ArrayList<URL>();
> +                            while (fURLEnum != null&&  fURLEnum.hasMoreElements()) {
> +                                resources.add(fURLEnum.nextElement());
> +                            }
> +                            return resources;
> +                        }
> +                    }, getAccessControlContextForClassLoading()));
> +            } catch (PrivilegedActionException pae) {
> +            }
>           }
>
>           // Add resources from codebase (only if nothing was found above,
> @@ -1900,6 +1951,56 @@
>           }
>       }
>
> +    /**
> +     * Returns an appropriate AccessControlContext for loading classes in
> +     * the running instance.
> +     *
> +     * The default context during class-loading only allows connection to
> +     * codebase. However applets are allowed to load jars from arbitrary
> +     * locations and the codebase only access falls short if a class from
> +     * one location needs a class from another.
> +     *
> +     * Given protected access since CodeBaseClassloader uses this function too.
> +     *
> +     * @return The appropriate AccessControlContext for loading classes for this instance
> +     */
> +    public AccessControlContext getAccessControlContextForClassLoading() {
> +        AccessControlContext context = AccessController.getContext();
> +
> +        try {
> +            context.checkPermission(new AllPermission());
> +            return context; // If context already has all permissions, don't bother
> +        } catch (AccessControlException ace) {
> +            // continue below
> +        }
> +
> +        // Since this is for class-loading, technically any class from one jar
> +        // should be able to access a class from another, therefore making the
> +        // original context code source irrelevant
> +        PermissionCollection permissions = this.security.getSandBoxPermissions();
> +
> +        // Local cache access permissions
> +        for (Permission resourcePermission : resourcePermissions) {
> +            permissions.add(resourcePermission);
> +        }
> +
> +        // Permissions for all remote hosting urls
> +        for (URL u: jarLocationSecurityMap.keySet()) {
> +            permissions.add(new SocketPermission(u.getHost(),
> +                                                 "connect, accept"));
> +        }
> +
> +        // Permissions for codebase urls
> +        for (URL u : codeBaseLoader.getURLs()) {
> +            permissions.add(new SocketPermission(u.getHost(),
> +                    "connect, accept"));
> +        }
> +
> +        ProtectionDomain pd = new ProtectionDomain(null, permissions);
> +
> +        return new AccessControlContext(new ProtectionDomain[] { pd });
> +    }
> +
>       /*
>        * Helper class to expose protected URLClassLoader methods.
>        */
> @@ -1931,10 +2032,16 @@
>                   throw new ClassNotFoundException(name);
>
>               try {
> -                return super.findClass(name);
> -            } catch (ClassNotFoundException cnfe) {
> +                final String fName = name;
> +                return AccessController.doPrivileged(
> +                        new PrivilegedExceptionAction<Class<?>>() {
> +                            public Class<?>  run() throws ClassNotFoundException {
> +                                return CodeBaseClassLoader.super.findClass(fName);
> +                            }
> +                        }, parentJNLPClassLoader.getAccessControlContextForClassLoading());
> +            } catch (PrivilegedActionException pae) {
>                   notFoundResources.put(name, super.getURLs());
> -                throw cnfe;
> +                throw new ClassNotFoundException("Could not find class " + name);
>               }
>           }
>
> @@ -1987,8 +2094,18 @@
>               if (Arrays.equals(super.getURLs(), notFoundResources.get(name)))
>                   return null;
>
> +            URL url = null;
>               if (!name.startsWith("META-INF")) {
> -                URL url = super.findResource(name);
> +                try {
> +                    final String fName = name;
> +                    url = AccessController.doPrivileged(
> +                            new PrivilegedExceptionAction<URL>() {
> +                                public URL run() {
> +                                    return CodeBaseClassLoader.super.findResource(fName);
> +                                }
> +                            }, parentJNLPClassLoader.getAccessControlContextForClassLoading());
> +                } catch (PrivilegedActionException pae) {
> +                }
>
>                   if (url == null) {
>                       notFoundResources.put(name, super.getURLs());




More information about the distro-pkg-dev mailing list