Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-5062667

LDAP provider does not use correct classloader for resolving proxy classes

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 6
    • 6
    • core-libs
    • b45
    • sparc
    • solaris_9



      Name: gm110360 Date: 06/14/2004


      FULL PRODUCT VERSION :
      java version "1.4.1_02"


      ADDITIONAL OS VERSION INFORMATION :
      SunOS sunny 5.9 Generic_112233-12 sun4u sparc SUNW,Sun-Fire-15000


      A DESCRIPTION OF THE PROBLEM :
      The sun ldap provider for JNDI resolves serialized objects using a custom implementation of ObjectInputStream ( com.sun.jndi.ldap.Obj.LoaderInputStream ).

      This class correctly overrides ObjectInputStream.resolveClass to uses the correct codebases for a given directory entry; however, it does not override ObjectInputStream.resolveProxyClass. This means that interfaces for proxies are resolved using the local classpath, not that specified by the codebases.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      bind a proxy into an LDAP directory, with codebases set, then try to look it up where the proxied class is not in the local class path. The invocation handler will be sucessfuly deserialized, but the overall resolution will fail with ClassNotFound.


      REPRODUCIBILITY :
      This bug can be reproduced always.

      CUSTOMER SUBMITTED WORKAROUND :
       class Obj {
        private static final class LoaderInputStream extends ObjectInputStream {

              protected Class resolveClass(ObjectStreamClass desc)
                      throws IOException, ClassNotFoundException {
                  try {
                      return classLoader.loadClass(desc.getName());
                  } catch (ClassNotFoundException e) {

                      return super.resolveClass(desc);
                  }
              }


              protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException {
                  ClassLoader nonPublicLoader = null;
                  boolean hasNonPublicInterface = false;

                  // define proxy in class loader of non-public interface(s), if any
                  Class[] classObjs = new Class[interfaces.length];
                  for (int i = 0; i < interfaces.length; i++) {
                      Class cl = Class.forName(interfaces[i], false, classLoader);
                      if ((cl.getModifiers() & Modifier.PUBLIC) == 0) {
                          if (hasNonPublicInterface) {
                              if (nonPublicLoader != cl.getClassLoader()) {
                                  throw new IllegalAccessError("conflicting non-public interface class loaders");
                              }
                          } else {
                              nonPublicLoader = cl.getClassLoader();
                              hasNonPublicInterface = true;
                          }
                      }
                      classObjs[i] = cl;
                  }
                  try {
                      return Proxy.getProxyClass(hasNonPublicInterface ? nonPublicLoader : classLoader,
                              classObjs);
                  } catch (IllegalArgumentException e) {
                      throw new ClassNotFoundException(null, e);
                  }
              }

              private ClassLoader classLoader;

              LoaderInputStream(InputStream in, ClassLoader cl)
                      throws IOException {
                  super(in);
                  classLoader = cl;
              }
          }
      }
      (Incident Review ID: 270728)
      ======================================================================

            jhangalsunw Jayalaxmi Hangal (Inactive)
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: