Using the JNDIRealm for authentication, if the LDAP server is set to automatically disconnect the client (in this case, tomcat's JNDIRealm), tomcat does not discover this until it attempts another login. If the connection has been reset, it results in a failed login attempt for the user. So the first time somebody logs into the application after some period of time (I think the timeout is pretty short on our LDAP server), the user will get one failed login attempt before a real one. I've not seen in the documentation any properties on the JNDIRealm an amount of time to hold the connection open before electively disconnecting it. 2005-02-28 07:47:39 JNDIRealm[/iso]: Searching for myuserid 2005-02-28 07:47:39 JNDIRealm[/iso]: base: ou=users,dc=company,dc=com filter: (&(objectClass=user)(uid=myuserid)) 2005-02-28 07:47:39 JNDIRealm[/iso]: Exception performing authentication javax.naming.CommunicationException: Connection reset [Root exception is java.net.SocketException: Connection reset]; remaining name 'ou=ou=users,dc=company,dc=com' at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1961) at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1806) at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1731) at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search (ComponentDirContext.java:368) at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search (PartialCompositeDirContext.java:338) at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search (PartialCompositeDirContext.java:321) at javax.naming.directory.InitialDirContext.search (InitialDirContext.java:248) at org.apache.catalina.realm.JNDIRealm.getUserBySearch (JNDIRealm.java:1074) at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:967) at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:916) at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:809) at org.apache.catalina.authenticator.FormAuthenticator.authenticate (FormAuthenticator.java:235) at org.apache.catalina.authenticator.AuthenticatorBase.invoke (AuthenticatorBase.java:446) at org.apache.catalina.core.StandardValveContext.invokeNext (StandardValveContext.java:102) at org.apache.catalina.core.StandardPipeline.invoke (StandardPipeline.java:520) at org.apache.catalina.core.StandardHostValve.invoke (StandardHostValve.java:137) at org.apache.catalina.core.StandardValveContext.invokeNext (StandardValveContext.java:104) at org.apache.catalina.valves.ErrorReportValve.invoke (ErrorReportValve.java:118) at org.apache.catalina.core.StandardValveContext.invokeNext (StandardValveContext.java:102) at org.apache.catalina.core.StandardPipeline.invoke (StandardPipeline.java:520) at org.apache.catalina.core.StandardEngineValve.invoke (StandardEngineValve.java:109) at org.apache.catalina.core.StandardValveContext.invokeNext (StandardValveContext.java:104) at org.apache.catalina.core.StandardPipeline.invoke (StandardPipeline.java:520) at org.apache.catalina.core.ContainerBase.invoke (ContainerBase.java:929) at org.apache.coyote.tomcat5.CoyoteAdapter.service (CoyoteAdapter.java:160) at org.apache.jk.server.JkCoyoteHandler.invoke (JkCoyoteHandler.java:300) at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:374) at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:743) at org.apache.jk.common.ChannelSocket.processConnection (ChannelSocket.java:675) at org.apache.jk.common.SocketConnection.runIt(ChannelSocket.java:866) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run (ThreadPool.java:684) at java.lang.Thread.run(Thread.java:595) Caused by: java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:168) at java.io.BufferedInputStream.fill(BufferedInputStream.java:218) at java.io.BufferedInputStream.read1(BufferedInputStream.java:256) at java.io.BufferedInputStream.read(BufferedInputStream.java:313) at com.sun.jndi.ldap.Connection.run(Connection.java:780) ... 1 more 2005-02-28 07:47:39 JNDIRealm[/iso]: Closing directory context
The amount of time to hold a connection open on the Tomcat JNDIRealm side wouldn't matter, though, would it? It's the LDAP server that's disconnecting the connection, not Tomcat. Looking at the current JNDIRealm code, in the authenticate method, it already tries twice automatically to account for the first-time failure. It tries once, and if a CommunicationException occurs (as is the case you report), it tries again. However, if the exception message is not null and does not contain "close", it won't try again. Maybe it's this check that's the problem.
Right, but when handling the said communication exception: // If contains the work closed. Then assume socket is closed. // If message is null, assume the worst and allow the // connection to be closed. if (e.getMessage()!=null && e.getMessage().indexOf("closed") < 0) throw(e); Here, the text is: exception performing authentication javax.naming.CommunicationException: Connection reset [Root exception is java.net.SocketException: Connection reset]; remaining name 'ou=ou=users,dc=company,dc=com' So no "closed", which means there won't be any retry. This type of hack is bad: we should just retry once anyway. I'm changing that in 5.5.x.
I hope when you say you're going to retry once anyway, you ONLY mean if there's a CommunicationException - if under normal circumstances, a user puts in a bad password, an exception is thrown - if you try again with any type of exception, it could trigger an account lockout. (I'll have to try a bad password to see what the precise exception is.)
We have a CVS browser, so how about verifying in the code that I did the right thing ? I did not test it, I simply removed the portions of code which looked highly suspicious.
The code looks decent to me. Will, please test 5.5.9 which will be out in a couple of days, and if it still fails reopen this issue. Thanks.
The patch looks ok to me too. For historical reference see ... http://cvs.apache.org/viewcvs.cgi/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/realm/JNDIRealm.java revision 1.12. At one time, there was even more specific logic looking for "Socket closed".
The first login attempt each morning fails because the LDAP server has closed the idle connection. We are running Tomcat 5.5.15 It looks to me as though this results in a ServiceUnavailableException rather than a CommunicationException which the previous fix addressed. Apr 17, 2007 8:18:38 AM org.apache.catalina.realm.JNDIRealm authenticate SEVERE: Exception performing authentication javax.naming.ServiceUnavailableException: public.ldap.uq.edu.au:389; socket closed; remaining name 'ou=People,o=The University of Queensland,c=AU' at com.sun.jndi.ldap.Connection.readReply(Connection.java:410) at com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:340) at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:170) at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2637) at com.sun.jndi.ldap.LdapCtx.ensureOpen(LdapCtx.java:2546) at com.sun.jndi.ldap.LdapCtx.ensureOpen(LdapCtx.java:2520) at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1901) at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1806) at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1731) at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search(ComponentDirContext.java:368) at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java: 338) at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search(PartialCompositeDirContext.java: 321) at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:248) at org.apache.catalina.realm.JNDIRealm.getUserBySearch(JNDIRealm.java:1055) at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:958) at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:907) at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:808) at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:257) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:416) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148) at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:199) at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:282) at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:754) at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:684) at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:876) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684) at java.lang.Thread.run(Thread.java:595)
This has been fixed in svn and will be included in 5.5.24 and 6.0.14 onwards.
(In reply to comment #8) > This has been fixed in svn and will be included in 5.5.24 and 6.0.14 onwards. I have recently tried using the JNDIRealm in 6.0.14 and it appears this problem has not been fixed. I cannot post the message because it is on an internal system, but the error message is the same "connection reset" problem as before. Maybe the fix did not reach this release?!
The "connection reset" message refers to a problem that never existed in the 6.0.x series - it was fixed before that series was started. Please check your configuration via the users list. If you still see the problem, you will need to post the stack trace (you can XXX out server names, ports etc from the stack trace) so we can figure out where the problem lies.
This is NOT fixed on a Solaris platform in 5.5.25 although 5.5.17 works ok on Windows XP. See below.... 29-Jan-2008 14:35:30 org.apache.catalina.realm.JNDIRealm authenticate SEVERE: Exception performing authentication javax.naming.ServiceUnavailableException: ldap2.dundee.ac.uk:389; socket closed; remaining name 'o= dundee' at com.sun.jndi.ldap.Connection.readReply(Connection.java:416) at com.sun.jndi.ldap.LdapClient.getSearchReply(LdapClient.java:611) at com.sun.jndi.ldap.LdapClient.search(LdapClient.java:534) at com.sun.jndi.ldap.LdapCtx.doSearch(LdapCtx.java:1948) at com.sun.jndi.ldap.LdapCtx.searchAux(LdapCtx.java:1810) at com.sun.jndi.ldap.LdapCtx.c_search(LdapCtx.java:1735) at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_search (ComponentDirContext.java:368) at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search (PartialCompositeDirContext.ja va:338) at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.search (PartialCompositeDirContext.ja va:321) at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:248) at org.apache.catalina.realm.JNDIRealm.getUserBySearch(JNDIRealm.java:1051) at org.apache.catalina.realm.JNDIRealm.getUser(JNDIRealm.java:959) at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:908) at org.apache.catalina.realm.JNDIRealm.authenticate(JNDIRealm.java:809) at org.apache.catalina.authenticator.FormAuthenticator.authenticate (FormAuthenticator.java: 258) at org.apache.catalina.authenticator.AuthenticatorBase.invoke (AuthenticatorBase.java:417) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117) at org.apache.catalina.core.StandardEngineValve.invoke (StandardEngineValve.java:108) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:151) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:870) at org.apache.coyote.http11.Http11BaseProtocol $Http11ConnectionHandler.processConnection(Ht tp11BaseProtocol.java:665) at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket (PoolTcpEndpoint.java:528) at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt (LeaderFollowerWorkerThread.j ava:81) at org.apache.tomcat.util.threads.ThreadPool $ControlRunnable.run(ThreadPool.java:685) at java.lang.Thread.run(Thread.java:619)
(In reply to comment #11) > This is NOT fixed on a Solaris platform in 5.5.25 although 5.5.17 works ok on > Windows XP. See below.... That it works on an earlier release on XP and fails on a later release on Solaris is a strong indication of a configuration problem on Solaris. That said, there was a minor improvement to the fix in 5.5.26. I don't think it will help but it is worth trying. If you still have problems, please use the users list in the first instance as this looks like a configuration issue.
(In reply to comment #12) > (In reply to comment #11) > > This is NOT fixed on a Solaris platform in 5.5.25 although 5.5.17 works ok on > > Windows XP. See below.... > That it works on an earlier release on XP and fails on a later release on > Solaris is a strong indication of a configuration problem on Solaris. That said, > there was a minor improvement to the fix in 5.5.26. I don't think it will help > but it is worth trying. > If you still have problems, please use the users list in the first instance as > this looks like a configuration issue. No response from users list. Its just this first time delay after the remote server has closed the connection thats the pain. (it eventually authenticates ok once the timeout has expired). Which is this timeout? Can't find what configuration to look at ( server.xml 's match on both platforms ). Some pointers much appreciated.