You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2010/12/22 14:47:14 UTC
svn commit: r1051897 - in /karaf/trunk:
jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java
manual/src/main/webapp/developers-guide/security-framework.conf
Author: gnodet
Date: Wed Dec 22 13:47:13 2010
New Revision: 1051897
URL: http://svn.apache.org/viewvc?rev=1051897&view=rev
Log:
[KARAF-307] Add support for SSL on the LDAPLoginModule
Modified:
karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java
karaf/trunk/manual/src/main/webapp/developers-guide/security-framework.conf
Modified: karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java
URL: http://svn.apache.org/viewvc/karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java?rev=1051897&r1=1051896&r2=1051897&view=diff
==============================================================================
--- karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java (original)
+++ karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/ldap/LDAPLoginModule.java Wed Dec 22 13:47:13 2010
@@ -17,17 +17,21 @@ package org.apache.karaf.jaas.modules.ld
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.karaf.jaas.config.KeystoreManager;
import org.apache.karaf.jaas.modules.AbstractKarafLoginModule;
import org.apache.karaf.jaas.modules.RolePrincipal;
import org.apache.karaf.jaas.modules.UserPrincipal;
+import org.osgi.framework.ServiceReference;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.*;
+import javax.net.ssl.SSLSocketFactory;
import javax.security.auth.Subject;
import javax.security.auth.callback.*;
import javax.security.auth.login.LoginException;
import java.io.IOException;
+import java.security.GeneralSecurityException;
import java.security.Principal;
import java.util.HashSet;
import java.util.Hashtable;
@@ -39,6 +43,7 @@ import java.util.Map;
* </p>
*
* @author jbonofre
+ * @author gnodet
*/
public class LDAPLoginModule extends AbstractKarafLoginModule {
@@ -56,6 +61,13 @@ public class LDAPLoginModule extends Abs
public final static String ROLE_SEARCH_SUBTREE = "role.search.subtree";
public final static String AUTHENTICATION = "authentication";
public final static String INITIAL_CONTEXT_FACTORY = "initial.context.factory";
+ public final static String SSL = "ssl";
+ public final static String SSL_PROVIDER = "ssl.provider";
+ public final static String SSL_PROTOCOL = "ssl.protocol";
+ public final static String SSL_ALGORITHM = "ssl.algorithm";
+ public final static String SSL_KEYSTORE = "ssl.keystore";
+ public final static String SSL_KEYALIAS = "ssl.keyalias";
+ public final static String SSL_TRUSTSTORE = "ssl.truststore";
public final static String DEFAULT_INITIAL_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
@@ -71,6 +83,13 @@ public class LDAPLoginModule extends Abs
private boolean roleSearchSubtree = true;
private String authentication = "simple";
private String initialContextFactory = null;
+ private boolean ssl;
+ private String sslProvider;
+ private String sslProtocol;
+ private String sslAlgorithm;
+ private String sslKeystore;
+ private String sslKeyAlias;
+ private String sslTrustStore;
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
super.initialize(subject, callbackHandler, options);
@@ -79,15 +98,11 @@ public class LDAPLoginModule extends Abs
connectionPassword = (String) options.get(CONNECTION_PASSWORD);
userBaseDN = (String) options.get(USER_BASE_DN);
userFilter = (String) options.get(USER_FILTER);
- if (options.get(USER_SEARCH_SUBTREE) != null) {
- userSearchSubtree = Boolean.getBoolean((String) options.get(USER_SEARCH_SUBTREE));
- }
+ userSearchSubtree = Boolean.parseBoolean((String) options.get(USER_SEARCH_SUBTREE));
roleBaseDN = (String) options.get(ROLE_BASE_DN);
roleFilter = (String) options.get(ROLE_FILTER);
roleNameAttribute = (String) options.get(ROLE_NAME_ATTRIBUTE);
- if (options.get(ROLE_SEARCH_SUBTREE) != null) {
- roleSearchSubtree = Boolean.getBoolean((String) options.get(ROLE_SEARCH_SUBTREE));
- }
+ roleSearchSubtree = Boolean.parseBoolean((String) options.get(ROLE_SEARCH_SUBTREE));
initialContextFactory = (String) options.get(INITIAL_CONTEXT_FACTORY);
if (initialContextFactory == null) {
initialContextFactory = DEFAULT_INITIAL_CONTEXT_FACTORY;
@@ -98,9 +113,30 @@ public class LDAPLoginModule extends Abs
} else if (!connectionURL.startsWith("ldap:")) {
LOG.error("Invalid LDAP URL.");
}
+ if (options.get(SSL) != null) {
+ ssl = Boolean.parseBoolean((String) options.get(SSL));
+ } else {
+ ssl = connectionURL.startsWith("ldaps:");
+ }
+ sslProvider = (String) options.get(SSL_PROVIDER);
+ sslProtocol = (String) options.get(SSL_PROTOCOL);
+ sslAlgorithm = (String) options.get(SSL_ALGORITHM);
+ sslKeystore = (String) options.get(SSL_KEYSTORE);
+ sslKeyAlias = (String) options.get(SSL_KEYALIAS);
+ sslTrustStore = (String) options.get(SSL_TRUSTSTORE);
}
public boolean login() throws LoginException {
+ ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+ try {
+ return doLogin();
+ } finally {
+ ManagedSSLSocketFactory.setSocketFactory(null);
+ Thread.currentThread().setContextClassLoader(tccl);
+ }
+ }
+
+ protected boolean doLogin() throws LoginException {
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("Username: ");
callbacks[1] = new PasswordCallback("Password: ", false);
@@ -133,8 +169,11 @@ public class LDAPLoginModule extends Abs
env.put(Context.SECURITY_PRINCIPAL, connectionUsername);
env.put(Context.SECURITY_CREDENTIALS, connectionPassword);
}
+ if (ssl) {
+ setupSsl(env);
+ }
LOG.debug("Get the user DN.");
- String userDN = null;
+ String userDN;
try {
LOG.debug("Initialize the JNDI LDAP Dir Context.");
DirContext context = new InitialDirContext(env);
@@ -205,6 +244,24 @@ public class LDAPLoginModule extends Abs
return true;
}
+ protected void setupSsl(Hashtable env) throws LoginException {
+ ServiceReference ref = null;
+ try {
+ LOG.debug("Setting up SSL");
+ env.put(Context.SECURITY_PROTOCOL, "ssl");
+ env.put("java.naming.ldap.factory.socket", ManagedSSLSocketFactory.class.getName());
+ ref = bundleContext.getServiceReference(KeystoreManager.class.getName());
+ KeystoreManager manager = (KeystoreManager) bundleContext.getService(ref);
+ SSLSocketFactory factory = manager.createSSLFactory(sslProvider, sslProtocol, sslAlgorithm, sslKeystore, sslKeyAlias, sslTrustStore);
+ ManagedSSLSocketFactory.setSocketFactory(factory);
+ Thread.currentThread().setContextClassLoader(ManagedSSLSocketFactory.class.getClassLoader());
+ } catch (Exception e) {
+ throw new LoginException("Unable to setup SSL support for LDAP: " + e.getMessage());
+ } finally {
+ bundleContext.ungetService(ref);
+ }
+ }
+
public boolean abort() throws LoginException {
return true;
}
@@ -215,4 +272,22 @@ public class LDAPLoginModule extends Abs
return true;
}
+ public static abstract class ManagedSSLSocketFactory extends SSLSocketFactory {
+
+ private static final ThreadLocal<SSLSocketFactory> factories = new ThreadLocal<SSLSocketFactory>();
+
+ public static void setSocketFactory(SSLSocketFactory factory) {
+ factories.set(factory);
+ }
+
+ public static SSLSocketFactory getDefault() {
+ SSLSocketFactory factory = factories.get();
+ if (factory == null) {
+ throw new IllegalStateException("No SSLSocketFactory parameters have been set!");
+ }
+ return factory;
+ }
+
+ }
+
}
Modified: karaf/trunk/manual/src/main/webapp/developers-guide/security-framework.conf
URL: http://svn.apache.org/viewvc/karaf/trunk/manual/src/main/webapp/developers-guide/security-framework.conf?rev=1051897&r1=1051896&r2=1051897&view=diff
==============================================================================
--- karaf/trunk/manual/src/main/webapp/developers-guide/security-framework.conf (original)
+++ karaf/trunk/manual/src/main/webapp/developers-guide/security-framework.conf Wed Dec 22 13:47:13 2010
@@ -83,7 +83,6 @@ Here are two example using this schema:
{pygmentize}
{pygmentize:xml}
<jaas:keystore xmlns:jaas="http://karaf.apache.org/xmlns/jaas/v1.0.0"
- id="keystore"
name="ks"
rank="1"
path="classpath:privatestore.jks"
@@ -199,6 +198,13 @@ The LDAPLoginModule supports the followi
| {{role.search.subtree}} | If "true", the role lookup will be recursive (SUBTREE). If "false", the role lookup will be performed only at the first level (ONELEVEL). |
| {{authentication}} | Define the authentication backend used on the LDAP server. The default is simple. |
| {{initial.context.factory}} | Define the initial context factory used to connect to the LDAP server. The default is com.sun.jndi.ldap.LdapCtxFactory |
+| {{ssl}} | If "true" or if the protocol on the {{connection.url}} is {{ldaps}}, an SSL connection will be used |
+| {{ssl.provider}} | The provider name to use for SSL |
+| {{ssl.protocol}} | The protocol name to use for SSL (SSL for example)|
+| {{ssl.algorithm}} | The algorithm to use for the KeyManagerFactory and TrustManagerFactory (PKIX for example) |
+| {{ssl.keystore}} | The key store name to use for SSL. The key store must be deployed using a {{jaas:keystore}} configuration. |
+| {{ssl.keyalias}} | The key alias to use for SSL |
+| {{ssl.truststore}} | The trust store name to use for SSL. The trust store must be deployed using a {{jaas:keystore}} configuration. |
A example of LDAPLoginModule usage follows:
@@ -218,6 +224,33 @@ A example of LDAPLoginModule usage follo
</jaas:config>
{pygmentize}
+If you want to use an SSL connection, the following configuration can be used as an example:
+{pygmentize:xml}
+<ext:property-placeholder />
+
+<jaas:config name="karaf" rank="1">
+ <jaas:module className="org.apache.karaf.jaas.modules.ldap.LDAPLoginModule" flags="required">
+ connection.url = ldaps://localhost:10636
+ user.base.dn = ou=users,ou=system
+ user.filter = (uid=%u)
+ user.search.subtree = true
+ role.base.dn = ou=groups,ou=system
+ role.filter = (uniqueMember=uid=%u)
+ role.name.attribute = cn
+ role.search.subtree = true
+ authentication = simple
+ ssl.protocol=SSL
+ ssl.truststore=ks
+ ssl.algorithm=PKIX
+ </jaas:module>
+</jaas:config>
+
+<jaas:keystore name="ks"
+ path="file:///${karaf.home}/etc/trusted.ks"
+ keystorePassword="secret" />
+{pygmentize}
+
+
h2. Encryption service
The [EncryptionService|http://svn.apache.org/repos/asf/karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/EncryptionService.java] is a service registered in the OSGi registry providing means to encrypt and check encrypted passwords. This service acts as a factory for [Encryption|http://svn.apache.org/repos/asf/karaf/trunk/jaas/modules/src/main/java/org/apache/karaf/jaas/modules/Encryption.java] objects actually performing the encryption.