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; 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) $$
*
*/