[jcifs] More classloader issues

Glass, Eric eric.glass at capitalone.com
Sat Dec 14 02:34:17 EST 2002


> 	The "only way"? Putting it in the container's CLASSPATH 
> works. At least with
> 	Resin it does. I have Resin running NetworkExplorer 
> servlet at work which uses
> 	the NtlmHttpFilter and the NtlmPasswordAuthentication 
> object returned by it to
> 	access SmbFile resources. I put the jar in the 
> top-level resin lib directory.
> 

Sorry -- I should have further qualified this statement as "under Tomcat".
The issue stems from how the different servlet containers implement web
application classloaders.

Attached is a servlet which prints out some information regarding the
classloaders used for some key classes.  Also attached is the output when
run under Tomcat and Resin.

Resin appends necessary support classes (core servlet classes, etc.) to the
system classpath; it then creates a child classloader for each web
application (this is necessary under any servlet container, to prevent the
occurrence that 2 web applications have identically-named classes).

Tomcat operates a bit differently -- rather than appending to the system
classpath, it creates a classloader for the "common" libraries (including
the core servlet library) which has the system classloader as its parent.
It then creates a "shared" classloader as a child of the common classloader
(for shared libraries not required by the container itself), and a
classloader for each web application, which has the shared classloader as
its parent.

So the Tomcat classloader hierarchy looks like this (from
http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html):

      Bootstrap
          |
       System
          |
       Common
      /      \
 Catalina   Shared
             /   \
        Webapp1  Webapp2 ...

Neither implementation is wrong; just different.  But the implication of
Tomcat's approach is that classes loaded by the system classloader (or the
boot classloader, which is where URL is actually loaded) cannot see classes
from the common classloader -- including javax.servlet.Filter, etc..
Ordinarily, this would not be an issue.  But in order for URL to properly
load the SMB URL handler, it must be installed under the system (or boot)
classloader.  Upon further investigation, this is why URL does:

Class cls = null;
try {
    cls = Class.forName(clsName);
} catch (ClassNotFoundException e) {
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    if (cl != null) {
        cls = cl.loadClass(clsName);
    }
}

The first attempt will load classes from the BOOT classloader (which is the
defining classloader for the URL class).  The second will load from the
SYSTEM classloader.  This is also why my previous detection code did not
work; I was trying to load the SMB handler directly from URL's classloader
(the boot classpath) rather than the system classloader (which is where it
will be).

The problem will arise under Tomcat when NtlmFilter is loaded; it will find
the implementation under the system classloader, but NtlmFilter will be
unable to find javax.servlet.Filter (which is loaded under the common
classloader).  This will cause a NoClassDefFoundError, specifically:

java.lang.NoClassDefFoundError: javax/servlet/Filter
	at java.lang.ClassLoader.defineClass0(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:509)
	at
java.security.SecureClassLoader.defineClass(SecureClassLoader.java:123)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:246)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:54)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:193)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:186)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:299)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:265)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:262)
	at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.jav
a:1340)
	at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.jav
a:1274)
	at
org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilter
Config.java:252)
	at
org.apache.catalina.core.ApplicationFilterConfig.setFilterDef(ApplicationFil
terConfig.java:314)
	at
org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterCon
fig.java:120)
	at
org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:31
39)
	at
org.apache.catalina.core.StandardContext.start(StandardContext.java:3528)
	at
org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:8
21)
	at
org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:807)
	at
org.apache.catalina.core.StandardHost.addChild(StandardHost.java:579)
	at
org.apache.catalina.core.StandardHostDeployer.install(StandardHostDeployer.j
ava:257)
	at
org.apache.catalina.core.StandardHost.install(StandardHost.java:772)
	at
org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:569
)
	at
org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:411)
	at org.apache.catalina.startup.HostConfig.start(HostConfig.java:879)
	at
org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:368)
	at
org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSuppor
t.java:166)
	at
org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1196)
	at
org.apache.catalina.core.StandardHost.start(StandardHost.java:738)
	at
org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1188)
	at
org.apache.catalina.core.StandardEngine.start(StandardEngine.java:347)
	at
org.apache.catalina.core.StandardService.start(StandardService.java:497)
	at
org.apache.catalina.core.StandardServer.start(StandardServer.java:2189)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:510)
	at org.apache.catalina.startup.Catalina.execute(Catalina.java:400)
	at org.apache.catalina.startup.Catalina.process(Catalina.java:180)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39
)
	at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl
