[DS-1518] Support of StartTLS in LDAPAuthentication.

This commit is contained in:
Christian Scheible
2016-01-25 16:59:18 +01:00
committed by Ivan Masár
parent ca963c3378
commit 7cf90d3db2
2 changed files with 123 additions and 37 deletions

View File

@@ -7,6 +7,7 @@
*/ */
package org.dspace.authenticate; package org.dspace.authenticate;
import java.io.IOException;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Hashtable; import java.util.Hashtable;
@@ -14,7 +15,16 @@ import java.util.List;
import javax.naming.NamingEnumeration; import javax.naming.NamingEnumeration;
import javax.naming.NamingException; import javax.naming.NamingException;
import javax.naming.directory.*; import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.naming.ldap.StartTlsRequest;
import javax.naming.ldap.StartTlsResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -405,6 +415,8 @@ public class LDAPAuthentication
String ldap_phone_field = ConfigurationManager.getProperty("authentication-ldap", "phone_field"); String ldap_phone_field = ConfigurationManager.getProperty("authentication-ldap", "phone_field");
String ldap_group_field = ConfigurationManager.getProperty("authentication-ldap", "login.groupmap.attribute"); String ldap_group_field = ConfigurationManager.getProperty("authentication-ldap", "login.groupmap.attribute");
boolean useTLS = ConfigurationManager.getBooleanProperty("authentication-ldap", "starttls", false);
SpeakerToLDAP(Logger thelog) SpeakerToLDAP(Logger thelog)
{ {
log = thelog; log = thelog;
@@ -432,17 +444,44 @@ public class LDAPAuthentication
} }
// Set up environment for creating initial context // Set up environment for creating initial context
Hashtable env = new Hashtable(11); Hashtable<String, String> env = new Hashtable<String, String>();
env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url); env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url);
LdapContext ctx = null;
StartTlsResponse startTLSResponse = null;
try
{
if ((adminUser != null) && (!adminUser.trim().equals("")) && if ((adminUser != null) && (!adminUser.trim().equals("")) &&
(adminPassword != null) && (!adminPassword.trim().equals(""))) (adminPassword != null) && (!adminPassword.trim().equals("")))
{
if(useTLS)
{
ctx = new InitialLdapContext(env, null);
// start TLS
startTLSResponse = (StartTlsResponse) ctx
.extendedOperation(new StartTlsRequest());
startTLSResponse.negotiate();
// perform simple client authentication
ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "simple");
ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL,
adminUser);
ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS,
adminPassword);
}
else
{ {
// Use admin credentials for search// Authenticate // Use admin credentials for search// Authenticate
env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple"); env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple");
env.put(javax.naming.Context.SECURITY_PRINCIPAL, adminUser); env.put(javax.naming.Context.SECURITY_PRINCIPAL, adminUser);
env.put(javax.naming.Context.SECURITY_CREDENTIALS, adminPassword); env.put(javax.naming.Context.SECURITY_CREDENTIALS, adminPassword);
// Create initial context
ctx = new InitialLdapContext(env, null);
}
} }
else else
{ {
@@ -450,12 +489,6 @@ public class LDAPAuthentication
env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "none"); env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "none");
} }
DirContext ctx = null;
try
{
// Create initial context
ctx = new InitialDirContext(env);
Attributes matchAttrs = new BasicAttributes(true); Attributes matchAttrs = new BasicAttributes(true);
matchAttrs.put(new BasicAttribute(ldap_id_field, netid)); matchAttrs.put(new BasicAttribute(ldap_id_field, netid));
@@ -465,8 +498,17 @@ public class LDAPAuthentication
SearchControls ctrls = new SearchControls(); SearchControls ctrls = new SearchControls();
ctrls.setSearchScope(ldap_search_scope_value); ctrls.setSearchScope(ldap_search_scope_value);
String searchName = "";
if(useTLS)
{
searchName = ldap_search_context;
}
else
{
searchName = ldap_provider_url + ldap_search_context;
}
NamingEnumeration<SearchResult> answer = ctx.search( NamingEnumeration<SearchResult> answer = ctx.search(
ldap_provider_url + ldap_search_context, searchName,
"(&({0}={1}))", new Object[] { ldap_id_field, "(&({0}={1}))", new Object[] { ldap_id_field,
netid }, ctrls); netid }, ctrls);
@@ -542,7 +584,7 @@ public class LDAPAuthentication
+ e)); + e));
} }
} }
catch (NamingException e) catch (NamingException | IOException e)
{ {
log.warn(LogManager.getHeader(context, log.warn(LogManager.getHeader(context,
"ldap_authentication", "type=failed_auth " + e)); "ldap_authentication", "type=failed_auth " + e));
@@ -552,12 +594,16 @@ public class LDAPAuthentication
// Close the context when we're done // Close the context when we're done
try try
{ {
if (startTLSResponse != null)
{
startTLSResponse.close();
}
if (ctx != null) if (ctx != null)
{ {
ctx.close(); ctx.close();
} }
} }
catch (NamingException e) catch (NamingException | IOException e)
{ {
} }
} }
@@ -572,12 +618,42 @@ public class LDAPAuthentication
protected boolean ldapAuthenticate(String netid, String password, protected boolean ldapAuthenticate(String netid, String password,
Context context) { Context context) {
if (!password.equals("")) { if (!password.equals("")) {
LdapContext ctx = null;
StartTlsResponse startTLSResponse = null;
// Set up environment for creating initial context // Set up environment for creating initial context
Hashtable<String, String> env = new Hashtable<String, String>(); Hashtable<String, String> env = new Hashtable<String, String>();
env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory"); "com.sun.jndi.ldap.LdapCtxFactory");
env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url); env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url);
try
{
if(useTLS)
{
ctx = new InitialLdapContext(env, null);
// start TLS
startTLSResponse = (StartTlsResponse) ctx
.extendedOperation(new StartTlsRequest());
startTLSResponse.negotiate();
// perform simple client authentication
ctx.addToEnvironment(javax.naming.Context.SECURITY_AUTHENTICATION, "simple");
ctx.addToEnvironment(javax.naming.Context.SECURITY_PRINCIPAL,
netid);
ctx.addToEnvironment(javax.naming.Context.SECURITY_CREDENTIALS,
password);
ctx.addToEnvironment(javax.naming.Context.AUTHORITATIVE, "true");
ctx.addToEnvironment(javax.naming.Context.REFERRAL, "follow");
// dummy operation to check if authentication has succeeded
ctx.getAttributes("");
}
else if (!useTLS)
{
// Authenticate // Authenticate
env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "Simple"); env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "Simple");
env.put(javax.naming.Context.SECURITY_PRINCIPAL, netid); env.put(javax.naming.Context.SECURITY_PRINCIPAL, netid);
@@ -585,25 +661,32 @@ public class LDAPAuthentication
env.put(javax.naming.Context.AUTHORITATIVE, "true"); env.put(javax.naming.Context.AUTHORITATIVE, "true");
env.put(javax.naming.Context.REFERRAL, "follow"); env.put(javax.naming.Context.REFERRAL, "follow");
DirContext ctx = null;
try {
// Try to bind // Try to bind
ctx = new InitialDirContext(env); ctx = new InitialLdapContext(env, null);
} catch (NamingException e) { }
}
catch (NamingException | IOException e)
{
// something went wrong (like wrong password) so return false
log.warn(LogManager.getHeader(context, log.warn(LogManager.getHeader(context,
"ldap_authentication", "type=failed_auth " + e)); "ldap_authentication", "type=failed_auth " + e));
return false; return false;
} finally { } finally
{
// Close the context when we're done // Close the context when we're done
try { try {
if (startTLSResponse != null)
{
startTLSResponse.close();
}
if (ctx != null) if (ctx != null)
{ {
ctx.close(); ctx.close();
} }
} catch (NamingException e) { } catch (NamingException | IOException e) {}
} }
} } else
} else { {
return false; return false;
} }

View File

@@ -167,3 +167,6 @@ authentication-ldap.autoregister = true
#authentication-ldap.login.groupmap.2 = ldap-dept2:dspace-groupA #authentication-ldap.login.groupmap.2 = ldap-dept2:dspace-groupA
#authentication-ldap.login.groupmap.3 = ldap-dept3:dspace-groupA #authentication-ldap.login.groupmap.3 = ldap-dept3:dspace-groupA
# Enables support for StartTLS (default is false). If this flag is true be sure provider_url looks like:
# ldap://ldap.myu.edu:389
#authentication-ldap.starttls=true