Skip to content

Commit

Permalink
Merge pull request traccar#3638 from Abyss777/ldap_improve
Browse files Browse the repository at this point in the history
Improve LDAP
  • Loading branch information
tananaev authored Nov 14, 2017
2 parents e6e762c + e0f16f7 commit e48863c
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 16 deletions.
2 changes: 1 addition & 1 deletion setup/default.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

<entry key='database.loginUser'>
SELECT * FROM users
WHERE email = :email
WHERE email = :email OR login = :email
</entry>

<entry key='database.selectPositions'>
Expand Down
2 changes: 1 addition & 1 deletion src/org/traccar/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ public static void init(String[] arguments) throws Exception {
}

if (config.getBoolean("ldap.enable")) {
ldapProvider = new LdapProvider(config.getString("ldap.url"), config.getString("ldap.context"));
ldapProvider = new LdapProvider(config);
}

if (config.hasKey("media.path")) {
Expand Down
11 changes: 6 additions & 5 deletions src/org/traccar/database/DataManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,13 @@ public class DataManager {

private boolean generateQueries;

private boolean forceLdap;

public DataManager(Config config) throws Exception {
this.config = config;

forceLdap = config.getBoolean("ldap.force");

initDatabase();
initDatabaseSchema();
}
Expand Down Expand Up @@ -304,15 +308,12 @@ public User login(String email, String password) throws SQLException {
LdapProvider ldapProvider = Context.getLdapProvider();
if (user != null) {
if (ldapProvider != null && ldapProvider.login(user.getLogin(), password)
|| user.isPasswordValid(password)) {
|| !forceLdap && user.isPasswordValid(password)) {
return user;
}
} else {
if (ldapProvider != null && ldapProvider.login(email, password)) {
user = new User();
user.setName(email);
user.setEmail(email);
user.setLogin(email);
user = ldapProvider.getUser(email);
Context.getUsersManager().addItem(user);
return user;
}
Expand Down
143 changes: 134 additions & 9 deletions src/org/traccar/database/LdapProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,161 @@
package org.traccar.database;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.traccar.Config;
import org.traccar.helper.Log;
import org.traccar.model.User;

import java.util.Hashtable;

public class LdapProvider {

private String url;
private String context;
private String searchBase;
private String idAttribute;
private String nameAttribute;
private String mailAttribute;
private String searchFilter;
private String adminFilter;
private String serviceUser;
private String servicePassword;

public LdapProvider(String url, String context) {
this.url = url;
this.context = context;
public LdapProvider(Config config) {
String url = config.getString("ldap.url");
if (url != null) {
this.url = url;
} else {
this.url = "ldap://" + config.getString("ldap.server") + ":" + config.getInteger("ldap.port", 389);
}
this.searchBase = config.getString("ldap.base");
this.idAttribute = config.getString("ldap.idAttribute", "uid");
this.nameAttribute = config.getString("ldap.nameAttribute", "cn");
this.mailAttribute = config.getString("ldap.mailAttribute", "mail");
this.searchFilter = config.getString("ldap.searchFilter", "(" + idAttribute + "=:login)");
String adminGroup = config.getString("ldap.adminGroup");
this.adminFilter = config.getString("ldap.adminFilter");
if (this.adminFilter == null && adminGroup != null) {
this.adminFilter = "(&(" + idAttribute + "=:login)(memberOf=" + adminGroup + "))";
}
this.serviceUser = config.getString("ldap.user");
this.servicePassword = config.getString("ldap.password");
}

public boolean login(String username, String password) {

private InitialDirContext auth(String accountName, String password) throws NamingException {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, url);

env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=" + username + "," + context);
env.put(Context.SECURITY_PRINCIPAL, accountName);
env.put(Context.SECURITY_CREDENTIALS, password);

return new InitialDirContext(env);
}

private boolean isAdmin(String accountName) {
if (this.adminFilter != null) {
try {
InitialDirContext context = initContext();
String searchString = new String(adminFilter).replace(":login", accountName);
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
NamingEnumeration<SearchResult> results = context.search(searchBase, searchString, searchControls);
if (results.hasMoreElements()) {
results.nextElement();
if (results.hasMoreElements()) {
Log.warning("Matched multiple users for the accountName: " + accountName);
return false;
}
return true;
}
} catch (NamingException e) {
return false;
}
}
return false;
}

public InitialDirContext initContext() throws NamingException {
return auth(serviceUser, servicePassword);
}

private SearchResult lookupUser(String accountName) throws NamingException {
InitialDirContext context = initContext();

String searchString = new String(searchFilter).replace(":login", accountName);

SearchControls searchControls = new SearchControls();
String[] attributeFilter = {idAttribute, nameAttribute, mailAttribute};
searchControls.setReturningAttributes(attributeFilter);
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);

NamingEnumeration<SearchResult> results = context.search(searchBase, searchString, searchControls);

SearchResult searchResult = null;
if (results.hasMoreElements()) {
searchResult = (SearchResult) results.nextElement();
if (results.hasMoreElements()) {
Log.warning("Matched multiple users for the accountName: " + accountName);
return null;
}
}

return searchResult;
}

public User getUser(String accountName) {
SearchResult ldapUser;
User user = new User();
try {
ldapUser = lookupUser(accountName);
if (ldapUser != null) {
Attribute attribute = ldapUser.getAttributes().get(idAttribute);
if (attribute != null) {
user.setLogin((String) attribute.get());
} else {
user.setLogin(accountName);
}
attribute = ldapUser.getAttributes().get(nameAttribute);
if (attribute != null) {
user.setName((String) attribute.get());
} else {
user.setName(accountName);
}
attribute = ldapUser.getAttributes().get(mailAttribute);
if (attribute != null) {
user.setEmail((String) attribute.get());
} else {
user.setEmail(accountName);
}
}
user.setAdmin(isAdmin(accountName));
} catch (NamingException e) {
user.setLogin(accountName);
user.setName(accountName);
user.setEmail(accountName);
Log.warning(e);
}
return user;
}

public boolean login(String username, String password) {
try {
new InitialDirContext(env).close();
return true;
SearchResult ldapUser = lookupUser(username);
if (ldapUser != null) {
auth(ldapUser.getNameInNamespace(), password).close();
return true;
}
} catch (NamingException e) {
return false;
}
return false;
}

}

0 comments on commit e48863c

Please sign in to comment.