[jcifs] NTLM usrname/password failure after each 5 mins
Michael B Allen
ioplex at gmail.com
Tue Jun 24 18:17:06 GMT 2008
On 6/24/08, Asaf Mesika <asaf.mesika at gmail.com> wrote:
> After investigating some more on the issue, I've found out that the load
> test problem is not in the synchronize issue I've raised, but its in the
> hiccup you've described.
> The Hiccup as I've seen it
> The transport is not being used for 5 minutes, since the load test is using
> the same users, thus jCIFS is using the cache. Once the transport performs
> the disconnect and then the connect, the transport.server.encryptionKey
> changes. Since the encryptionKey is the challenge jCIFS returns to the
> browser on the type2 message, it is the heart of the problem.
> The problem occurs when we send the challenge, before the disconnect ,in
> the type2 message.
Aha. Interesting. Nice work!
Unfortunately this is a little difficult to fix because there is no
way to know if or when the HTTP client will submit hashes that use
that challenge. The HTTP client could get the challenge, sleep for an
hour, and then submit the type-3-message. Or it could get the
challenge and never submit hashes at all. There's no way to handle
both of those cases gracefully. It's just a limitation in trying to do
stateful authentication over a stateless protocol.
However, in practice there are idle periods where no clients are
authenticating and it is safe to disconnect the client and thereby
free associated resources. We just need to >>stop the transport from
disconnecting as long as there are outstanding challenges<<.
To implement this, add a "refcount" to jcifs.util.transport.Transport.
In loop(), detect the soTimeout case (I don't recall what type of
Exception this triggers) and do NOT call disconnect() if refcount > 0.
Then, in SmbSession.interrogate(), change trans.server.encryptionKey
to trans.getEncryptionKey() and in SmbTransport.getEncryptionKey(),
increment trans.refcount++. Also, in SmbSession.logon(), decrement
trans.refcount-- if it is > 0 after the challenge is used.
However, this will result in a net positive refcount value because
clients may not send the type-3-message and, again, in general there
are many things that can go wrong that prevent logon from ever being
called. So, you also need to decrement trans.refcount in another more
aggressive way. For example, you could decrement the refcount every
time you get the exception triggered by soTimeout but do not
disconnect. Meaning refcount will be decremented every time soTimeout
fires. That could be enough to offset any misbehaving clients. You
might also cap the refcount value at some high value that would almost
never be reached with HTTP clients that are behaving properly.
I'm just brainstorming at this point but basically you need to stop
the transport from disconnecting if there are outstanding challenges.
How you detect when there are outstanding challenges and when they
should no longer be counted is up to you.
Michael B Allen
PHP Active Directory SPNEGO SSO
More information about the jcifs