.java:25)
	at java.lang.reflect.Method.invoke(Method.java:324)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:203)


Tomcat users will experience similar errors whenever classes loaded under
the system classloader attempt to access classes available only to the
common classloader.

A workaround for Tomcat users (short of splitting jCIFS into two jars) would
be to move servlet.jar (the core servlet classes) from
$TOMCAT_HOME/common/lib into the jre/lib/ext directory (or make it otherwise
available to the system classloader).

> >  one contains
> > the core jCIFS classes (and should be installed as an 
> extension or otherwise
> > under the system classloader).  The other contains the http 
> stuff, and
> > should be installed under the web application classloader (i.e., in
> > WEB-INF/lib).
> > 
> 	I don't want to break up the package unnecessarily. If 
> someone has permission
> 	to add the jar to the jre/lib/ext directory that 
> implies they have permission to add
> 	it to the container CLASSPATH.
> 
> 	So the solution to both the class loader and security 
> policy issues is to just make
> 	sure that the jCIFS jar is in the container's 
> CLASSPATH. Presumably these
> 	security policy files are associated with files loaded 
> by web apps rather than the
> 	container itself. Right?
> 
> 

The security policy would be applied and enforced by the servlet container;
the settings would apply to the entire JVM (although typically it would
grant AllPermission to the container codebase, so your statement would
generally be correct in that this would solve the classloader issues related
to SMB URLs).  The location/filename of the policy file would be
container-specific (as would the means of telling the container to apply the
policy); Tomcat uses "catalina.policy" by default (in the "conf"
subdirectory).  When enforced by launching Tomcat with the "-security" flag,
this provides a level of protection against malicious servlets by installing
a security manager which enforces the policy (via
System.setSecurityManager).  The person responsible for maintaining the
servlet container would edit this file and add the line:

    permission java.util.PropertyPermission "java.protocol.handler.pkgs",
"read, write";

to either the global "grant" section, or to a grant covering the codebase
under which jCIFS is installed -- i.e., you could do:

    grant {
        ... other global grants here
        permission java.util.PropertyPermission
"java.protocol.handler.pkgs", "read, write";
    };

which would grant permission to read and write the
"java.protocol.handler.pkgs" property to all code running anywhere; you
could also do:

    grant codeBase "file:/some/relevant/location/jcifs-0.7.0bx.jar" {
        permission java.util.PropertyPermission
"java.protocol.handler.pkgs", "read, write";
    };

which would grant this only to classes loaded from the jCIFS jar.  If
installed as an extension under the jre/lib/ext directory, none of this
would typically be necessary; extensions are usually granted full system
access via:

    grant codeBase "file:${java.home}/jre/lib/ext/-" {
        permission java.security.AllPermission;
    };

Likewise, a similar grant section would typically exist to grant
AllPermission to the codebase from which the container loads its classes.

Eric
 
**************************************************************************
The information transmitted herewith is sensitive information intended only
for use by the individual or entity to which it is addressed. If the reader
of this message is not the intended recipient, you are hereby notified that
any review, retransmission, dissemination, distribution, copying or other
use of, or taking of any action in reliance upon this information is
strictly prohibited. If you have received this communication in error,
please contact the sender and delete the material from your computer.
      

