[jcifs] jcifs on J2EE compliant server

Glass, Eric eric.glass at capitalone.com
Wed Dec 11 22:23:13 EST 2002


> 
> > This is fairly interesting... one of the internal Sun One 
> classes is 
> > apparently attempting to cast the 
> NtlmPasswordAuthentication object to 
> > something it does not implement.  Since it couldn't 
> conceivably have any 
> > knowledge regarding the internal jCIFS classes, my only 
> guess would be 
> > that it is attempting to serialize the objects in the 
> HttpSession (and 
> > is casting the NtlmPasswordAuthentication object to 
> > java.io.Serializable).  This would require more investigation to 
> > confirm, however.  If this turns out to be the case, 
> > NtlmPasswordAuthentication could be made to implement Serializable 
> > fairly easily; in fact, you could just add it to the 
> implements class 
> > and recompile the jCIFS classes if you wanted to test this out.
> > 
> 	I don't see how this would work. The ansiHash and 
> unicodeHash are
> 	specific to a particular SmbTransport. If an 
> NtlmPasswordAuthentication
> 	object is marshalled into another/new VM using some 
> form of serialization
> 	the hashes will be wrong. Or is this not what the 
> container is trying to do?
> 
> 
> 

That was pure speculation on my part -- servlet containers are required to
support storage of Serializable objects in the session, but are NOT required
to support storage of non-serializable objects (although most do, and simply
throw exceptions upon attempts to actually serialize the session).  The
container is supposed to throw an IllegalArgumentException upon insertion
into the session of an invalid object (defined by the spec as "objects where
the container cannot support the mechanism necessary for migration of a
session storing them").  I was just speculating that the container was
instead simply casting to Serializable.  This is incorrect -- I downloaded
the Sun One application server (a hefty 97 MB) and did some further
investigation.  One of the app server's internal classes is attempting to
do:

if (httpservletrequest.getUserPrincipal() != null) {
    WebPrincipal webprincipal = (WebPrincipal)
httpservletrequest.getUserPrincipal();
    ....
}

It is essentially trying to cast the principal object (in our case, an
NtlmPasswordAuthentication) to an internal principal implementation (which
would work if our filter was not being applied).  This will fail when any
filter is used which applies a request wrapper and overrides
getUserPrincipal to return a different implementation.  This would appear to
be a bug in the Sun One application server; according to the servlet spec:

"Central to the notion of filtering is the concept of wrapping a request or
response in
order that it can override behavior to perform a filtering task. In this
model, the
developer not only has the ability to override existing methods on the
request and
response objects, but to provide new API suited to a particular filtering
task to a
filter or target web resource down the chain. For example, the developer may
wish to
extend the response object with higher level output objects that the output
stream or
the writer, such as API that allows DOM objects to be written back to the
client.

In order to support this style of filter the container must support the
following
requirement. When a filter invokes the doFilter method on the container's
filter
chain implementation, the container must ensure that the request and
response
object that it passes to the next entity in the filter chain, or to the
target web
resource if the filter was the last in the chain, is the same object that
was passed
into the doFilter method by the calling filter."


In other terms, when our filter calls:

	chain.doFilter(new NtlmHttpServletRequest(req, ntlm), response);

it is the container's responsibility to ensure that the next filter (or
target resource) in the chain receives the NtlmHttpServletRequest object we
passed in.  It is therefore NOT safe for the application server to assume
that any specific implementation will be provided.

It IS required that the wrapper class wrap the request provided to the
doFilter method (this ensures that at the top of the wrapped "stack" the
container's implementation class is present); therefore, one correct
approach for the Sun One class would be:


while (httpservletrequest instanceof HttpServletRequestWrapper) {
    httpservletrequest = (HttpServletRequest)
            ((HttpServletRequestWrapper) httpservletrequest).getRequest();
}
if (httpservletrequest.getUserPrincipal() != null) {
    WebPrincipal webprincipal = (WebPrincipal)
httpservletrequest.getUserPrincipal();
    ....
}


That is, they need to fully unwrap the request to ensure that they are
dealing with the base request object.

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.



More information about the jcifs mailing list