added support for locked users

This commit is contained in:
Joern Muehlencord
2019-06-25 13:06:53 +02:00
parent bf590223b8
commit 3ae4dba8fe

View File

@ -1,10 +1,17 @@
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.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Connection to ldap server to searh by different values
@ -13,6 +20,8 @@ import javax.naming.directory.SearchResult;
*/
public class LDAPSearch {
private static final Logger LOGGER = LoggerFactory.getLogger(LDAPSearch.class);
/**
* the ldap connection to use
*/
@ -26,22 +35,17 @@ public class LDAPSearch {
* Creates a new instance of a ldap search.
*
* <p>
* 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 certificates. (e.g.
* self signed certificates) </p>
* 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
* certificates. (e.g. self signed certificates) </p>
*
* <p>
* To provide access to a trust center you can specify the following
* parameter to your application by providing the following parameter
* To provide access to a trust center you can specify the following parameter to your application by providing the following parameter
* <pre>
* -Djavax.net.ssl.trustStore=/path/to/truststore.keystore
* </pre> </p>
*
* @param url the url of the ldap server to connect to like
* <code>ldap://ldapserver.your.domain:389</code>
* @param searchBase the search base to use - e.g.
* <code>DC=wincor-nixdorf,DC=com</code>
* @param url the url of the ldap server to connect to like <code>ldap://ldapserver.your.domain:389</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 password the password to connect with
*/
@ -57,24 +61,19 @@ public class LDAPSearch {
* Creates a new instance of a ldap search.
*
* <p>
* 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 certificates. (e.g.
* self signed certificates) </p>
* 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
* certificates. (e.g. self signed certificates) </p>
*
* <p>
* To provide access to a trust center you can specify the following
* parameter to your application by providing the following parameter
* To provide access to a trust center you can specify the following parameter to your application by providing the following parameter
* <pre>
* -Djavax.net.ssl.trustStore=/path/to/truststore.keystore
* </pre> </p>
*
* @param authentication the authentification type to use -e.g. "SIMPLE"
* @param url the url of the ldap server to connect to like
* <code>ldap://ldapserver.your.domain:389</code>
* @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 url the url of the ldap server to connect to like <code>ldap://ldapserver.your.domain:389</code>
* @param securityProtocol 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 username the username to connect with
* @param password the password to connect with
*/
@ -136,7 +135,7 @@ public class LDAPSearch {
// prepare search parameters
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 + ")";
SearchControls searchcontrols = new SearchControls();
String[] resultAttributes = resultattributes;
@ -168,8 +167,7 @@ public class LDAPSearch {
}
/**
* Returns true, if the given email address can be found in the configured
* ldap
* Returns true, if the given email address can be found in the configured ldap
*
* @param email the emailaddress to search for
* @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,
* specified by the DN
* Returns true, if the given email address is member of the given group, specified by the DN
*
* @param email the email to validat
* @param groupDn the group search base - all members must be found as
* "member" in this group
* @param groupDn the group search base - all members must be found as "member" in this group
* @return
*/
public boolean isMemberOfGroup(String email, String groupDn) throws LDAPException {
@ -231,6 +227,8 @@ public class LDAPSearch {
private LDAPContact createLDAPContact(Attributes attributes) throws LDAPException {
LDAPContact ldapContact = new LDAPContact();
ldapContact.setEnabled(true);
long userAccountControlNumber = 0;
if (attributes.get("mail") != null) {
ldapContact.setEmailaddress(attributes.get("mail").toString());
@ -298,18 +296,19 @@ public class LDAPSearch {
crmname = crmname.substring(crmname.indexOf(":") + 2);
ldapContact.setCrmname(crmname);
}
if (attributes.get("userAccountControl") != null) {
String userAccountControl = attributes.get("userAccountControl").toString();
userAccountControl = userAccountControl.substring(userAccountControl.indexOf(":") + 2);
if (userAccountControl.equals("512")) {
ldapContact.setEnabled(true);
} else {
ldapContact.setEnabled(false);
}
} else {
ldapContact.setEnabled(false);
userAccountControlNumber = Long.parseLong(userAccountControl);
BitSet bitSet = BitSet.valueOf(new long[]{userAccountControlNumber});
// bitSet.get(1) = binary value 2 = UF_ACCOUNT_DISABLE
// if bit is set, value is 2
// if bit is set, account is disabled
ldapContact.setEnabled(!bitSet.get(1));
}
break;
case LDAPContact.TYPE_GROUP:
case LDAPContact.TYPE_PUBLICFOLDER:
// 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");
}
}
}
}
/**
* History:
*
* $$Log: src/main/java/com/wincornixdorf/shared/network/ldap/LDAPSearch.java $
* Revision 1.1 2013/12/16 16:42:52MEZ Muehlencord, Joern (joern.muehlencord)
* 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) $$
*
*/
if (!ldapContact.isEnabled()) {
LOGGER.info("User {} is locked", ldapContact.getEmailaddress());
}
return ldapContact;
}
}