-------------- next part --------------
A non-text attachment was scrubbed...
Name: ContainerInfo.java
Type: application/octet-stream
Size: 3163 bytes
Desc: not available
Url : http://lists.samba.org/archive/jcifs/attachments/20021213/50edc494/ContainerInfo.obj
-------------- next part --------------
System Class Loader Type:    sun.misc.Launcher$AppClassLoader
System Class Loader:         sun.misc.Launcher$AppClassLoader at 2f6684
--------------------------------------------------------------------------------
Servlet Code Source:         (file:/C:/resin-2.1.6/lib/jsdk23.jar <no certificates>)
Servlet Class Loader Type:   sun.misc.Launcher$AppClassLoader
Servlet Class Loader:        sun.misc.Launcher$AppClassLoader at 2f6684
--------------------------------------------------------------------------------
This Code Source:            (null <no certificates>)
This Class Loader Type:      com.caucho.java.CompilingClassLoader
This Class Loader:           [CompilingClassLoader src:/C:/resin-2.1.6/webapps/info/WEB-INF/classes]
--------------------------------------------------------------------------------
sun.boot.class.path:         c:\java\jre\lib\rt.jar;c:\java\jre\lib\i18n.jar;c:\java\jre\lib\sunrsasign.jar;c:\java\jre\lib\jsse.jar;c:\java\jre\lib\jce.jar;c:\java\jre\lib\charsets.jar;c:\java\jre\classes
java.endorsed.dirs:          c:\java\jre\lib\endorsed
java.ext.dirs:               c:\java\jre\lib\ext
java.class.path:             classes;C:\resin-2.1.6\classes;C:\resin-2.1.6\lib\resin.jar;c:\java\lib\tools.jar;c:\java\jre\lib\rt.jar;C:\resin-2.1.6\lib\dom.jar;C:\resin-2.1.6\lib\jaxp.jar;C:\resin-2.1.6\lib\jdbc-mysql.jar;C:\resin-2.1.6\lib\jdbc2_0-stdext.jar;C:\resin-2.1.6\lib\jmx.jar;C:\resin-2.1.6\lib\jndi.jar;C:\resin-2.1.6\lib\jsdk23.jar;C:\resin-2.1.6\lib\jta-spec1_0_1.jar;C:\resin-2.1.6\lib\sax.jar;C:\resin-2.1.6\lib\webutil.jar
--------------------------------------------------------------------------------
-- listing properties --
java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
sun.boot.library.path=c:\java\jre\bin
java.vm.version=1.4.0_01-b03
java.vm.vendor=Sun Microsystems Inc.
java.vendor.url=http://java.sun.com/
path.separator=;
java.vm.name=Java HotSpot(TM) Client VM
file.encoding.pkg=sun.io
user.country=US
sun.os.patch.level=Service Pack 2
java.vm.specification.name=Java Virtual Machine Specification
user.dir=C:\resin-2.1.6
org.xml.sax.driver=com.caucho.xml.Xml
java.runtime.version=1.4.0_01-b03
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=c:\java\jre\lib\endorsed
os.arch=x86
java.io.tmpdir=C:\WINNT\Temp\
line.separator=

java.vm.specification.vendor=Sun Microsystems Inc.
user.variant=
java.naming.factory.url.pkgs=com.caucho.naming
os.name=Windows 2000
resin.home=C:\resin-2.1.6
sun.java2d.fontpath=
java.library.path=c:\java\bin;.;C:\WINNT\System32;C:\WI...
java.specification.name=Java Platform API Specification
java.class.version=48.0
java.util.prefs.PreferencesFactory=java.util.prefs.WindowsPreferencesFac...
os.version=5.0
user.home=C:\Documents and Settings\eglass
user.timezone=America/New_York
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=Cp1252
java.specification.version=1.4
user.name=eglass
java.class.path=classes;C:\resin-2.1.6\classes;C:\res...
java.naming.factory.initial=com.caucho.naming.InitialContextFacto...
java.vm.specification.version=1.0
sun.arch.data.model=32
java.home=c:\java\jre
java.specification.vendor=Sun Microsystems Inc.
user.language=en
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode
java.version=1.4.0_01
java.ext.dirs=c:\java\jre\lib\ext
sun.boot.class.path=c:\java\jre\lib\rt.jar;c:\java\jre\li...
java.vendor=Sun Microsystems Inc.
file.separator=\
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.cpu.isalist=pentium i486 i386


