added support for locked users
This commit is contained in:
@ -1,10 +1,17 @@
|
|||||||
package de.muehlencord.shared.network.ldap;
|
package de.muehlencord.shared.network.ldap;
|
||||||
|
|
||||||
|
import de.muehlencord.shared.util.DateUtil;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.BitSet;
|
||||||
|
import java.util.Date;
|
||||||
import javax.naming.NamingEnumeration;
|
import javax.naming.NamingEnumeration;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.naming.directory.Attributes;
|
import javax.naming.directory.Attributes;
|
||||||
import javax.naming.directory.SearchControls;
|
import javax.naming.directory.SearchControls;
|
||||||
import javax.naming.directory.SearchResult;
|
import javax.naming.directory.SearchResult;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection to ldap server to searh by different values
|
* Connection to ldap server to searh by different values
|
||||||
@ -13,6 +20,8 @@ import javax.naming.directory.SearchResult;
|
|||||||
*/
|
*/
|
||||||
public class LDAPSearch {
|
public class LDAPSearch {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(LDAPSearch.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the ldap connection to use
|
* the ldap connection to use
|
||||||
*/
|
*/
|
||||||
@ -26,22 +35,17 @@ public class LDAPSearch {
|
|||||||
* Creates a new instance of a ldap search.
|
* Creates a new instance of a ldap search.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Important: <br> If you want to use ldaps - usually port 636 make sure you
|
* Important: <br> If you want to use ldaps - usually port 636 make sure you provide a trustkeystore in case your ldap server does not use a certificate which can be trusted by the build in root
|
||||||
* provide a trustkeystore in case your ldap server does not use a
|
* certificates. (e.g. self signed certificates) </p>
|
||||||
* certificate which can be trusted by the build in root certificates. (e.g.
|
|
||||||
* self signed certificates) </p>
|
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* To provide access to a trust center you can specify the following
|
* To provide access to a trust center you can specify the following parameter to your application by providing the following parameter
|
||||||
* parameter to your application by providing the following parameter
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* -Djavax.net.ssl.trustStore=/path/to/truststore.keystore
|
* -Djavax.net.ssl.trustStore=/path/to/truststore.keystore
|
||||||
* </pre> </p>
|
* </pre> </p>
|
||||||
*
|
*
|
||||||
* @param url the url of the ldap server to connect to like
|
* @param url the url of the ldap server to connect to like <code>ldap://ldapserver.your.domain:389</code>
|
||||||
* <code>ldap://ldapserver.your.domain:389</code>
|
* @param searchBase the search base to use - e.g. <code>DC=wincor-nixdorf,DC=com</code>
|
||||||
* @param searchBase the search base to use - e.g.
|
|
||||||
* <code>DC=wincor-nixdorf,DC=com</code>
|
|
||||||
* @param username the username to connect with
|
* @param username the username to connect with
|
||||||
* @param password the password to connect with
|
* @param password the password to connect with
|
||||||
*/
|
*/
|
||||||
@ -57,24 +61,19 @@ public class LDAPSearch {
|
|||||||
* Creates a new instance of a ldap search.
|
* Creates a new instance of a ldap search.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* Important: <br> If you want to use ldaps - usually port 636 make sure you
|
* Important: <br> If you want to use ldaps - usually port 636 make sure you provide a trustkeystore in case your ldap server does not use a certificate which can be trusted by the build in root
|
||||||
* provide a trustkeystore in case your ldap server does not use a
|
* certificates. (e.g. self signed certificates) </p>
|
||||||
* certificate which can be trusted by the build in root certificates. (e.g.
|
|
||||||
* self signed certificates) </p>
|
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* To provide access to a trust center you can specify the following
|
* To provide access to a trust center you can specify the following parameter to your application by providing the following parameter
|
||||||
* parameter to your application by providing the following parameter
|
|
||||||
* <pre>
|
* <pre>
|
||||||
* -Djavax.net.ssl.trustStore=/path/to/truststore.keystore
|
* -Djavax.net.ssl.trustStore=/path/to/truststore.keystore
|
||||||
* </pre> </p>
|
* </pre> </p>
|
||||||
*
|
*
|
||||||
* @param authentication the authentification type to use -e.g. "SIMPLE"
|
* @param authentication the authentification type to use -e.g. "SIMPLE"
|
||||||
* @param url the url of the ldap server to connect to like
|
* @param url the url of the ldap server to connect to like <code>ldap://ldapserver.your.domain:389</code>
|
||||||
* <code>ldap://ldapserver.your.domain:389</code>
|
* @param securityProtocol the security protocol to use - e.g. SIMPLE
|
||||||
* @param securityProtoco the security protocol to use - e.g. SIMPLE
|
* @param searchBase the search base to use - e.g. <code>DC=wincor-nixdorf,DC=com</code>
|
||||||
* @param searchBase the search base to use - e.g.
|
|
||||||
* <code>DC=wincor-nixdorf,DC=com</code>
|
|
||||||
* @param username the username to connect with
|
* @param username the username to connect with
|
||||||
* @param password the password to connect with
|
* @param password the password to connect with
|
||||||
*/
|
*/
|
||||||
@ -136,7 +135,7 @@ public class LDAPSearch {
|
|||||||
|
|
||||||
// prepare search parameters
|
// prepare search parameters
|
||||||
String[] resultattributes = {"objectClass", "name", "givenName", "sn", "department", "co", "telephoneNumber", "sAMAccountName", "c",
|
String[] resultattributes = {"objectClass", "name", "givenName", "sn", "department", "co", "telephoneNumber", "sAMAccountName", "c",
|
||||||
"userAccountControl", "managedBy", "distinguishedName", "mail"};
|
"userAccountControl", "managedBy", "distinguishedName", "mail", "lastLogon", "lastLogonTimestamp"};
|
||||||
String searchfilter = "(" + searchField + "=" + searchValue + ")";
|
String searchfilter = "(" + searchField + "=" + searchValue + ")";
|
||||||
SearchControls searchcontrols = new SearchControls();
|
SearchControls searchcontrols = new SearchControls();
|
||||||
String[] resultAttributes = resultattributes;
|
String[] resultAttributes = resultattributes;
|
||||||
@ -168,8 +167,7 @@ public class LDAPSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true, if the given email address can be found in the configured
|
* Returns true, if the given email address can be found in the configured ldap
|
||||||
* ldap
|
|
||||||
*
|
*
|
||||||
* @param email the emailaddress to search for
|
* @param email the emailaddress to search for
|
||||||
* @return true, if the email address could be found; else false
|
* @return true, if the email address could be found; else false
|
||||||
@ -180,12 +178,10 @@ public class LDAPSearch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true, if the given email address is member of the given group,
|
* Returns true, if the given email address is member of the given group, specified by the DN
|
||||||
* specified by the DN
|
|
||||||
*
|
*
|
||||||
* @param email the email to validat
|
* @param email the email to validat
|
||||||
* @param groupDn the group search base - all members must be found as
|
* @param groupDn the group search base - all members must be found as "member" in this group
|
||||||
* "member" in this group
|
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public boolean isMemberOfGroup(String email, String groupDn) throws LDAPException {
|
public boolean isMemberOfGroup(String email, String groupDn) throws LDAPException {
|
||||||
@ -231,6 +227,8 @@ public class LDAPSearch {
|
|||||||
private LDAPContact createLDAPContact(Attributes attributes) throws LDAPException {
|
private LDAPContact createLDAPContact(Attributes attributes) throws LDAPException {
|
||||||
|
|
||||||
LDAPContact ldapContact = new LDAPContact();
|
LDAPContact ldapContact = new LDAPContact();
|
||||||
|
ldapContact.setEnabled(true);
|
||||||
|
long userAccountControlNumber = 0;
|
||||||
|
|
||||||
if (attributes.get("mail") != null) {
|
if (attributes.get("mail") != null) {
|
||||||
ldapContact.setEmailaddress(attributes.get("mail").toString());
|
ldapContact.setEmailaddress(attributes.get("mail").toString());
|
||||||
@ -298,18 +296,19 @@ public class LDAPSearch {
|
|||||||
crmname = crmname.substring(crmname.indexOf(":") + 2);
|
crmname = crmname.substring(crmname.indexOf(":") + 2);
|
||||||
ldapContact.setCrmname(crmname);
|
ldapContact.setCrmname(crmname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes.get("userAccountControl") != null) {
|
if (attributes.get("userAccountControl") != null) {
|
||||||
String userAccountControl = attributes.get("userAccountControl").toString();
|
String userAccountControl = attributes.get("userAccountControl").toString();
|
||||||
userAccountControl = userAccountControl.substring(userAccountControl.indexOf(":") + 2);
|
userAccountControl = userAccountControl.substring(userAccountControl.indexOf(":") + 2);
|
||||||
if (userAccountControl.equals("512")) {
|
userAccountControlNumber = Long.parseLong(userAccountControl);
|
||||||
ldapContact.setEnabled(true);
|
BitSet bitSet = BitSet.valueOf(new long[]{userAccountControlNumber});
|
||||||
} else {
|
// bitSet.get(1) = binary value 2 = UF_ACCOUNT_DISABLE
|
||||||
ldapContact.setEnabled(false);
|
// if bit is set, value is 2
|
||||||
}
|
// if bit is set, account is disabled
|
||||||
} else {
|
ldapContact.setEnabled(!bitSet.get(1));
|
||||||
ldapContact.setEnabled(false);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LDAPContact.TYPE_GROUP:
|
case LDAPContact.TYPE_GROUP:
|
||||||
case LDAPContact.TYPE_PUBLICFOLDER:
|
case LDAPContact.TYPE_PUBLICFOLDER:
|
||||||
// handle groups
|
// handle groups
|
||||||
@ -342,19 +341,57 @@ public class LDAPSearch {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ldapContact;
|
// some workarounds - seems to bit 2 is set too often / too early
|
||||||
|
if (!ldapContact.isEnabled()) {
|
||||||
|
|
||||||
|
if (userAccountControlNumber == 66050) {
|
||||||
|
// locked = 2
|
||||||
|
// normal account = 512
|
||||||
|
// password does not expire = 65536
|
||||||
|
// service users / mailbox groups or similar created as normal user
|
||||||
|
ldapContact.setEnabled(true);
|
||||||
|
} else if ((attributes.get("lastLogon") == null) && (attributes.get("lastLogonTimestamp") == null)) {
|
||||||
|
// users without lastLogon date - probably distribution lists etc
|
||||||
|
ldapContact.setEnabled(true);
|
||||||
|
LOGGER.info("Found locked user without lastLogon - probably a shared mailbox - asuming user is still active");
|
||||||
|
} else if ((attributes.get("lastLogon") != null) || (attributes.get("lastLogonTimestamp") != null)) {
|
||||||
|
// check if users have been logged in recently
|
||||||
|
String lastLogonDateString;
|
||||||
|
if (attributes.get("lastLogon") == null) {
|
||||||
|
lastLogonDateString = attributes.get("lastLogonTimestamp").toString();
|
||||||
|
} else {
|
||||||
|
lastLogonDateString = attributes.get("lastLogon").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastLogonDateString.contains(":")) {
|
||||||
|
lastLogonDateString = lastLogonDateString.substring(lastLogonDateString.indexOf(":") + 1).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
long lastLogonDate = Long.parseLong(lastLogonDateString);
|
||||||
|
if (lastLogonDate == 0) {
|
||||||
|
ldapContact.setEnabled(true);
|
||||||
|
LOGGER.info("Found locked user without lastLogon - probably a shared mailbox - asuming user is still active");
|
||||||
|
} else {
|
||||||
|
lastLogonDate = (lastLogonDate / 10000L) - +11644473600000L;
|
||||||
|
|
||||||
|
Date date = new Date(lastLogonDate);
|
||||||
|
LocalDateTime lastLogonDateTime = DateUtil.getDateTime(date);
|
||||||
|
|
||||||
|
LocalDateTime referenceDate = DateUtil.getUtcDateTime(DateUtil.getCurrentTimeInUTC());
|
||||||
|
referenceDate = referenceDate.minus(120, ChronoUnit.DAYS);
|
||||||
|
|
||||||
|
if (lastLogonDateTime.isAfter(referenceDate)) {
|
||||||
|
ldapContact.setEnabled(true);
|
||||||
|
LOGGER.info("Found locked user who recently logged in - asuming user is still active");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if (!ldapContact.isEnabled()) {
|
||||||
* History:
|
LOGGER.info("User {} is locked", ldapContact.getEmailaddress());
|
||||||
*
|
}
|
||||||
* $$Log: src/main/java/com/wincornixdorf/shared/network/ldap/LDAPSearch.java $
|
|
||||||
* Revision 1.1 2013/12/16 16:42:52MEZ Muehlencord, Joern (joern.muehlencord)
|
return ldapContact;
|
||||||
* Initial revision Member added to project
|
}
|
||||||
* m:/MKS/ESP_Tools/shared/shared-network/shared-network.pj $Revision 1.6
|
}
|
||||||
* 2013/09/05 07:14:33 jomu $fixed ldap search if group setup is not complete.
|
|
||||||
* (1147451) $ $Revision 1.5 2013/09/04 15:07:26 jomu $fixed ldap search if
|
|
||||||
* group setup is not complete. (1147451) $$
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|||||||
Reference in New Issue
Block a user