Bug 47841

Summary: CombinedRealm fails to switch to other realm
Product: Tomcat 6 Reporter: Edward <edward.quick>
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 6.0.20   
Target Milestone: default   
Hardware: PC   
OS: Linux   
Attachments: catalina.out - with errors

Description Edward 2009-09-15 02:01:07 UTC
Created attachment 24266 [details]
catalina.out - with errors

I have the following configuration in server.xml to enable authentication
against both the ldap servers and user realm. This works perfectly except for
if both the ldap servers are unreachable, Tomcat doesn't fall back to the user
realm. When I start Tomcat up the requests just hang waiting for a connection
timeout. 

    <Engine name="Catalina" defaultHost="localhost">

      <Realm className="org.apache.catalina.realm.LockOutRealm">

             <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
                       resourceName="UserDatabase"/>

             <Realm className="org.apache.catalina.realm.JNDIRealm"
                       connectionName="${jndi.connectionName}"
                       connectionPassword="${jndi.connectionPassword}"

                       connectionURL="${jndi.connectionURL}"
                       alternateURL="${jndi.alternateURL}"

                       userBase="${jndi.userBase}"
                       userSearch="${jndi.userSearch}"
                       userSubtree="${jndi.userSubtree}"

                       roleBase="${jndi.roleBase}"
                       roleName="${jndi.roleName}"
                       roleSearch="${jndi.roleSearch}"
                       roleSubtree="${jndi.roleSubtree}"

             />


      </Realm>
Comment 1 Mark Thomas 2009-11-22 14:50:41 UTC
In the scenario you describe, with the configuration provided, Tomcat will try the UserdatabaseRealm first and then the JNDIRealm.

If the LDAP server isn't available, then Tomcat will wait for the connection to time out.

The timeout is not currently configurable. It is debatable how useful that would be since if the LDAP server was down, you system is likely to have real issues.

If you have a use case where configuring the timeout would be useful, please create an enhancement request. Enhancement requests with patches and a good justification usually get looked at faster.
Comment 2 Edward 2009-11-23 01:53:21 UTC

(In reply to comment #1)
> In the scenario you describe, with the configuration provided, Tomcat will try
> the UserdatabaseRealm first and then the JNDIRealm.
> 
> If the LDAP server isn't available, then Tomcat will wait for the connection to
> time out.
> 
> The timeout is not currently configurable. It is debatable how useful that
> would be since if the LDAP server was down, you system is likely to have real
> issues.
> 
> If you have a use case where configuring the timeout would be useful, please
> create an enhancement request. Enhancement requests with patches and a good
> justification usually get looked at faster.

Mark,

Thanks for your reply. 

I tested this again, and what surprises me is that if LDAP were down (I simulated this by changing the ldap port number in jndi.connectionURL), then Tomcat won't serve anything. Surely non-protected content should be served regardless of what is going on with LDAP, but I can't even get to the tomcat home page.

I can think of 2 reasons to add a configurable timeout for LDAP:

1. To stop tcp requests stacking up on the server.
2. To aid the user trying to log in, at least realise there's a problem on the server side (and not the client).

Regards,

Edward.
Comment 3 Mark Thomas 2009-12-15 15:31:01 UTC
Ah, I see what is going on here. If one of the nested realms fails to start, the combined realm fails to start. That doesn't seem like a good idea. I'll fix that so the combined realm logs an error but carries on. I'll also look at making the LDAP timeout configurable.
Comment 4 Mark Thomas 2009-12-16 03:09:40 UTC
I have fixed the issue on realm start and also added a connection timeout attribute to the JNDIRealm. These changes have been applied to trunk and proposed for 6.0.x
Comment 5 Edward 2009-12-18 07:36:45 UTC
Hi Mark,

Just to let you know I have tested out your fix for the combined realm and that works perfectly.
 This is the output I saw in catalina.out. Even though tomcat couldn't contact ldap, it carried on working as usual
 and I was able to log in with the UserDatabaseRealm instead.

Thanks for your help on this.

Edward.


INFO: Starting Servlet Engine: Apache Tomcat/7.0.0-dev
18-Dec-2009 15:22:45 org.apache.catalina.realm.JNDIRealm open
WARNING: Exception performing authentication
javax.naming.CommunicationException: lmprdinf901.companyx.local:390 [Root exception is java.net.ConnectException: Connection refused: connect]
        at com.sun.jndi.ldap.Connection.<init>(Connection.java:197)
        at com.sun.jndi.ldap.LdapClient.<init>(LdapClient.java:118)
        at com.sun.jndi.ldap.LdapClient.getInstance(LdapClient.java:1580)
        at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2652)
        at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:293)
        at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:175)
        at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:193)
        at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:136)
        at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:66)
        at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:667)
        at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288)
        at javax.naming.InitialContext.init(InitialContext.java:223)
        at javax.naming.InitialContext.<init>(InitialContext.java:197)
        at javax.naming.directory.InitialDirContext.<init>(InitialDirContext.java:82)
        at org.apache.catalina.realm.JNDIRealm.open(JNDIRealm.java:1951)
        at org.apache.catalina.realm.JNDIRealm.start(JNDIRealm.java:2043)
        at org.apache.catalina.realm.CombinedRealm.start(CombinedRealm.java:237)
        at org.apache.catalina.realm.LockOutRealm.start(LockOutRealm.java:112)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1037)
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:451)
        at org.apache.catalina.core.StandardService.start(StandardService.java:516)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:726)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:580)
        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:597)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: java.net.ConnectException: Connection refused: connect
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
        at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
        at java.net.Socket.connect(Socket.java:525)
        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:597)
        at com.sun.jndi.ldap.Connection.createSocket(Connection.java:336)
        at com.sun.jndi.ldap.Connection.<init>(Connection.java:184)
        ... 28 more
18-Dec-2009 15:22:46 org.apache.catalina.realm.CombinedRealm start
SEVERE: Failed to start "org.apache.catalina.realm.JNDIRealm/1.0" realm
LifecycleException:  Exception opening directory server connection:  javax.naming.CommunicationException: lmprdinf902.ig
i.ig.local:390 [Root exception is java.net.ConnectException: Connection refused: connect]
        at org.apache.catalina.realm.JNDIRealm.start(JNDIRealm.java:2045)
        at org.apache.catalina.realm.CombinedRealm.start(CombinedRealm.java:237)
        at org.apache.catalina.realm.LockOutRealm.start(LockOutRealm.java:112)
        at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1037)
        at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:451)
        at org.apache.catalina.core.StandardService.start(StandardService.java:516)
        at org.apache.catalina.core.StandardServer.start(StandardServer.java:726)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:580)
        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:597)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
18-Dec-2009 15:22:46 org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor host-manager.xml
18-Dec-2009 15:22:46 org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor manager.xml
18-Dec-2009 15:22:46 org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory docs
18-Dec-2009 15:22:46 org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory examples
18-Dec-2009 15:22:47 org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory ROOT
18-Dec-2009 15:22:47 org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
18-Dec-2009 15:22:47 org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8443
18-Dec-2009 15:22:47 org.apache.coyote.ajp.AjpProtocol start
INFO: Starting Coyote AJP/1.3 on ajp-8009
Comment 6 Mark Thomas 2009-12-18 07:44:54 UTC
Glad it works. Just leaving this open until the fix is actually applied to 6.0.x
Comment 7 Mark Thomas 2009-12-19 18:33:04 UTC
Fix applied to 6.0.x and will be in 6.0.21 onwards.