-------------- next part --------------
System Class Loader Type:    sun.misc.Launcher$AppClassLoader
System Class Loader:         sun.misc.Launcher$AppClassLoader at 2f6684
--------------------------------------------------------------------------------
Servlet Code Source:         (file:C:/jakarta-tomcat/basic/common/lib/servlet.jar <no certificates>)
Servlet Class Loader Type:   org.apache.catalina.loader.StandardClassLoader
Servlet Class Loader:        StandardClassLoader
  available:
    Extension[org.apache.tools.ant, implementationVendor=Apache Software Foundation, implementationVersion=1.5, specificationVendor=Apache Software Foundation, specificationVersion=1.5]
    Extension[org.apache.commons.collections, implementationVendor=Apache Software Foundation, implementationVersion=1.1-dev, specificationVendor=Apache Software Foundation, specificationVersion=1.0]
    Extension[org.apache.commons.logging, implementationVendor=Apache Software Foundation, implementationVersion=1.0.1, specificationVendor=Apache Software Foundation, specificationVersion=1.0]
    Extension[org.apache.commons.pool, implementationVendor=Apache Software Foundation, implementationVersion=1.0, specificationVendor=Apache Software Foundation, specificationVersion=1.0]
    Extension[javax.mail, implementationVendor=Sun Microsystems, Inc., implementationVendorId=com.sun, implementationVersion=1.2, specificationVendor=Sun Microsystems, Inc., specificationVersion=1.2]
  delegate: true
  repositories:
    file:C:\jakarta-tomcat\basic\common\lib\activation.jar
    file:C:\jakarta-tomcat\basic\common\lib\ant.jar
    file:C:\jakarta-tomcat\basic\common\lib\commons-collections.jar
    file:C:\jakarta-tomcat\basic\common\lib\commons-dbcp.jar
    file:C:\jakarta-tomcat\basic\common\lib\commons-logging-api.jar
    file:C:\jakarta-tomcat\basic\common\lib\commons-pool.jar
    file:C:\jakarta-tomcat\basic\common\lib\jasper-compiler.jar
    file:C:\jakarta-tomcat\basic\common\lib\jasper-runtime.jar
    file:C:\jakarta-tomcat\basic\common\lib\jaxrpc-api.jar
    file:C:\jakarta-tomcat\basic\common\lib\jaxrpc-ri.jar
    file:C:\jakarta-tomcat\basic\common\lib\mail.jar
    file:C:\jakarta-tomcat\basic\common\lib\msbase.jar
    file:C:\jakarta-tomcat\basic\common\lib\mssqlserver.jar
    file:C:\jakarta-tomcat\basic\common\lib\msutil.jar
    file:C:\jakarta-tomcat\basic\common\lib\naming-common.jar
    file:C:\jakarta-tomcat\basic\common\lib\naming-factory.jar
    file:C:\jakarta-tomcat\basic\common\lib\naming-resources.jar
    file:C:\jakarta-tomcat\basic\common\lib\ojdbc14.jar
    file:C:\jakarta-tomcat\basic\common\lib\saaj-api.jar
    file:C:\jakarta-tomcat\basic\common\lib\saaj-ri.jar
    file:C:\jakarta-tomcat\basic\common\lib\servlet.jar
    file:C:\jakarta-tomcat\basic\common\lib\soap.jar
    file:C:\jakarta-tomcat\basic\common\lib\tidy.jar
  required:
----------> Parent Classloader:
sun.misc.Launcher$AppClassLoader at 2f6684

--------------------------------------------------------------------------------
This Code Source:            (file:/C:/jakarta-tomcat/basic/work/Standalone/localhost/info/WEB-INF/classes/ContainerInfo.class <no certificates>)
This Class Loader Type:      org.apache.catalina.loader.WebappClassLoader
This Class Loader:           WebappClassLoader
  available:
  delegate: false
  repositories:
    /WEB-INF/classes/
  required:
----------> Parent Classloader:
StandardClassLoader
  available:
  delegate: true
  repositories:
  required:
----------> Parent Classloader:
StandardClassLoader
  available:
    Extension[org.apache.tools.ant, implementationVendor=Apache Software Foundation, implementationVersion=1.5, specificationVendor=Apache Software Foundation, specificationVersion=1.5]
    Extension[org.apache.commons.collections, implementationVendor=Apache Software Foundation, implementationVersion=1.1-dev, specificationVendor=Apache Software Foundation, specificationVersion=1.0]
    Extension[org.apache.commons.logging, implementationVendor=Apache Software Foundation, implementationVersion=1.0.1, specificationVendor=Apache Software Foundation, specificationVersion=1.0]
    Extension[org.apache.commons.pool, implementationVendor=Apache Software Foundation, implementationVersion=1.0, specificationVendor=Apache Software Foundation, specificationVersion=1.0]
    Extension[javax.mail, implementationVendor=Sun Microsystems, Inc., implementationVendorId=com.sun, implementationVersion=1.2, specificationVendor=Sun Microsystems, Inc., specificationVersion=1.2]
  delegate: true
  repositories:
    file:C:\jakarta-tomcat\basic\common\lib\activation.jar
    file:C:\jakarta-tomcat\basic\common\lib\ant.jar
    file:C:\jakarta-tomcat\basic\common\lib\commons-collections.jar
    file:C:\jakarta-tomcat\basic\common\lib\commons-dbcp.jar
    file:C:\jakarta-tomcat\basic\common\lib\commons-logging-api.jar
    file:C:\jakarta-tomcat\basic\common\lib\commons-pool.jar
    file:C:\jakarta-tomcat\basic\common\lib\jasper-compiler.jar
    file:C:\jakarta-tomcat\basic\common\lib\jasper-runtime.jar
    file:C:\jakarta-tomcat\basic\common\lib\jaxrpc-api.jar
    file:C:\jakarta-tomcat\basic\common\lib\jaxrpc-ri.jar
    file:C:\jakarta-tomcat\basic\common\lib\mail.jar
    file:C:\jakarta-tomcat\basic\common\lib\msbase.jar
    file:C:\jakarta-tomcat\basic\common\lib\mssqlserver.jar
    file:C:\jakarta-tomcat\basic\common\lib\msutil.jar
    file:C:\jakarta-tomcat\basic\common\lib\naming-common.jar
    file:C:\jakarta-tomcat\basic\common\lib\naming-factory.jar
    file:C:\jakarta-tomcat\basic\common\lib\naming-resources.jar
    file:C:\jakarta-tomcat\basic\common\lib\ojdbc14.jar
    file:C:\jakarta-tomcat\basic\common\lib\saaj-api.jar
    file:C:\jakarta-tomcat\basic\common\lib\saaj-ri.jar
    file:C:\jakarta-tomcat\basic\common\lib\servlet.jar
    file:C:\jakarta-tomcat\basic\common\lib\soap.jar
    file:C:\jakarta-tomcat\basic\common\lib\tidy.jar
  required:
