ASF Bugzilla – Attachment 25916 Details for
Bug 49785
Enable STARTTLS for JNDIRealm
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
InitialContextFactory which produces TLS enabled LdapContext instances
tlsFactory.diff (text/plain), 7.72 KB, created by
Felix Schumacher
on 2010-08-19 13:04:06 UTC
(
hide
)
Description:
InitialContextFactory which produces TLS enabled LdapContext instances
Filename:
MIME Type:
Creator:
Felix Schumacher
Created:
2010-08-19 13:04:06 UTC
Size:
7.72 KB
patch
obsolete
>diff --git a/java/org/apache/catalina/realm/LdapTlsContextFactory.java b/java/org/apache/catalina/realm/LdapTlsContextFactory.java >new file mode 100644 >index 0000000..1295736 >--- /dev/null >+++ b/java/org/apache/catalina/realm/LdapTlsContextFactory.java >@@ -0,0 +1,177 @@ >+/* >+ * Licensed to the Apache Software Foundation (ASF) under one or more >+ * contributor license agreements. See the NOTICE file distributed with >+ * this work for additional information regarding copyright ownership. >+ * The ASF licenses this file to You under the Apache License, Version 2.0 >+ * (the "License"); you may not use this file except in compliance with >+ * the License. You may obtain a copy of the License at >+ * >+ * http://www.apache.org/licenses/LICENSE-2.0 >+ * >+ * Unless required by applicable law or agreed to in writing, software >+ * distributed under the License is distributed on an "AS IS" BASIS, >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >+ * See the License for the specific language governing permissions and >+ * limitations under the License. >+ */ >+ >+package org.apache.catalina.realm; >+ >+import java.io.IOException; >+import java.lang.reflect.InvocationHandler; >+import java.lang.reflect.InvocationTargetException; >+import java.lang.reflect.Method; >+import java.lang.reflect.Proxy; >+import java.util.Arrays; >+import java.util.HashMap; >+import java.util.Hashtable; >+import java.util.Map; >+import java.util.logging.Logger; >+ >+import javax.naming.Context; >+import javax.naming.NamingException; >+import javax.naming.directory.DirContext; >+import javax.naming.ldap.InitialLdapContext; >+import javax.naming.ldap.LdapContext; >+import javax.naming.ldap.StartTlsRequest; >+import javax.naming.ldap.StartTlsResponse; >+import javax.naming.spi.InitialContextFactory; >+import javax.net.ssl.SSLSession; >+ >+import org.apache.catalina.util.StringManager; >+ >+/** >+ * Implements an {@link InitialContextFactory} which will create >+ * {@link LdapContext} instances which have tls enabled.<br> >+ * >+ * Pooling will be disabled as recommended by sun. >+ * >+ * @author Felix Schumacher >+ * >+ */ >+public class LdapTlsContextFactory implements InitialContextFactory { >+ >+ /** >+ * The string manager for this package. >+ */ >+ protected static StringManager sm = StringManager >+ .getManager(Constants.Package); >+ >+ /** >+ * Proxies a {@link LdapContext} and handles instantiation and close >+ * specially to start TLS and end it. >+ */ >+ private static final class ProxyLdapContext implements InvocationHandler { >+ private final LdapContext delegate; >+ private final StartTlsResponse tls; >+ >+ @SuppressWarnings("unchecked") >+ private ProxyLdapContext(Hashtable origEnv) throws NamingException { >+ Hashtable env = new Hashtable(origEnv); >+ /* >+ * We want to have login to happen after TLS was established, so >+ * save credentials for later usage and remove them from env. >+ */ >+ Map<String, Object> credentials = new HashMap<String, Object>(); >+ for (String key : Arrays.asList(Context.SECURITY_AUTHENTICATION, >+ Context.SECURITY_CREDENTIALS, Context.SECURITY_PRINCIPAL, >+ Context.SECURITY_PROTOCOL)) { >+ Object entry = env.remove(key); >+ if (entry != null) { >+ credentials.put(key, entry); >+ } >+ } >+ delegate = new InitialLdapContext(env, null); >+ tls = (StartTlsResponse) delegate >+ .extendedOperation(new StartTlsRequest()); >+ try { >+ SSLSession negotiate = tls.negotiate(); >+ Logger.getLogger(this.getClass().getCanonicalName()).fine( >+ sm.getString("LDAP connection protocol is {0}", >+ negotiate.getProtocol())); >+ } catch (IOException e) { >+ throw new NamingException(e.getMessage()); >+ } >+ /* >+ * now is the time to reinstate the credentials into env >+ */ >+ for (Map.Entry<String, Object> savedEntry : credentials.entrySet()) { >+ delegate.addToEnvironment(savedEntry.getKey(), savedEntry >+ .getValue()); >+ } >+ } >+ >+ @Override >+ public Object invoke(Object proxy, Method method, Object[] args) >+ throws Throwable { >+ if ("close".equals(method.getName())) { >+ return doClose(delegate); >+ } >+ return method.invoke(delegate, args); >+ } >+ >+ /** >+ * Wrapper to the original close method. It will try to end tls before >+ * closing the underlying connection. >+ * >+ * @param delegate >+ * underlying connection >+ * @return always <code>null</code> >+ * @throws InvocationTargetException >+ * if an {@link IOException} or a {@link NamingException} >+ * was catched while closing the connection >+ */ >+ private Object doClose(LdapContext delegate) >+ throws InvocationTargetException { >+ try { >+ if (tls != null) { >+ try { >+ tls.close(); >+ } catch (IOException e) { >+ throw new InvocationTargetException(e); >+ } >+ } >+ } finally { >+ try { >+ if (delegate != null) { >+ delegate.close(); >+ } >+ } catch (NamingException e) { >+ throw new InvocationTargetException(e); >+ } >+ } >+ return null; >+ } >+ } >+ >+ /** >+ * Environment key under which the JNDI context factory is stored which >+ * shall be used inside the proxy. >+ */ >+ public static final String REAL_INITIAL_CONTEXT_FACTORY = "REAL_INITIAL_CONTEXT_FACTORY"; >+ >+ /** >+ * The JNDI context factory used to acquire our InitialContext. By default, >+ * assumes use of an LDAP server using the standard JNDI LDAP provider. >+ */ >+ private static final String DEFAULT_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; >+ >+ @SuppressWarnings("unchecked") >+ @Override >+ public Context getInitialContext(final Hashtable environment) >+ throws NamingException { >+ final Hashtable proxyEnv = new Hashtable(environment); >+ final Object realFactory; >+ if (environment.contains(REAL_INITIAL_CONTEXT_FACTORY)) { >+ realFactory = environment.get(REAL_INITIAL_CONTEXT_FACTORY); >+ } else { >+ realFactory = DEFAULT_CONTEXT_FACTORY; >+ } >+ proxyEnv.put(Context.INITIAL_CONTEXT_FACTORY, realFactory); >+ proxyEnv.put("com.sun.jndi.ldap.connect.pool", "false"); >+ return (Context) Proxy.newProxyInstance(this.getClass() >+ .getClassLoader(), new Class<?>[] { DirContext.class }, >+ new ProxyLdapContext(proxyEnv)); >+ } >+ >+} >diff --git a/java/org/apache/catalina/realm/LocalStrings.properties b/java/org/apache/catalina/realm/LocalStrings.properties >index b2a6c45..366a959 100644 >--- a/java/org/apache/catalina/realm/LocalStrings.properties >+++ b/java/org/apache/catalina/realm/LocalStrings.properties >@@ -98,3 +98,4 @@ combinedRealm.addRealm=Add "{0}" realm, making a total of "{1}" realms > combinedRealm.realmStartFail=Failed to start "{0}" realm > lockOutRealm.authLockedUser=An attempt was made to authenticate the locked user "{0}" > lockOutRealm.removeWarning=User "{0}" was removed from the failed users cache after {1} seconds to keep the cache size within the limit set >+tlsContextFactory.protocolInfo=connection protocol is {0}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 49785
:
25916
|
32448
|
32465