----------> Parent Classloader:
sun.misc.Launcher$AppClassLoader at 2f6684



--------------------------------------------------------------------------------
sun.boot.class.path:         ..\bin\bootstrap.jar;..\bin\commons-daemon.jar;..\bin\tomcat-jni.jar;c:\java\jre\lib\rt.jar;c:\java\jre\lib\i18n.jar;c:\java\jre\lib\sunrsasign.jar;c:\java\jre\lib\jsse.jar;c:\java\jre\lib\jce.jar;c:\java\jre\lib\charsets.jar;c:\java\jre\classes
java.endorsed.dirs:          ..\bin;..\common\endorsed
java.ext.dirs:               c:\java\jre\lib\ext
java.class.path:             c:\java\lib\tools.jar;..\bin\bootstrap.jar
--------------------------------------------------------------------------------
-- listing properties --
java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
sun.boot.library.path=c:\java\jre\bin
java.vm.version=1.4.0_01-b03
java.vm.vendor=Sun Microsystems Inc.
java.vendor.url=http://java.sun.com/
path.separator=;
java.vm.name=Java HotSpot(TM) Client VM
file.encoding.pkg=sun.io
user.country=US
sun.os.patch.level=Service Pack 2
java.vm.specification.name=Java Virtual Machine Specification
user.dir=C:\jakarta-tomcat\basic\bin
java.runtime.version=1.4.0_01-b03
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
java.endorsed.dirs=..\bin;..\common\endorsed
os.arch=x86
java.io.tmpdir=..\temp
line.separator=

java.vm.specification.vendor=Sun Microsystems Inc.
user.variant=
java.naming.factory.url.pkgs=org.apache.naming
os.name=Windows 2000
sun.java2d.fontpath=
java.library.path=c:\java\bin;.;C:\WINNT\System32;C:\WI...
java.specification.name=Java Platform API Specification
java.class.version=48.0
java.util.prefs.PreferencesFactory=java.util.prefs.WindowsPreferencesFac...
os.version=5.0
user.home=C:\Documents and Settings\eglass
user.timezone=America/New_York
catalina.useNaming=true
java.awt.printerjob=sun.awt.windows.WPrinterJob
file.encoding=Cp1252
java.specification.version=1.4
catalina.home=..
user.name=eglass
java.class.path=c:\java\lib\tools.jar;..\bin\bootstra...
java.naming.factory.initial=org.apache.naming.java.javaURLContext...
java.vm.specification.version=1.0
sun.arch.data.model=32
java.home=c:\java\jre
java.specification.vendor=Sun Microsystems Inc.
user.language=en
awt.toolkit=sun.awt.windows.WToolkit
java.vm.info=mixed mode
java.version=1.4.0_01
java.ext.dirs=c:\java\jre\lib\ext
sun.boot.class.path=..\bin\bootstrap.jar;..\bin\commons-d...
java.vendor=Sun Microsystems Inc.
catalina.base=..
file.separator=\
java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...
sun.cpu.endian=little
sun.io.unicode.encoding=UnicodeLittle
sun.cpu.isalist=pentium i486 i386




More information about the jcifs mailing list