diff --git a/federation/ldap/pom.xml b/federation/ldap/pom.xml
index 38fa19d3ddb..bf3feeab028 100755
--- a/federation/ldap/pom.xml
+++ b/federation/ldap/pom.xml
@@ -26,9 +26,14 @@
4.0.0keycloak-ldap-federation
- Keycloak LDAP Federation
+ Keycloak LDAP UserStoreProvider
+
+ 1.8
+ 1.8
+
+
org.keycloak
@@ -40,11 +45,6 @@
keycloak-server-spiprovided
-
- org.keycloak
- keycloak-server-spi-private
- provided
- org.keycloakkeycloak-kerberos-federation
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPConfig.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPConfig.java
deleted file mode 100644
index 7d32e6a122c..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPConfig.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap;
-
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.UserFederationProvider;
-
-import javax.naming.directory.SearchControls;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- * @author Marek Posolda
- *
- */
-public class LDAPConfig {
-
- private final Map config;
-
- public LDAPConfig(Map config) {
- this.config = config;
- }
-
- public String getConnectionUrl() {
- return config.get(LDAPConstants.CONNECTION_URL);
- }
-
- public String getFactoryName() {
- // hardcoded for now
- return "com.sun.jndi.ldap.LdapCtxFactory";
- }
-
- public String getAuthType() {
- String value = config.get(LDAPConstants.AUTH_TYPE);
- if (value == null) {
- return LDAPConstants.AUTH_TYPE_SIMPLE;
- } else {
- return value;
- }
- }
-
- public String getUseTruststoreSpi() {
- return config.get(LDAPConstants.USE_TRUSTSTORE_SPI);
- }
-
- public String getUsersDn() {
- String usersDn = config.get(LDAPConstants.USERS_DN);
-
- if (usersDn == null) {
- // Just for the backwards compatibility 1.2 -> 1.3 . Should be removed later.
- usersDn = config.get("userDnSuffix");
- }
-
- return usersDn;
- }
-
- public Collection getUserObjectClasses() {
- String objClassesCfg = config.get(LDAPConstants.USER_OBJECT_CLASSES);
- String objClassesStr = (objClassesCfg != null && objClassesCfg.length() > 0) ? objClassesCfg.trim() : "inetOrgPerson,organizationalPerson";
-
- String[] objectClasses = objClassesStr.split(",");
-
- // Trim them
- Set userObjClasses = new HashSet<>();
- for (int i=0 ; i 1.3 . Should be removed later.
- rdn = LDAPConstants.CN;
- }
-
- }
- return rdn;
- }
-
-
- public String getCustomUserSearchFilter() {
- String customFilter = config.get(LDAPConstants.CUSTOM_USER_SEARCH_FILTER);
- if (customFilter != null) {
- customFilter = customFilter.trim();
- if (customFilter.length() > 0) {
- return customFilter;
- }
- }
- return null;
- }
-
- public UserFederationProvider.EditMode getEditMode() {
- String editModeString = config.get(LDAPConstants.EDIT_MODE);
- if (editModeString == null) {
- return UserFederationProvider.EditMode.READ_ONLY;
- } else {
- return UserFederationProvider.EditMode.valueOf(editModeString);
- }
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
deleted file mode 100755
index 67cfb45fe71..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProvider.java
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.common.constants.KerberosConstants;
-import org.keycloak.credential.CredentialInput;
-import org.keycloak.credential.CredentialModel;
-import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
-import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.query.Condition;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
-import org.keycloak.federation.ldap.kerberos.LDAPProviderKerberosConfig;
-import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.LDAPMappersComparator;
-import org.keycloak.federation.ldap.mappers.PasswordUpdated;
-import org.keycloak.mappers.UserFederationMapper;
-import org.keycloak.models.CredentialValidationOutput;
-import org.keycloak.models.GroupModel;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.ModelReadOnlyException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.RoleModel;
-import org.keycloak.models.UserCredentialModel;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.UserManager;
-
-import javax.naming.AuthenticationException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Marek Posolda
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class LDAPFederationProvider implements UserFederationProvider {
- private static final Logger logger = Logger.getLogger(LDAPFederationProvider.class);
-
- protected LDAPFederationProviderFactory factory;
- protected KeycloakSession session;
- protected UserFederationProviderModel model;
- protected LDAPIdentityStore ldapIdentityStore;
- protected EditMode editMode;
- protected LDAPProviderKerberosConfig kerberosConfig;
- protected PasswordUpdated updater;
-
- protected final Set supportedCredentialTypes = new HashSet<>();
-
- public LDAPFederationProvider(LDAPFederationProviderFactory factory, KeycloakSession session, UserFederationProviderModel model, LDAPIdentityStore ldapIdentityStore) {
- this.factory = factory;
- this.session = session;
- this.model = model;
- this.ldapIdentityStore = ldapIdentityStore;
- this.kerberosConfig = new LDAPProviderKerberosConfig(model);
- this.editMode = ldapIdentityStore.getConfig().getEditMode();
-
- supportedCredentialTypes.add(UserCredentialModel.PASSWORD);
- if (kerberosConfig.isAllowKerberosAuthentication()) {
- supportedCredentialTypes.add(UserCredentialModel.KERBEROS);
- }
- }
-
- public void setUpdater(PasswordUpdated updater) {
- this.updater = updater;
- }
-
- public KeycloakSession getSession() {
- return session;
- }
-
- public UserFederationProviderModel getModel() {
- return model;
- }
-
- public LDAPIdentityStore getLdapIdentityStore() {
- return this.ldapIdentityStore;
- }
-
- public EditMode getEditMode() {
- return editMode;
- }
-
- @Override
- public UserModel validateAndProxy(RealmModel realm, UserModel local) {
- LDAPObject ldapObject = loadAndValidateUser(realm, local);
- if (ldapObject == null) {
- return null;
- }
-
- return proxy(realm, local, ldapObject);
- }
-
- protected UserModel proxy(RealmModel realm, UserModel local, LDAPObject ldapObject) {
- UserModel proxied = local;
- switch (editMode) {
- case READ_ONLY:
- proxied = new ReadonlyLDAPUserModelDelegate(local, this);
- break;
- case WRITABLE:
- proxied = new WritableLDAPUserModelDelegate(local, this, ldapObject);
- break;
- case UNSYNCED:
- proxied = new UnsyncedLDAPUserModelDelegate(local, this);
- }
-
- Set federationMappers = realm.getUserFederationMappersByFederationProvider(model.getId());
- List sortedMappers = sortMappersAsc(federationMappers);
- for (UserFederationMapperModel mapperModel : sortedMappers) {
- LDAPFederationMapper ldapMapper = getMapper(mapperModel);
- proxied = ldapMapper.proxy(mapperModel, this, ldapObject, proxied, realm);
- }
-
- return proxied;
- }
-
- @Override
- public Set getSupportedCredentialTypes() {
- return new HashSet(this.supportedCredentialTypes);
- }
-
- @Override
- public boolean synchronizeRegistrations() {
- return "true".equalsIgnoreCase(model.getConfig().get(LDAPConstants.SYNC_REGISTRATIONS)) && editMode == EditMode.WRITABLE;
- }
-
- @Override
- public UserModel register(RealmModel realm, UserModel user) {
- if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) throw new IllegalStateException("Registration is not supported by this ldap server");
- if (!synchronizeRegistrations()) throw new IllegalStateException("Registration is not supported by this ldap server");
-
- LDAPObject ldapUser = LDAPUtils.addUserToLDAP(this, realm, user);
- LDAPUtils.checkUuid(ldapUser, ldapIdentityStore.getConfig());
- user.setSingleAttribute(LDAPConstants.LDAP_ID, ldapUser.getUuid());
- user.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapUser.getDn().toString());
-
- return proxy(realm, user, ldapUser);
- }
-
- @Override
- public boolean removeUser(RealmModel realm, UserModel user) {
- if (editMode == EditMode.READ_ONLY || editMode == EditMode.UNSYNCED) {
- logger.warnf("User '%s' can't be deleted in LDAP as editMode is '%s'. Deleting user just from Keycloak DB, but he will be re-imported from LDAP again once searched in Keycloak", user.getUsername(), editMode.toString());
- return true;
- }
-
- LDAPObject ldapObject = loadAndValidateUser(realm, user);
- if (ldapObject == null) {
- logger.warnf("User '%s' can't be deleted from LDAP as it doesn't exist here", user.getUsername());
- return false;
- }
-
- ldapIdentityStore.remove(ldapObject);
- return true;
- }
-
- @Override
- public List searchByAttributes(Map attributes, RealmModel realm, int maxResults) {
- List searchResults =new LinkedList();
-
- List ldapUsers = searchLDAP(realm, attributes, maxResults);
- for (LDAPObject ldapUser : ldapUsers) {
- String ldapUsername = LDAPUtils.getUsername(ldapUser, this.ldapIdentityStore.getConfig());
- if (session.userStorage().getUserByUsername(ldapUsername, realm) == null) {
- UserModel imported = importUserFromLDAP(session, realm, ldapUser);
- searchResults.add(imported);
- }
- }
-
- return searchResults;
- }
-
- @Override
- public List getGroupMembers(RealmModel realm, GroupModel group, int firstResult, int maxResults) {
- Set federationMappers = realm.getUserFederationMappersByFederationProvider(model.getId());
- for (UserFederationMapperModel mapperModel : federationMappers) {
- LDAPFederationMapper ldapMapper = getMapper(mapperModel);
- List users = ldapMapper.getGroupMembers(mapperModel, this, realm, group, firstResult, maxResults);
-
- // Sufficient for now
- if (users.size() > 0) {
- return users;
- }
- }
-
- return Collections.emptyList();
- }
-
- public List loadUsersByUsernames(List usernames, RealmModel realm) {
- List result = new ArrayList<>();
- for (String username : usernames) {
- UserModel kcUser = session.users().getUserByUsername(username, realm);
- if (kcUser == null) {
- logger.warnf("User '%s' referenced by membership wasn't found in LDAP", username);
- } else if (!model.getId().equals(kcUser.getFederationLink())) {
- logger.warnf("Incorrect federation provider of user '%s'", kcUser.getUsername());
- } else {
- result.add(kcUser);
- }
- }
- return result;
- }
-
- protected List searchLDAP(RealmModel realm, Map attributes, int maxResults) {
-
- List results = new ArrayList();
- if (attributes.containsKey(USERNAME)) {
- LDAPObject user = loadLDAPUserByUsername(realm, attributes.get(USERNAME));
- if (user != null) {
- results.add(user);
- }
- }
-
- if (attributes.containsKey(EMAIL)) {
- LDAPObject user = queryByEmail(realm, attributes.get(EMAIL));
- if (user != null) {
- results.add(user);
- }
- }
-
- if (attributes.containsKey(FIRST_NAME) || attributes.containsKey(LAST_NAME)) {
- LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
- LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
-
- // Mapper should replace parameter with correct LDAP mapped attributes
- if (attributes.containsKey(FIRST_NAME)) {
- ldapQuery.addWhereCondition(conditionsBuilder.equal(FIRST_NAME, attributes.get(FIRST_NAME)));
- }
- if (attributes.containsKey(LAST_NAME)) {
- ldapQuery.addWhereCondition(conditionsBuilder.equal(LAST_NAME, attributes.get(LAST_NAME)));
- }
-
- List ldapObjects = ldapQuery.getResultList();
- results.addAll(ldapObjects);
- }
-
- return results;
- }
-
- /**
- * @param local
- * @return ldapUser corresponding to local user or null if user is no longer in LDAP
- */
- protected LDAPObject loadAndValidateUser(RealmModel realm, UserModel local) {
- LDAPObject ldapUser = loadLDAPUserByUsername(realm, local.getUsername());
- if (ldapUser == null) {
- return null;
- }
- LDAPUtils.checkUuid(ldapUser, ldapIdentityStore.getConfig());
-
- if (ldapUser.getUuid().equals(local.getFirstAttribute(LDAPConstants.LDAP_ID))) {
- return ldapUser;
- } else {
- logger.warnf("LDAP User invalid. ID doesn't match. ID from LDAP [%s], LDAP ID from local DB: [%s]", ldapUser.getUuid(), local.getFirstAttribute(LDAPConstants.LDAP_ID));
- return null;
- }
- }
-
- @Override
- public boolean isValid(RealmModel realm, UserModel local) {
- return loadAndValidateUser(realm, local) != null;
- }
-
- @Override
- public UserModel getUserByUsername(RealmModel realm, String username) {
- LDAPObject ldapUser = loadLDAPUserByUsername(realm, username);
- if (ldapUser == null) {
- return null;
- }
-
- return importUserFromLDAP(session, realm, ldapUser);
- }
-
- protected UserModel importUserFromLDAP(KeycloakSession session, RealmModel realm, LDAPObject ldapUser) {
- String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig());
- LDAPUtils.checkUuid(ldapUser, ldapIdentityStore.getConfig());
-
- UserModel imported = session.userStorage().addUser(realm, ldapUsername);
- imported.setEnabled(true);
-
- Set federationMappers = realm.getUserFederationMappersByFederationProvider(getModel().getId());
- List sortedMappers = sortMappersDesc(federationMappers);
- for (UserFederationMapperModel mapperModel : sortedMappers) {
- if (logger.isTraceEnabled()) {
- logger.tracef("Using mapper %s during import user from LDAP", mapperModel);
- }
- LDAPFederationMapper ldapMapper = getMapper(mapperModel);
- ldapMapper.onImportUserFromLDAP(mapperModel, this, ldapUser, imported, realm, true);
- }
-
- String userDN = ldapUser.getDn().toString();
- imported.setFederationLink(model.getId());
- imported.setSingleAttribute(LDAPConstants.LDAP_ID, ldapUser.getUuid());
- imported.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, userDN);
-
- logger.debugf("Imported new user from LDAP to Keycloak DB. Username: [%s], Email: [%s], LDAP_ID: [%s], LDAP Entry DN: [%s]", imported.getUsername(), imported.getEmail(),
- ldapUser.getUuid(), userDN);
- return proxy(realm, imported, ldapUser);
- }
-
- protected LDAPObject queryByEmail(RealmModel realm, String email) {
- LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
- LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
-
- // Mapper should replace "email" in parameter name with correct LDAP mapped attribute
- Condition emailCondition = conditionsBuilder.equal(UserModel.EMAIL, email);
- ldapQuery.addWhereCondition(emailCondition);
-
- return ldapQuery.getFirstResult();
- }
-
-
- @Override
- public UserModel getUserByEmail(RealmModel realm, String email) {
- LDAPObject ldapUser = queryByEmail(realm, email);
- if (ldapUser == null) {
- return null;
- }
-
- // Check here if user already exists
- String ldapUsername = LDAPUtils.getUsername(ldapUser, ldapIdentityStore.getConfig());
- if (session.userStorage().getUserByUsername(ldapUsername, realm) != null) {
- throw new ModelDuplicateException("User with username '" + ldapUsername + "' already exists in Keycloak. It conflicts with LDAP user with email '" + email + "'");
- }
-
- return importUserFromLDAP(session, realm, ldapUser);
- }
-
- @Override
- public void preRemove(RealmModel realm) {
- // complete Don't think we have to do anything
- }
-
- @Override
- public void preRemove(RealmModel realm, RoleModel role) {
- // TODO: Maybe mappers callback to ensure role deletion propagated to LDAP by RoleLDAPFederationMapper?
- }
-
- @Override
- public void preRemove(RealmModel realm, GroupModel group) {
-
- }
-
- public boolean validPassword(RealmModel realm, UserModel user, String password) {
- if (kerberosConfig.isAllowKerberosAuthentication() && kerberosConfig.isUseKerberosForPasswordAuthentication()) {
- // Use Kerberos JAAS (Krb5LoginModule)
- KerberosUsernamePasswordAuthenticator authenticator = factory.createKerberosUsernamePasswordAuthenticator(kerberosConfig);
- return authenticator.validUser(user.getUsername(), password);
- } else {
- // Use Naming LDAP API
- LDAPObject ldapUser = loadAndValidateUser(realm, user);
-
- try {
- ldapIdentityStore.validatePassword(ldapUser, password);
- return true;
- } catch (AuthenticationException ae) {
-
- // Check if any mapper provides callback for handle LDAP AuthenticationException
- Set federationMappers = realm.getUserFederationMappersByFederationProvider(getModel().getId());
- boolean processed = false;
- for (UserFederationMapperModel mapperModel : federationMappers) {
- LDAPFederationMapper ldapMapper = getMapper(mapperModel);
- processed = processed || ldapMapper.onAuthenticationFailure(mapperModel, this, ldapUser, user, ae, realm);
- }
-
- return processed;
- }
- }
- }
-
-
- @Override
- public boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input) {
- if (!CredentialModel.PASSWORD.equals(input.getType()) || ! (input instanceof UserCredentialModel)) return false;
- if (editMode == EditMode.READ_ONLY) {
- throw new ModelReadOnlyException("Federated storage is not writable");
-
- } else if (editMode == EditMode.WRITABLE) {
- LDAPIdentityStore ldapIdentityStore = getLdapIdentityStore();
- UserCredentialModel cred = (UserCredentialModel)input;
- String password = cred.getValue();
- LDAPObject ldapUser = loadAndValidateUser(realm, user);
- ldapIdentityStore.updatePassword(ldapUser, password);
- if (updater != null) updater.passwordUpdated(user, ldapUser, input);
- return true;
- } else {
- return false;
- }
- }
-
- @Override
- public void disableCredentialType(RealmModel realm, UserModel user, String credentialType) {
-
- }
-
- @Override
- public Set getDisableableCredentialTypes(RealmModel realm, UserModel user) {
- return Collections.EMPTY_SET;
- }
-
- @Override
- public boolean supportsCredentialType(String credentialType) {
- return getSupportedCredentialTypes().contains(credentialType);
- }
-
- @Override
- public boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType) {
- return getSupportedCredentialTypes().contains(credentialType);
- }
-
- @Override
- public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
- if (!(input instanceof UserCredentialModel)) return false;
- if (input.getType().equals(UserCredentialModel.PASSWORD) && !session.userCredentialManager().isConfiguredLocally(realm, user, UserCredentialModel.PASSWORD)) {
- return validPassword(realm, user, ((UserCredentialModel)input).getValue());
- } else {
- return false; // invalid cred type
- }
- }
-
- @Override
- public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential) {
- if (credential.getType().equals(UserCredentialModel.KERBEROS)) {
- if (kerberosConfig.isAllowKerberosAuthentication()) {
- String spnegoToken = credential.getValue();
- SPNEGOAuthenticator spnegoAuthenticator = factory.createSPNEGOAuthenticator(spnegoToken, kerberosConfig);
-
- spnegoAuthenticator.authenticate();
-
- Map state = new HashMap();
- if (spnegoAuthenticator.isAuthenticated()) {
-
- // TODO: This assumes that LDAP "uid" is equal to kerberos principal name. Like uid "hnelson" and kerberos principal "hnelson@KEYCLOAK.ORG".
- // Check if it's correct or if LDAP attribute for mapping kerberos principal should be available (For ApacheDS it seems to be attribute "krb5PrincipalName" but on MSAD it's likely different)
- String username = spnegoAuthenticator.getAuthenticatedUsername();
- UserModel user = findOrCreateAuthenticatedUser(realm, username);
-
- if (user == null) {
- logger.warnf("Kerberos/SPNEGO authentication succeeded with username [%s], but couldn't find or create user with federation provider [%s]", username, model.getDisplayName());
- return CredentialValidationOutput.failed();
- } else {
- String delegationCredential = spnegoAuthenticator.getSerializedDelegationCredential();
- if (delegationCredential != null) {
- state.put(KerberosConstants.GSS_DELEGATION_CREDENTIAL, delegationCredential);
- }
-
- return new CredentialValidationOutput(user, CredentialValidationOutput.Status.AUTHENTICATED, state);
- }
- } else {
- state.put(KerberosConstants.RESPONSE_TOKEN, spnegoAuthenticator.getResponseToken());
- return new CredentialValidationOutput(null, CredentialValidationOutput.Status.CONTINUE, state);
- }
- }
- }
-
- return CredentialValidationOutput.failed();
- }
-
- @Override
- public void close() {
- }
-
- /**
- * Called after successful kerberos authentication
- *
- * @param realm realm
- * @param username username without realm prefix
- * @return finded or newly created user
- */
- protected UserModel findOrCreateAuthenticatedUser(RealmModel realm, String username) {
- UserModel user = session.userStorage().getUserByUsername(username, realm);
- if (user != null) {
- logger.debugf("Kerberos authenticated user [%s] found in Keycloak storage", username);
- if (!model.getId().equals(user.getFederationLink())) {
- logger.warnf("User with username [%s] already exists, but is not linked to provider [%s]", username, model.getDisplayName());
- return null;
- } else {
- LDAPObject ldapObject = loadAndValidateUser(realm, user);
- if (ldapObject != null) {
- return proxy(realm, user, ldapObject);
- } else {
- logger.warnf("User with username [%s] aready exists and is linked to provider [%s] but is not valid. Stale LDAP_ID on local user is: %s",
- username, model.getDisplayName(), user.getFirstAttribute(LDAPConstants.LDAP_ID));
- logger.warn("Will re-create user");
- new UserManager(session).removeUser(realm, user, session.userStorage());
- }
- }
- }
-
- // Creating user to local storage
- logger.debugf("Kerberos authenticated user [%s] not in Keycloak storage. Creating him", username);
- return getUserByUsername(realm, username);
- }
-
- public LDAPObject loadLDAPUserByUsername(RealmModel realm, String username) {
- LDAPQuery ldapQuery = LDAPUtils.createQueryForUserSearch(this, realm);
- LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
-
- String usernameMappedAttribute = this.ldapIdentityStore.getConfig().getUsernameLdapAttribute();
- Condition usernameCondition = conditionsBuilder.equal(usernameMappedAttribute, username);
- ldapQuery.addWhereCondition(usernameCondition);
-
- LDAPObject ldapUser = ldapQuery.getFirstResult();
- if (ldapUser == null) {
- return null;
- }
-
- return ldapUser;
- }
-
- public LDAPFederationMapper getMapper(UserFederationMapperModel mapperModel) {
- LDAPFederationMapper ldapMapper = (LDAPFederationMapper) getSession().getProvider(UserFederationMapper.class, mapperModel.getFederationMapperType());
- if (ldapMapper == null) {
- throw new ModelException("Can't find mapper type with ID: " + mapperModel.getFederationMapperType());
- }
-
- return ldapMapper;
- }
-
-
- public List sortMappersAsc(Collection mappers) {
- return LDAPMappersComparator.sortAsc(getLdapIdentityStore().getConfig(), mappers);
- }
-
- protected List sortMappersDesc(Collection mappers) {
- return LDAPMappersComparator.sortDesc(getLdapIdentityStore().getConfig(), mappers);
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java
deleted file mode 100755
index 51a3c8cb705..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPFederationProviderFactory.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.Config;
-import org.keycloak.federation.kerberos.CommonKerberosConfig;
-import org.keycloak.federation.kerberos.impl.KerberosServerSubjectAuthenticator;
-import org.keycloak.federation.kerberos.impl.KerberosUsernamePasswordAuthenticator;
-import org.keycloak.federation.kerberos.impl.SPNEGOAuthenticator;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.query.Condition;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
-import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.FullNameLDAPFederationMapperFactory;
-import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.UserAttributeLDAPFederationMapperFactory;
-import org.keycloak.federation.ldap.mappers.msad.MSADUserAccountControlMapperFactory;
-import org.keycloak.mappers.FederationConfigValidationException;
-import org.keycloak.mappers.UserFederationMapper;
-import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.KeycloakSessionTask;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationEventAwareProviderFactory;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserFederationProvider;
-import org.keycloak.models.UserFederationProviderModel;
-import org.keycloak.models.UserFederationSyncResult;
-import org.keycloak.models.UserFederationValidatingProviderFactory;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.KeycloakModelUtils;
-
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Marek Posolda
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class LDAPFederationProviderFactory extends UserFederationEventAwareProviderFactory implements UserFederationValidatingProviderFactory {
- private static final Logger logger = Logger.getLogger(LDAPFederationProviderFactory.class);
- public static final String PROVIDER_NAME = LDAPConstants.LDAP_PROVIDER;
-
- private LDAPIdentityStoreRegistry ldapStoreRegistry;
-
- @Override
- public UserFederationProvider create(KeycloakSession session) {
- throw new IllegalAccessError("Illegal to call this method");
- }
-
- @Override
- public LDAPFederationProvider getInstance(KeycloakSession session, UserFederationProviderModel model) {
- LDAPIdentityStore ldapIdentityStore = this.ldapStoreRegistry.getLdapStore(model);
- return new LDAPFederationProvider(this, session, model, ldapIdentityStore);
- }
-
- @Override
- public void validateConfig(RealmModel realm, UserFederationProviderModel providerModel) throws FederationConfigValidationException {
- LDAPConfig cfg = new LDAPConfig(providerModel.getConfig());
- String customFilter = cfg.getCustomUserSearchFilter();
- LDAPUtils.validateCustomLdapFilter(customFilter);
- }
-
- @Override
- public void init(Config.Scope config) {
- this.ldapStoreRegistry = new LDAPIdentityStoreRegistry();
- }
-
- @Override
- public void close() {
- this.ldapStoreRegistry = null;
- }
-
- @Override
- public String getId() {
- return PROVIDER_NAME;
- }
-
- @Override
- public Set getConfigurationOptions() {
- return Collections.emptySet();
- }
-
-
- // Best effort to create appropriate mappers according to our LDAP config
- @Override
- public void onProviderModelCreated(RealmModel realm, UserFederationProviderModel newProviderModel) {
- LDAPConfig ldapConfig = new LDAPConfig(newProviderModel.getConfig());
-
- boolean activeDirectory = ldapConfig.isActiveDirectory();
- UserFederationProvider.EditMode editMode = ldapConfig.getEditMode();
- String readOnly = String.valueOf(editMode == UserFederationProvider.EditMode.READ_ONLY || editMode == UserFederationProvider.EditMode.UNSYNCED);
- String usernameLdapAttribute = ldapConfig.getUsernameLdapAttribute();
-
- String alwaysReadValueFromLDAP = String.valueOf(editMode==UserFederationProvider.EditMode.READ_ONLY || editMode== UserFederationProvider.EditMode.WRITABLE);
-
- UserFederationMapperModel mapperModel;
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("username", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.USERNAME,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, usernameLdapAttribute,
- UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
- realm.addUserFederationMapper(mapperModel);
-
- // CN is typically used as RDN for Active Directory deployments
- if (ldapConfig.getRdnLdapAttribute().equalsIgnoreCase(LDAPConstants.CN)) {
-
- if (usernameLdapAttribute.equalsIgnoreCase(LDAPConstants.CN)) {
-
- // For AD deployments with "cn" as username, we will map "givenName" to first name
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.GIVENNAME,
- UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
- realm.addUserFederationMapper(mapperModel);
-
- } else {
- if (editMode == UserFederationProvider.EditMode.WRITABLE) {
-
- // For AD deployments with "sAMAccountName" as username and writable, we need to map "cn" as username as well (this is needed so we can register new users from KC into LDAP) and we will map "givenName" to first name.
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.GIVENNAME,
- UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
- realm.addUserFederationMapper(mapperModel);
-
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("username-cn", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.USERNAME,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.CN,
- UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
- realm.addUserFederationMapper(mapperModel);
- } else {
-
- // For read-only LDAP, we map "cn" as full name
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("full name", newProviderModel.getId(), FullNameLDAPFederationMapperFactory.PROVIDER_ID,
- FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE, LDAPConstants.CN,
- FullNameLDAPFederationMapper.READ_ONLY, readOnly,
- FullNameLDAPFederationMapper.WRITE_ONLY, "false");
- realm.addUserFederationMapper(mapperModel);
- }
- }
- } else {
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("first name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.FIRST_NAME,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.CN,
- UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
- realm.addUserFederationMapper(mapperModel);
- }
-
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("last name", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.LAST_NAME,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.SN,
- UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "true");
- realm.addUserFederationMapper(mapperModel);
-
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("email", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, UserModel.EMAIL,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, LDAPConstants.EMAIL,
- UserAttributeLDAPFederationMapper.READ_ONLY, readOnly,
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, "false",
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
- realm.addUserFederationMapper(mapperModel);
-
- String createTimestampLdapAttrName = activeDirectory ? "whenCreated" : LDAPConstants.CREATE_TIMESTAMP;
- String modifyTimestampLdapAttrName = activeDirectory ? "whenChanged" : LDAPConstants.MODIFY_TIMESTAMP;
-
- // map createTimeStamp as read-only
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("creation date", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, LDAPConstants.CREATE_TIMESTAMP,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, createTimestampLdapAttrName,
- UserAttributeLDAPFederationMapper.READ_ONLY, "true",
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
- realm.addUserFederationMapper(mapperModel);
-
- // map modifyTimeStamp as read-only
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("modify date", newProviderModel.getId(), UserAttributeLDAPFederationMapperFactory.PROVIDER_ID,
- UserAttributeLDAPFederationMapper.USER_MODEL_ATTRIBUTE, LDAPConstants.MODIFY_TIMESTAMP,
- UserAttributeLDAPFederationMapper.LDAP_ATTRIBUTE, modifyTimestampLdapAttrName,
- UserAttributeLDAPFederationMapper.READ_ONLY, "true",
- UserAttributeLDAPFederationMapper.ALWAYS_READ_VALUE_FROM_LDAP, alwaysReadValueFromLDAP,
- UserAttributeLDAPFederationMapper.IS_MANDATORY_IN_LDAP, "false");
- realm.addUserFederationMapper(mapperModel);
-
- // MSAD specific mapper for account state propagation
- if (activeDirectory) {
- mapperModel = KeycloakModelUtils.createUserFederationMapperModel("MSAD account controls", newProviderModel.getId(), MSADUserAccountControlMapperFactory.PROVIDER_ID);
- realm.addUserFederationMapper(mapperModel);
- }
- }
-
-
- @Override
- public UserFederationSyncResult syncAllUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
- syncMappers(sessionFactory, realmId, model);
-
- logger.infof("Sync all users from LDAP to local store: realm: %s, federation provider: %s", realmId, model.getDisplayName());
-
- LDAPQuery userQuery = createQuery(sessionFactory, realmId, model);
- UserFederationSyncResult syncResult = syncImpl(sessionFactory, userQuery, realmId, model);
-
- // TODO: Remove all existing keycloak users, which have federation links, but are not in LDAP. Perhaps don't check users, which were just added or updated during this sync?
-
- logger.infof("Sync all users finished: %s", syncResult.getStatus());
- return syncResult;
- }
-
- @Override
- public UserFederationSyncResult syncChangedUsers(KeycloakSessionFactory sessionFactory, String realmId, UserFederationProviderModel model, Date lastSync) {
- syncMappers(sessionFactory, realmId, model);
-
- logger.infof("Sync changed users from LDAP to local store: realm: %s, federation provider: %s, last sync time: " + lastSync, realmId, model.getDisplayName());
-
- // Sync newly created and updated users
- LDAPQueryConditionsBuilder conditionsBuilder = new LDAPQueryConditionsBuilder();
- Condition createCondition = conditionsBuilder.greaterThanOrEqualTo(LDAPConstants.CREATE_TIMESTAMP, lastSync);
- Condition modifyCondition = conditionsBuilder.greaterThanOrEqualTo(LDAPConstants.MODIFY_TIMESTAMP, lastSync);
- Condition orCondition = conditionsBuilder.orCondition(createCondition, modifyCondition);
-
- LDAPQuery userQuery = createQuery(sessionFactory, realmId, model);
- userQuery.addWhereCondition(orCondition);
- UserFederationSyncResult result = syncImpl(sessionFactory, userQuery, realmId, model);
-
- logger.infof("Sync changed users finished: %s", result.getStatus());
- return result;
- }
-
- protected void syncMappers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
- KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
-
- @Override
- public void run(KeycloakSession session) {
- LDAPFederationProvider ldapProvider = getInstance(session, model);
- RealmModel realm = session.realms().getRealm(realmId);
- Set mappers = realm.getUserFederationMappersByFederationProvider(model.getId());
- for (UserFederationMapperModel mapperModel : mappers) {
- UserFederationMapper ldapMapper = session.getProvider(UserFederationMapper.class, mapperModel.getFederationMapperType());
- UserFederationSyncResult syncResult = ldapMapper.syncDataFromFederationProviderToKeycloak(mapperModel, ldapProvider, session, realm);
- if (syncResult.getAdded() > 0 || syncResult.getUpdated() > 0 || syncResult.getRemoved() > 0 || syncResult.getFailed() > 0) {
- logger.infof("Sync of federation mapper '%s' finished. Status: %s", mapperModel.getName(), syncResult.toString());
- }
- }
- }
-
- });
- }
-
- protected UserFederationSyncResult syncImpl(KeycloakSessionFactory sessionFactory, LDAPQuery userQuery, final String realmId, final UserFederationProviderModel fedModel) {
-
- final UserFederationSyncResult syncResult = new UserFederationSyncResult();
-
- LDAPConfig ldapConfig = new LDAPConfig(fedModel.getConfig());
- boolean pagination = ldapConfig.isPagination();
- if (pagination) {
- int pageSize = ldapConfig.getBatchSizeForSync();
-
- boolean nextPage = true;
- while (nextPage) {
- userQuery.setLimit(pageSize);
- final List users = userQuery.getResultList();
- nextPage = userQuery.getPaginationContext() != null;
- UserFederationSyncResult currentPageSync = importLdapUsers(sessionFactory, realmId, fedModel, users);
- syncResult.add(currentPageSync);
- }
- } else {
- // LDAP pagination not available. Do everything in single transaction
- final List users = userQuery.getResultList();
- UserFederationSyncResult currentSync = importLdapUsers(sessionFactory, realmId, fedModel, users);
- syncResult.add(currentSync);
- }
-
- return syncResult;
- }
-
- private LDAPQuery createQuery(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel model) {
- class QueryHolder {
- LDAPQuery query;
- }
-
- final QueryHolder queryHolder = new QueryHolder();
- KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
-
- @Override
- public void run(KeycloakSession session) {
- LDAPFederationProvider ldapFedProvider = getInstance(session, model);
- RealmModel realm = session.realms().getRealm(realmId);
- queryHolder.query = LDAPUtils.createQueryForUserSearch(ldapFedProvider, realm);
- }
-
- });
- return queryHolder.query;
- }
-
- protected UserFederationSyncResult importLdapUsers(KeycloakSessionFactory sessionFactory, final String realmId, final UserFederationProviderModel fedModel, List ldapUsers) {
- final UserFederationSyncResult syncResult = new UserFederationSyncResult();
-
- class BooleanHolder {
- private boolean value = true;
- }
- final BooleanHolder exists = new BooleanHolder();
-
- for (final LDAPObject ldapUser : ldapUsers) {
-
- try {
-
- // Process each user in it's own transaction to avoid global fail
- KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
-
- @Override
- public void run(KeycloakSession session) {
- LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
- RealmModel currentRealm = session.realms().getRealm(realmId);
-
- String username = LDAPUtils.getUsername(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
- exists.value = true;
- LDAPUtils.checkUuid(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
- UserModel currentUser = session.userStorage().getUserByUsername(username, currentRealm);
-
- if (currentUser == null) {
-
- // Add new user to Keycloak
- exists.value = false;
- ldapFedProvider.importUserFromLDAP(session, currentRealm, ldapUser);
- syncResult.increaseAdded();
-
- } else {
- if ((fedModel.getId().equals(currentUser.getFederationLink())) && (ldapUser.getUuid().equals(currentUser.getFirstAttribute(LDAPConstants.LDAP_ID)))) {
-
- // Update keycloak user
- Set federationMappers = currentRealm.getUserFederationMappersByFederationProvider(fedModel.getId());
- List sortedMappers = ldapFedProvider.sortMappersDesc(federationMappers);
- for (UserFederationMapperModel mapperModel : sortedMappers) {
- LDAPFederationMapper ldapMapper = ldapFedProvider.getMapper(mapperModel);
- ldapMapper.onImportUserFromLDAP(mapperModel, ldapFedProvider, ldapUser, currentUser, currentRealm, false);
- }
-
- logger.debugf("Updated user from LDAP: %s", currentUser.getUsername());
- syncResult.increaseUpdated();
- } else {
- logger.warnf("User '%s' is not updated during sync as he already exists in Keycloak database but is not linked to federation provider '%s'", username, fedModel.getDisplayName());
- syncResult.increaseFailed();
- }
- }
- }
-
- });
- } catch (ModelException me) {
- logger.error("Failed during import user from LDAP", me);
- syncResult.increaseFailed();
-
- // Remove user if we already added him during this transaction
- if (!exists.value) {
- KeycloakModelUtils.runJobInTransaction(sessionFactory, new KeycloakSessionTask() {
-
- @Override
- public void run(KeycloakSession session) {
- LDAPFederationProvider ldapFedProvider = getInstance(session, fedModel);
- RealmModel currentRealm = session.realms().getRealm(realmId);
- String username = null;
- try {
- username = LDAPUtils.getUsername(ldapUser, ldapFedProvider.getLdapIdentityStore().getConfig());
- } catch (ModelException ignore) {
- }
-
- if (username != null) {
- UserModel existing = session.userStorage().getUserByUsername(username, currentRealm);
- if (existing != null) {
- session.userStorage().removeUser(currentRealm, existing);
- }
- }
- }
-
- });
- }
- }
- }
-
- return syncResult;
- }
-
- protected SPNEGOAuthenticator createSPNEGOAuthenticator(String spnegoToken, CommonKerberosConfig kerberosConfig) {
- KerberosServerSubjectAuthenticator kerberosAuth = createKerberosSubjectAuthenticator(kerberosConfig);
- return new SPNEGOAuthenticator(kerberosConfig, kerberosAuth, spnegoToken);
- }
-
- protected KerberosServerSubjectAuthenticator createKerberosSubjectAuthenticator(CommonKerberosConfig kerberosConfig) {
- return new KerberosServerSubjectAuthenticator(kerberosConfig);
- }
-
- protected KerberosUsernamePasswordAuthenticator createKerberosUsernamePasswordAuthenticator(CommonKerberosConfig kerberosConfig) {
- return new KerberosUsernamePasswordAuthenticator(kerberosConfig);
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java
deleted file mode 100644
index 7470d4375fd..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPIdentityStoreRegistry.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.UserFederationProviderModel;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author Marek Posolda
- */
-public class LDAPIdentityStoreRegistry {
-
- private static final Logger logger = Logger.getLogger(LDAPIdentityStoreRegistry.class);
-
- private Map ldapStores = new ConcurrentHashMap();
-
- public LDAPIdentityStore getLdapStore(UserFederationProviderModel model) {
- LDAPIdentityStoreContext context = ldapStores.get(model.getId());
-
- // Ldap config might have changed for the realm. In this case, we must re-initialize
- Map config = model.getConfig();
- if (context == null || !config.equals(context.config)) {
- logLDAPConfig(model.getDisplayName(), config);
-
- LDAPIdentityStore store = createLdapIdentityStore(config);
- context = new LDAPIdentityStoreContext(config, store);
- ldapStores.put(model.getId(), context);
- }
- return context.store;
- }
-
- // Don't log LDAP password
- private void logLDAPConfig(String fedProviderDisplayName, Map ldapConfig) {
- Map copy = new HashMap(ldapConfig);
- copy.remove(LDAPConstants.BIND_CREDENTIAL);
- logger.infof("Creating new LDAP based partition manager for the Federation provider: " + fedProviderDisplayName + ", LDAP Configuration: " + copy);
- }
-
- /**
- * @param ldapConfig from realm
- * @return PartitionManager instance based on LDAP store
- */
- public static LDAPIdentityStore createLdapIdentityStore(Map ldapConfig) {
- LDAPConfig cfg = new LDAPConfig(ldapConfig);
-
- checkSystemProperty("com.sun.jndi.ldap.connect.pool.authentication", "none simple");
- checkSystemProperty("com.sun.jndi.ldap.connect.pool.initsize", "1");
- checkSystemProperty("com.sun.jndi.ldap.connect.pool.maxsize", "1000");
- checkSystemProperty("com.sun.jndi.ldap.connect.pool.prefsize", "5");
- checkSystemProperty("com.sun.jndi.ldap.connect.pool.timeout", "300000");
- checkSystemProperty("com.sun.jndi.ldap.connect.pool.protocol", "plain");
- checkSystemProperty("com.sun.jndi.ldap.connect.pool.debug", "off");
-
- return new LDAPIdentityStore(cfg);
- }
-
- private static void checkSystemProperty(String name, String defaultValue) {
- if (System.getProperty(name) == null) {
- System.setProperty(name, defaultValue);
- }
- }
-
-
- private class LDAPIdentityStoreContext {
-
- private LDAPIdentityStoreContext(Map config, LDAPIdentityStore store) {
- this.config = config;
- this.store = store;
- }
-
- private Map config;
- private LDAPIdentityStore store;
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java
deleted file mode 100755
index 0c203665732..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/LDAPUtils.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap;
-
-import org.keycloak.federation.ldap.idm.model.LDAPDn;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.query.Condition;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQueryConditionsBuilder;
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPIdentityStore;
-import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
-import org.keycloak.federation.ldap.mappers.membership.MembershipType;
-import org.keycloak.mappers.FederationConfigValidationException;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.RealmModel;
-import org.keycloak.models.UserFederationMapperModel;
-import org.keycloak.models.UserModel;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Allow to directly call some operations against LDAPIdentityStore.
- *
- * @author Marek Posolda
- */
-public class LDAPUtils {
-
- /**
- * @param ldapProvider
- * @param realm
- * @param user
- * @return newly created LDAPObject with all the attributes, uuid and DN properly set
- */
- public static LDAPObject addUserToLDAP(LDAPFederationProvider ldapProvider, RealmModel realm, UserModel user) {
- LDAPObject ldapUser = new LDAPObject();
-
- LDAPIdentityStore ldapStore = ldapProvider.getLdapIdentityStore();
- LDAPConfig ldapConfig = ldapStore.getConfig();
- ldapUser.setRdnAttributeName(ldapConfig.getRdnLdapAttribute());
- ldapUser.setObjectClasses(ldapConfig.getUserObjectClasses());
-
- Set federationMappers = realm.getUserFederationMappersByFederationProvider(ldapProvider.getModel().getId());
- List sortedMappers = ldapProvider.sortMappersAsc(federationMappers);
- for (UserFederationMapperModel mapperModel : sortedMappers) {
- LDAPFederationMapper ldapMapper = ldapProvider.getMapper(mapperModel);
- ldapMapper.onRegisterUserToLDAP(mapperModel, ldapProvider, ldapUser, user, realm);
- }
-
- LDAPUtils.computeAndSetDn(ldapConfig, ldapUser);
- ldapStore.add(ldapUser);
- return ldapUser;
- }
-
- public static LDAPQuery createQueryForUserSearch(LDAPFederationProvider ldapProvider, RealmModel realm) {
- LDAPQuery ldapQuery = new LDAPQuery(ldapProvider);
- LDAPConfig config = ldapProvider.getLdapIdentityStore().getConfig();
- ldapQuery.setSearchScope(config.getSearchScope());
- ldapQuery.setSearchDn(config.getUsersDn());
- ldapQuery.addObjectClasses(config.getUserObjectClasses());
-
- String customFilter = config.getCustomUserSearchFilter();
- if (customFilter != null) {
- Condition customFilterCondition = new LDAPQueryConditionsBuilder().addCustomLDAPFilter(customFilter);
- ldapQuery.addWhereCondition(customFilterCondition);
- }
-
- Set mapperModels = realm.getUserFederationMappersByFederationProvider(ldapProvider.getModel().getId());
- ldapQuery.addMappers(mapperModels);
-
- return ldapQuery;
- }
-
- // ldapUser has filled attributes, but doesn't have filled dn.
- private static void computeAndSetDn(LDAPConfig config, LDAPObject ldapUser) {
- String rdnLdapAttrName = config.getRdnLdapAttribute();
- String rdnLdapAttrValue = ldapUser.getAttributeAsString(rdnLdapAttrName);
- if (rdnLdapAttrValue == null) {
- throw new ModelException("RDN Attribute [" + rdnLdapAttrName + "] is not filled. Filled attributes: " + ldapUser.getAttributes());
- }
-
- LDAPDn dn = LDAPDn.fromString(config.getUsersDn());
- dn.addFirst(rdnLdapAttrName, rdnLdapAttrValue);
- ldapUser.setDn(dn);
- }
-
- public static String getUsername(LDAPObject ldapUser, LDAPConfig config) {
- String usernameAttr = config.getUsernameLdapAttribute();
- String ldapUsername = ldapUser.getAttributeAsString(usernameAttr);
-
- if (ldapUsername == null) {
- throw new ModelException("User returned from LDAP has null username! Check configuration of your LDAP mappings. Mapped username LDAP attribute: " +
- config.getUsernameLdapAttribute() + ", user DN: " + ldapUser.getDn() + ", attributes from LDAP: " + ldapUser.getAttributes());
- }
-
- return ldapUsername;
- }
-
- public static void checkUuid(LDAPObject ldapUser, LDAPConfig config) {
- if (ldapUser.getUuid() == null) {
- throw new ModelException("User returned from LDAP has null uuid! Check configuration of your LDAP settings. UUID Attribute must be unique among your LDAP records and available on all the LDAP user records. " +
- "If your LDAP server really doesn't support the notion of UUID, you can use any other attribute, which is supposed to be unique among LDAP users in tree. For example 'uid' or 'entryDN' . " +
- "Mapped UUID LDAP attribute: " + config.getUuidLDAPAttributeName() + ", user DN: " + ldapUser.getDn());
- }
- }
-
-
- // roles & groups
-
- public static LDAPObject createLDAPGroup(LDAPFederationProvider ldapProvider, String groupName, String groupNameAttribute, Collection objectClasses,
- String parentDn, Map> additionalAttributes) {
- LDAPObject ldapObject = new LDAPObject();
-
- ldapObject.setRdnAttributeName(groupNameAttribute);
- ldapObject.setObjectClasses(objectClasses);
- ldapObject.setSingleAttribute(groupNameAttribute, groupName);
-
- LDAPDn roleDn = LDAPDn.fromString(parentDn);
- roleDn.addFirst(groupNameAttribute, groupName);
- ldapObject.setDn(roleDn);
-
- for (Map.Entry> attrEntry : additionalAttributes.entrySet()) {
- ldapObject.setAttribute(attrEntry.getKey(), attrEntry.getValue());
- }
-
- ldapProvider.getLdapIdentityStore().add(ldapObject);
- return ldapObject;
- }
-
- /**
- * Add ldapChild as member of ldapParent and save ldapParent to LDAP.
- *
- * @param ldapProvider
- * @param membershipType how is 'member' attribute saved (full DN or just uid)
- * @param memberAttrName usually 'member'
- * @param ldapParent role or group
- * @param ldapChild usually user (or child group or child role)
- * @param sendLDAPUpdateRequest if true, the method will send LDAP update request too. Otherwise it will skip it
- */
- public static void addMember(LDAPFederationProvider ldapProvider, MembershipType membershipType, String memberAttrName, LDAPObject ldapParent, LDAPObject ldapChild, boolean sendLDAPUpdateRequest) {
-
- Set memberships = getExistingMemberships(memberAttrName, ldapParent);
-
- // Remove membership placeholder if present
- if (membershipType == MembershipType.DN) {
- for (String membership : memberships) {
- if (LDAPConstants.EMPTY_MEMBER_ATTRIBUTE_VALUE.equals(membership)) {
- memberships.remove(membership);
- break;
- }
- }
- }
-
- String membership = getMemberValueOfChildObject(ldapChild, membershipType);
-
- memberships.add(membership);
- ldapParent.setAttribute(memberAttrName, memberships);
-
- if (sendLDAPUpdateRequest) {
- ldapProvider.getLdapIdentityStore().update(ldapParent);
- }
- }
-
- /**
- * Remove ldapChild as member of ldapParent and save ldapParent to LDAP.
- *
- * @param ldapProvider
- * @param membershipType how is 'member' attribute saved (full DN or just uid)
- * @param memberAttrName usually 'member'
- * @param ldapParent role or group
- * @param ldapChild usually user (or child group or child role)
- * @param sendLDAPUpdateRequest if true, the method will send LDAP update request too. Otherwise it will skip it
- */
- public static void deleteMember(LDAPFederationProvider ldapProvider, MembershipType membershipType, String memberAttrName, LDAPObject ldapParent, LDAPObject ldapChild, boolean sendLDAPUpdateRequest) {
- Set memberships = getExistingMemberships(memberAttrName, ldapParent);
-
- String userMembership = getMemberValueOfChildObject(ldapChild, membershipType);
-
- memberships.remove(userMembership);
-
- // Some membership placeholder needs to be always here as "member" is mandatory attribute on some LDAP servers. But not on active directory! (Placeholder, which not matches any real object is not allowed here)
- if (memberships.size() == 0 && membershipType== MembershipType.DN && !ldapProvider.getLdapIdentityStore().getConfig().isActiveDirectory()) {
- memberships.add(LDAPConstants.EMPTY_MEMBER_ATTRIBUTE_VALUE);
- }
-
- ldapParent.setAttribute(memberAttrName, memberships);
- ldapProvider.getLdapIdentityStore().update(ldapParent);
- }
-
- /**
- * Return all existing memberships (values of attribute 'member' ) from the given ldapRole or ldapGroup
- *
- * @param memberAttrName usually 'member'
- * @param ldapRole
- * @return
- */
- public static Set getExistingMemberships(String memberAttrName, LDAPObject ldapRole) {
- Set memberships = ldapRole.getAttributeAsSet(memberAttrName);
- if (memberships == null) {
- memberships = new HashSet<>();
- }
- return memberships;
- }
-
- /**
- * Get value to be used as attribute 'member' in some parent ldapObject
- */
- public static String getMemberValueOfChildObject(LDAPObject ldapUser, MembershipType membershipType) {
- return membershipType == MembershipType.DN ? ldapUser.getDn().toString() : ldapUser.getAttributeAsString(ldapUser.getRdnAttributeName());
- }
-
-
- /**
- * Load all LDAP objects corresponding to given query. We will load them paginated, so we allow to bypass the limitation of 1000
- * maximum loaded objects in single query in MSAD
- *
- * @param ldapQuery
- * @param ldapProvider
- * @return
- */
- public static List loadAllLDAPObjects(LDAPQuery ldapQuery, LDAPFederationProvider ldapProvider) {
- LDAPConfig ldapConfig = ldapProvider.getLdapIdentityStore().getConfig();
- boolean pagination = ldapConfig.isPagination();
- if (pagination) {
- // For now reuse globally configured batch size in LDAP provider page
- int pageSize = ldapConfig.getBatchSizeForSync();
-
- List result = new LinkedList<>();
- boolean nextPage = true;
-
- while (nextPage) {
- ldapQuery.setLimit(pageSize);
- final List currentPageGroups = ldapQuery.getResultList();
- result.addAll(currentPageGroups);
- nextPage = ldapQuery.getPaginationContext() != null;
- }
-
- return result;
- } else {
- // LDAP pagination not available. Do everything in single transaction
- return ldapQuery.getResultList();
- }
- }
-
-
- /**
- * Validate configured customFilter matches the requested format
- *
- * @param customFilter
- * @throws FederationConfigValidationException
- */
- public static void validateCustomLdapFilter(String customFilter) throws FederationConfigValidationException {
- if (customFilter != null) {
-
- customFilter = customFilter.trim();
- if (customFilter.isEmpty()) {
- return;
- }
-
- if (!customFilter.startsWith("(") || !customFilter.endsWith(")")) {
- throw new FederationConfigValidationException("ldapErrorInvalidCustomFilter");
- }
- }
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/ReadonlyLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/ReadonlyLDAPUserModelDelegate.java
deleted file mode 100755
index 6a839b6698d..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/ReadonlyLDAPUserModelDelegate.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap;
-
-import org.keycloak.models.ModelReadOnlyException;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.UserModelDelegate;
-
-/**
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class ReadonlyLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
-
- protected LDAPFederationProvider provider;
-
- public ReadonlyLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider) {
- super(delegate);
- this.provider = provider;
- }
-
- @Override
- public void setUsername(String username) {
- throw new ModelReadOnlyException("Federated storage is not writable");
- }
-
- @Override
- public void setLastName(String lastName) {
- throw new ModelReadOnlyException("Federated storage is not writable");
- }
-
- @Override
- public void setFirstName(String first) {
- throw new ModelReadOnlyException("Federated storage is not writable");
- }
-
- @Override
- public void setEmail(String email) {
- throw new ModelReadOnlyException("Federated storage is not writable");
- }
-
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/UnsyncedLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/UnsyncedLDAPUserModelDelegate.java
deleted file mode 100755
index 4d116e41349..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/UnsyncedLDAPUserModelDelegate.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.UserModelDelegate;
-
-/**
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class UnsyncedLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
- private static final Logger logger = Logger.getLogger(UnsyncedLDAPUserModelDelegate.class);
-
- protected LDAPFederationProvider provider;
-
- public UnsyncedLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider) {
- super(delegate);
- this.provider = provider;
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java
deleted file mode 100755
index 7bc78014cfa..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/WritableLDAPUserModelDelegate.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.models.UserModel;
-import org.keycloak.models.utils.UserModelDelegate;
-
-/**
- * @author Bill Burke
- * @version $Revision: 1 $
- */
-public class WritableLDAPUserModelDelegate extends UserModelDelegate implements UserModel {
- private static final Logger logger = Logger.getLogger(WritableLDAPUserModelDelegate.class);
-
- protected LDAPFederationProvider provider;
- protected LDAPObject ldapObject;
-
- public WritableLDAPUserModelDelegate(UserModel delegate, LDAPFederationProvider provider, LDAPObject ldapObject) {
- super(delegate);
- this.provider = provider;
- this.ldapObject = ldapObject;
- }
-
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPDn.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPDn.java
deleted file mode 100644
index bfbce5964a1..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPDn.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.model;
-
-import javax.naming.ldap.Rdn;
-import java.util.Collection;
-import java.util.Deque;
-import java.util.LinkedList;
-
-/**
- * @author Marek Posolda
- */
-public class LDAPDn {
-
- private final Deque entries = new LinkedList<>();
-
- public static LDAPDn fromString(String dnString) {
- LDAPDn dn = new LDAPDn();
-
- // In certain OpenLDAP implementations the uniqueMember attribute is mandatory
- // Thus, if a new group is created, it will contain an empty uniqueMember attribute
- // Later on, when adding members, this empty attribute will be kept
- // Keycloak must be able to process it, properly, w/o throwing an ArrayIndexOutOfBoundsException
- if(dnString.trim().isEmpty())
- return dn;
-
- String[] rdns = dnString.split("(? entries) {
- StringBuilder builder = new StringBuilder();
-
- boolean first = true;
- for (Entry rdn : entries) {
- if (first) {
- first = false;
- } else {
- builder.append(",");
- }
- builder.append(rdn.attrName).append("=").append(rdn.attrValue);
- }
-
- return builder.toString();
- }
-
- /**
- * @return string like "uid=joe" from the DN like "uid=joe,dc=something,dc=org"
- */
- public String getFirstRdn() {
- Entry firstEntry = entries.getFirst();
- return firstEntry.attrName + "=" + firstEntry.attrValue;
- }
-
- /**
- * @return string attribute name like "uid" from the DN like "uid=joe,dc=something,dc=org"
- */
- public String getFirstRdnAttrName() {
- Entry firstEntry = entries.getFirst();
- return firstEntry.attrName;
- }
-
- /**
- * @return string attribute value like "joe" from the DN like "uid=joe,dc=something,dc=org"
- */
- public String getFirstRdnAttrValue() {
- Entry firstEntry = entries.getFirst();
- return firstEntry.attrValue;
- }
-
- /**
- *
- * @return string like "dc=something,dc=org" from the DN like "uid=joe,dc=something,dc=org"
- */
- public String getParentDn() {
- LinkedList parentDnEntries = new LinkedList<>(entries);
- parentDnEntries.remove();
- return toString(parentDnEntries);
- }
-
- public boolean isDescendantOf(LDAPDn expectedParentDn) {
- int parentEntriesCount = expectedParentDn.entries.size();
-
- Deque myEntries = new LinkedList<>(this.entries);
- boolean someRemoved = false;
- while (myEntries.size() > parentEntriesCount) {
- myEntries.removeFirst();
- someRemoved = true;
- }
-
- String myEntriesParentStr = toString(myEntries).toLowerCase();
- String expectedParentDnStr = expectedParentDn.toString().toLowerCase();
- return someRemoved && myEntriesParentStr.equals(expectedParentDnStr);
- }
-
- public void addFirst(String rdnName, String rdnValue) {
- rdnValue = Rdn.escapeValue(rdnValue);
- entries.addFirst(new Entry(rdnName, rdnValue));
- }
-
- private void addLast(String rdnName, String rdnValue) {
- entries.addLast(new Entry(rdnName, rdnValue));
- }
-
- private static class Entry {
- private final String attrName;
- private final String attrValue;
-
- private Entry(String attrName, String attrValue) {
- this.attrName = attrName;
- this.attrValue = attrValue;
- }
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPObject.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPObject.java
deleted file mode 100644
index 0141a451f75..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/model/LDAPObject.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.model;
-
-import org.jboss.logging.Logger;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Marek Posolda
- */
-public class LDAPObject {
-
- private static final Logger logger = Logger.getLogger(LDAPObject.class);
-
- private String uuid;
- private LDAPDn dn;
- private String rdnAttributeName;
-
- private final List objectClasses = new LinkedList<>();
-
- // NOTE: names of read-only attributes are lower-cased to avoid case sensitivity issues
- private final List readOnlyAttributeNames = new LinkedList<>();
-
- private final Map> attributes = new HashMap<>();
-
- // Copy of "attributes" containing lower-cased keys
- private final Map> lowerCasedAttributes = new HashMap<>();
-
-
- public String getUuid() {
- return uuid;
- }
-
- public void setUuid(String uuid) {
- this.uuid = uuid;
- }
-
- public LDAPDn getDn() {
- return dn;
- }
-
- public void setDn(LDAPDn dn) {
- this.dn = dn;
- }
-
- public List getObjectClasses() {
- return objectClasses;
- }
-
- public void setObjectClasses(Collection objectClasses) {
- this.objectClasses.clear();
- this.objectClasses.addAll(objectClasses);
- }
-
- public List getReadOnlyAttributeNames() {
- return readOnlyAttributeNames;
- }
-
- public void addReadOnlyAttributeName(String readOnlyAttribute) {
- readOnlyAttributeNames.add(readOnlyAttribute.toLowerCase());
- }
-
- public void removeReadOnlyAttributeName(String readOnlyAttribute) {
- readOnlyAttributeNames.remove(readOnlyAttribute.toLowerCase());
- }
-
- public String getRdnAttributeName() {
- return rdnAttributeName;
- }
-
- public void setRdnAttributeName(String rdnAttributeName) {
- this.rdnAttributeName = rdnAttributeName;
- }
-
- public void setSingleAttribute(String attributeName, String attributeValue) {
- Set asSet = new LinkedHashSet<>();
- asSet.add(attributeValue);
- setAttribute(attributeName, asSet);
- }
-
- public void setAttribute(String attributeName, Set attributeValue) {
- attributes.put(attributeName, attributeValue);
- lowerCasedAttributes.put(attributeName.toLowerCase(), attributeValue);
- }
-
- // Case-insensitive
- public String getAttributeAsString(String name) {
- Set attrValue = lowerCasedAttributes.get(name.toLowerCase());
- if (attrValue == null || attrValue.size() == 0) {
- return null;
- } else if (attrValue.size() > 1) {
- logger.warnf("Expected String but attribute '%s' has more values '%s' on object '%s' . Returning just first value", name, attrValue, dn);
- }
-
- return attrValue.iterator().next();
- }
-
- // Case-insensitive. Return null if there is not value of attribute with given name or set with all values otherwise
- public Set getAttributeAsSet(String name) {
- Set values = lowerCasedAttributes.get(name.toLowerCase());
- return (values == null) ? null : new LinkedHashSet<>(values);
- }
-
-
- public Map> getAttributes() {
- return attributes;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
-
- if (!getClass().isInstance(obj)) {
- return false;
- }
-
- LDAPObject other = (LDAPObject) obj;
-
- return getUuid() != null && other.getUuid() != null && getUuid().equals(other.getUuid());
- }
-
- @Override
- public int hashCode() {
- int result = getUuid() != null ? getUuid().hashCode() : 0;
- result = 31 * result + (getUuid() != null ? getUuid().hashCode() : 0);
- return result;
- }
-
- @Override
- public String toString() {
- return "LDAP Object [ dn: " + dn + " , uuid: " + uuid + ", attributes: " + attributes + ", readOnly attribute names: " + readOnlyAttributeNames + " ]";
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java
deleted file mode 100644
index a8d3f071823..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Condition.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query;
-
-/**
- *
A {@link Condition} is used to specify how a specific query parameter
- * is defined in order to filter query results.
- *
- * @author Pedro Igor
- */
-public interface Condition {
-
- String getParameterName();
- void setParameterName(String parameterName);
-
- /**
- * Will change the parameter name if it is "modelParamName" to "ldapParamName" . Implementation can apply this to subconditions as well.
- *
- * It is used to update LDAP queries, which were created with model parameter name ( for example "firstName" ) and rewrite them to use real
- * LDAP mapped attribute (for example "givenName" )
- */
- void updateParameterName(String modelParamName, String ldapParamName);
-
-
- void applyCondition(StringBuilder filter);
-
-}
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java
deleted file mode 100644
index da982726c30..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/Sort.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query;
-
-/**
- * @author Pedro Igor
- */
-public class Sort {
-
- private final String paramName;
- private final boolean asc;
-
- public Sort(String paramName, boolean asc) {
- this.paramName = paramName;
- this.asc = asc;
- }
-
- public String getParameter() {
- return this.paramName;
- }
-
- public boolean isAscending() {
- return asc;
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java
deleted file mode 100644
index ba926e9310e..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/BetweenCondition.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil;
-
-import java.util.Date;
-
-/**
- * @author Pedro Igor
- */
-class BetweenCondition extends NamedParameterCondition {
-
- private final Comparable x;
- private final Comparable y;
-
- public BetweenCondition(String name, Comparable x, Comparable y) {
- super(name);
- this.x = x;
- this.y = y;
- }
-
- @Override
- public void applyCondition(StringBuilder filter) {
- Comparable x = this.x;
- Comparable y = this.y;
-
- if (Date.class.isInstance(x)) {
- x = LDAPUtil.formatDate((Date) x);
- }
-
- if (Date.class.isInstance(y)) {
- y = LDAPUtil.formatDate((Date) y);
- }
-
- filter.append("(").append(x).append("<=").append(getParameterName()).append("<=").append(y).append(")");
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/CustomLDAPFilter.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/CustomLDAPFilter.java
deleted file mode 100644
index 45b3b1d6818..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/CustomLDAPFilter.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.idm.query.Condition;
-
-/**
- * @author Marek Posolda
- */
-class CustomLDAPFilter implements Condition {
-
- private final String customFilter;
-
- public CustomLDAPFilter(String customFilter) {
- this.customFilter = customFilter;
- }
-
- @Override
- public String getParameterName() {
- return null;
- }
-
- @Override
- public void setParameterName(String parameterName) {
- }
-
- @Override
- public void updateParameterName(String modelParamName, String ldapParamName) {
-
- }
-
- @Override
- public void applyCondition(StringBuilder filter) {
- filter.append(customFilter);
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java
deleted file mode 100644
index 115e11f4da1..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/EqualCondition.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil;
-import org.keycloak.models.LDAPConstants;
-
-import java.util.Date;
-
-/**
- * @author Pedro Igor
- */
-public class EqualCondition extends NamedParameterCondition {
-
- private final Object value;
-
- public EqualCondition(String name, Object value) {
- super(name);
- this.value = value;
- }
-
- public Object getValue() {
- return this.value;
- }
-
- @Override
- public void applyCondition(StringBuilder filter) {
- Object parameterValue = value;
- if (Date.class.isInstance(value)) {
- parameterValue = LDAPUtil.formatDate((Date) parameterValue);
- }
-
- filter.append("(").append(getParameterName()).append(LDAPConstants.EQUAL).append(parameterValue).append(")");
- }
-
- @Override
- public String toString() {
- return "EqualCondition{" +
- "paramName=" + getParameterName() +
- ", value=" + value +
- '}';
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java
deleted file mode 100644
index 3ef65357196..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/GreaterThanCondition.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil;
-
-import java.util.Date;
-
-/**
- * @author Pedro Igor
- */
-class GreaterThanCondition extends NamedParameterCondition {
-
- private final boolean orEqual;
-
- private final Comparable value;
-
- public GreaterThanCondition(String name, Comparable value, boolean orEqual) {
- super(name);
- this.value = value;
- this.orEqual = orEqual;
- }
-
- @Override
- public void applyCondition(StringBuilder filter) {
- Comparable parameterValue = value;
-
- if (Date.class.isInstance(parameterValue)) {
- parameterValue = LDAPUtil.formatDate((Date) parameterValue);
- }
-
- if (orEqual) {
- filter.append("(").append(getParameterName()).append(">=").append(parameterValue).append(")");
- } else {
- filter.append("(").append(getParameterName()).append(">").append(parameterValue).append(")");
- }
- }
-}
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java
deleted file mode 100644
index ebecd54cf6a..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/InCondition.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.models.LDAPConstants;
-
-/**
- * @author Pedro Igor
- */
-class InCondition extends NamedParameterCondition {
-
- private final Object[] valuesToCompare;
-
- public InCondition(String name, Object[] valuesToCompare) {
- super(name);
- this.valuesToCompare = valuesToCompare;
- }
-
- @Override
- public void applyCondition(StringBuilder filter) {
-
- filter.append("(&(");
-
- for (int i = 0; i< valuesToCompare.length; i++) {
- Object value = valuesToCompare[i];
-
- filter.append("(").append(getParameterName()).append(LDAPConstants.EQUAL).append(value).append(")");
- }
-
- filter.append("))");
- }
-}
-
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQuery.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQuery.java
deleted file mode 100644
index 5a57f84f3df..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQuery.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.LDAPFederationProvider;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.query.Condition;
-import org.keycloak.federation.ldap.idm.query.Sort;
-import org.keycloak.federation.ldap.mappers.LDAPFederationMapper;
-import org.keycloak.models.ModelDuplicateException;
-import org.keycloak.models.ModelException;
-import org.keycloak.models.UserFederationMapperModel;
-
-import javax.naming.directory.SearchControls;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import static java.util.Collections.unmodifiableSet;
-
-/**
- * Default IdentityQuery implementation.
- *
- *
- * @author Shane Bryzak
- */
-public class LDAPQuery {
-
- private final LDAPFederationProvider ldapFedProvider;
-
- private int offset;
- private int limit;
- private byte[] paginationContext;
- private String searchDn;
- private final Set conditions = new LinkedHashSet();
- private final Set ordering = new LinkedHashSet();
-
- private final Set returningLdapAttributes = new LinkedHashSet();
-
- // Contains just those returningLdapAttributes, which are read-only. They will be marked as read-only in returned LDAPObject instances as well
- // NOTE: names of attributes are lower-cased to avoid case sensitivity issues (LDAP searching is usually case-insensitive, so we want to be as well)
- private final Set returningReadOnlyLdapAttributes = new LinkedHashSet();
- private final Set objectClasses = new LinkedHashSet();
-
- private final List mappers = new ArrayList();
-
- private int searchScope = SearchControls.SUBTREE_SCOPE;
-
- public LDAPQuery(LDAPFederationProvider ldapProvider) {
- this.ldapFedProvider = ldapProvider;
- }
-
- public LDAPQuery addWhereCondition(Condition... condition) {
- this.conditions.addAll(Arrays.asList(condition));
- return this;
- }
-
- public LDAPQuery sortBy(Sort... sorts) {
- this.ordering.addAll(Arrays.asList(sorts));
- return this;
- }
-
- public LDAPQuery setSearchDn(String searchDn) {
- this.searchDn = searchDn;
- return this;
- }
-
- public LDAPQuery addObjectClasses(Collection objectClasses) {
- this.objectClasses.addAll(objectClasses);
- return this;
- }
-
- public LDAPQuery addReturningLdapAttribute(String ldapAttributeName) {
- this.returningLdapAttributes.add(ldapAttributeName);
- return this;
- }
-
- public LDAPQuery addReturningReadOnlyLdapAttribute(String ldapAttributeName) {
- this.returningReadOnlyLdapAttributes.add(ldapAttributeName.toLowerCase());
- return this;
- }
-
- public LDAPQuery addMappers(Collection mappers) {
- this.mappers.addAll(mappers);
- return this;
- }
-
- public LDAPQuery setSearchScope(int searchScope) {
- this.searchScope = searchScope;
- return this;
- }
-
- public Set getSorting() {
- return unmodifiableSet(this.ordering);
- }
-
- public String getSearchDn() {
- return this.searchDn;
- }
-
- public Set getObjectClasses() {
- return unmodifiableSet(this.objectClasses);
- }
-
- public Set getReturningLdapAttributes() {
- return unmodifiableSet(this.returningLdapAttributes);
- }
-
- public Set getReturningReadOnlyLdapAttributes() {
- return unmodifiableSet(this.returningReadOnlyLdapAttributes);
- }
-
- public List getMappers() {
- return mappers;
- }
-
- public int getSearchScope() {
- return searchScope;
- }
-
- public int getLimit() {
- return limit;
- }
-
- public int getOffset() {
- return offset;
- }
-
- public byte[] getPaginationContext() {
- return paginationContext;
- }
-
-
- public List getResultList() {
-
- // Apply mappers now
- List sortedMappers = ldapFedProvider.sortMappersAsc(mappers);
- for (UserFederationMapperModel mapperModel : sortedMappers) {
- LDAPFederationMapper fedMapper = ldapFedProvider.getMapper(mapperModel);
- fedMapper.beforeLDAPQuery(mapperModel, this);
- }
-
- List result = new ArrayList();
-
- try {
- for (LDAPObject ldapObject : ldapFedProvider.getLdapIdentityStore().fetchQueryResults(this)) {
- result.add(ldapObject);
- }
- } catch (Exception e) {
- throw new ModelException("LDAP Query failed", e);
- }
-
- return result;
- }
-
- public LDAPObject getFirstResult() {
- List results = getResultList();
-
- if (results.isEmpty()) {
- return null;
- } else if (results.size() == 1) {
- return results.get(0);
- } else {
- throw new ModelDuplicateException("Error - multiple LDAP objects found but expected just one");
- }
- }
-
- public int getResultCount() {
- return ldapFedProvider.getLdapIdentityStore().countQueryResults(this);
- }
-
- public LDAPQuery setOffset(int offset) {
- this.offset = offset;
- return this;
- }
-
- public LDAPQuery setLimit(int limit) {
- this.limit = limit;
- return this;
- }
-
- public LDAPQuery setPaginationContext(byte[] paginationContext) {
- this.paginationContext = paginationContext;
- return this;
- }
-
- public Set getConditions() {
- return this.conditions;
- }
-
- public LDAPFederationProvider getLdapProvider() {
- return ldapFedProvider;
- }
-
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQueryConditionsBuilder.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQueryConditionsBuilder.java
deleted file mode 100644
index 4be4ba41c57..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LDAPQueryConditionsBuilder.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.idm.query.Condition;
-import org.keycloak.federation.ldap.idm.query.Sort;
-import org.keycloak.models.ModelException;
-
-/**
- * @author Pedro Igor
- */
-public class LDAPQueryConditionsBuilder {
-
- public Condition equal(String parameter, Object value) {
- return new EqualCondition(parameter, value);
- }
-
- public Condition greaterThan(String paramName, Object x) {
- throwExceptionIfNotComparable(x);
- return new GreaterThanCondition(paramName, (Comparable) x, false);
- }
-
- public Condition greaterThanOrEqualTo(String paramName, Object x) {
- throwExceptionIfNotComparable(x);
- return new GreaterThanCondition(paramName, (Comparable) x, true);
- }
-
- public Condition lessThan(String paramName, Comparable x) {
- return new LessThanCondition(paramName, x, false);
- }
-
- public Condition lessThanOrEqualTo(String paramName, Comparable x) {
- return new LessThanCondition(paramName, x, true);
- }
-
- public Condition between(String paramName, Comparable x, Comparable y) {
- return new BetweenCondition(paramName, x, y);
- }
-
- public Condition orCondition(Condition... conditions) {
- if (conditions == null || conditions.length == 0) {
- throw new ModelException("At least one condition should be provided to OR query");
- }
- return new OrCondition(conditions);
- }
-
- public Condition addCustomLDAPFilter(String filter) {
- filter = filter.trim();
- return new CustomLDAPFilter(filter);
- }
-
- public Condition in(String paramName, Object... x) {
- return new InCondition(paramName, x);
- }
-
- public Sort asc(String paramName) {
- return new Sort(paramName, true);
- }
-
- public Sort desc(String paramName) {
- return new Sort(paramName, false);
- }
-
- private void throwExceptionIfNotComparable(Object x) {
- if (!Comparable.class.isInstance(x)) {
- throw new ModelException("Query parameter value [" + x + "] must be " + Comparable.class + ".");
- }
- }
-}
\ No newline at end of file
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java
deleted file mode 100644
index e29b014125b..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/LessThanCondition.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.idm.store.ldap.LDAPUtil;
-
-import java.util.Date;
-
-/**
- * @author Pedro Igor
- */
-class LessThanCondition extends NamedParameterCondition {
-
- private final boolean orEqual;
-
- private final Comparable value;
-
- public LessThanCondition(String name, Comparable value, boolean orEqual) {
- super(name);
- this.value = value;
- this.orEqual = orEqual;
- }
-
- @Override
- public void applyCondition(StringBuilder filter) {
- Comparable parameterValue = value;
-
- if (Date.class.isInstance(parameterValue)) {
- parameterValue = LDAPUtil.formatDate((Date) parameterValue);
- }
-
- if (orEqual) {
- filter.append("(").append(getParameterName()).append("<=").append(parameterValue).append(")");
- } else {
- filter.append("(").append(getParameterName()).append("<").append(parameterValue).append(")");
- }
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/NamedParameterCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/NamedParameterCondition.java
deleted file mode 100644
index 50cb7723be1..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/NamedParameterCondition.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.idm.query.Condition;
-
-/**
- * @author Marek Posolda
- */
-public abstract class NamedParameterCondition implements Condition {
-
- private String parameterName;
-
- public NamedParameterCondition(String parameterName) {
- this.parameterName = parameterName;
- }
-
- @Override
- public String getParameterName() {
- return parameterName;
- }
-
- @Override
- public void setParameterName(String parameterName) {
- this.parameterName = parameterName;
- }
-
-
- @Override
- public void updateParameterName(String modelParamName, String ldapParamName) {
- if (parameterName.equalsIgnoreCase(modelParamName)) {
- this.parameterName = ldapParamName;
- }
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/OrCondition.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/OrCondition.java
deleted file mode 100644
index 7f0e93f211a..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/query/internal/OrCondition.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.query.internal;
-
-import org.keycloak.federation.ldap.idm.query.Condition;
-
-/**
- * @author Marek Posolda
- */
-class OrCondition implements Condition {
-
- private final Condition[] innerConditions;
-
- public OrCondition(Condition... innerConditions) {
- this.innerConditions = innerConditions;
- }
-
- @Override
- public String getParameterName() {
- return null;
- }
-
- @Override
- public void setParameterName(String parameterName) {
- }
-
- @Override
- public void updateParameterName(String modelParamName, String ldapParamName) {
- for (Condition innerCondition : innerConditions) {
- innerCondition.updateParameterName(modelParamName, ldapParamName);
- }
- }
-
- @Override
- public void applyCondition(StringBuilder filter) {
- filter.append("(|");
-
- for (Condition innerCondition : innerConditions) {
- innerCondition.applyCondition(filter);
- }
-
- filter.append(")");
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java
deleted file mode 100644
index c14f4f03adf..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/IdentityStore.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.store;
-
-import org.keycloak.federation.ldap.LDAPConfig;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
-
-import javax.naming.AuthenticationException;
-import java.util.List;
-
-/**
- * IdentityStore representation providing minimal SPI
- *
- * TODO: Rather remove this abstraction
- *
- * @author Boleslaw Dawidowicz
- * @author Shane Bryzak
- */
-public interface IdentityStore {
-
- /**
- * Returns the configuration for this IdentityStore instance
- *
- * @return
- */
- LDAPConfig getConfig();
-
- // General
-
- /**
- * Persists the specified IdentityType
- *
- * @param ldapObject
- */
- void add(LDAPObject ldapObject);
-
- /**
- * Updates the specified IdentityType
- *
- * @param ldapObject
- */
- void update(LDAPObject ldapObject);
-
- /**
- * Removes the specified IdentityType
- *
- * @param ldapObject
- */
- void remove(LDAPObject ldapObject);
-
- // Identity query
-
- List fetchQueryResults(LDAPQuery LDAPQuery);
-
- int countQueryResults(LDAPQuery LDAPQuery);
-
-// // Relationship query
-//
-// List fetchQueryResults(RelationshipQuery query);
-//
-// int countQueryResults(RelationshipQuery query);
-
- // Credentials
-
- /**
- * Validates the specified credentials.
- *
- * @param user Keycloak user
- * @param password Ldap password
- * @throws AuthenticationException if authentication is not successful
- */
- void validatePassword(LDAPObject user, String password) throws AuthenticationException;
-
- /**
- * Updates the specified credential value.
- *
- * @param user Keycloak user
- * @param password Ldap password
- */
- void updatePassword(LDAPObject user, String password);
-
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java
deleted file mode 100644
index 367fb04d57b..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPIdentityStore.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.store.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.federation.ldap.LDAPConfig;
-import org.keycloak.federation.ldap.idm.model.LDAPDn;
-import org.keycloak.federation.ldap.idm.model.LDAPObject;
-import org.keycloak.federation.ldap.idm.query.Condition;
-import org.keycloak.federation.ldap.idm.query.internal.EqualCondition;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
-import org.keycloak.federation.ldap.idm.store.IdentityStore;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.ModelException;
-
-import javax.naming.AuthenticationException;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttribute;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.ModificationItem;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.TreeSet;
-
-/**
- * An IdentityStore implementation backed by an LDAP directory
- *
- * @author Shane Bryzak
- * @author Anil Saldhana
- * @author Pedro Silva
- */
-public class LDAPIdentityStore implements IdentityStore {
-
- private static final Logger logger = Logger.getLogger(LDAPIdentityStore.class);
-
- private final LDAPConfig config;
- private final LDAPOperationManager operationManager;
-
- public LDAPIdentityStore(LDAPConfig config) {
- this.config = config;
-
- try {
- this.operationManager = new LDAPOperationManager(config);
- } catch (NamingException e) {
- throw new ModelException("Couldn't init operation manager", e);
- }
- }
-
- @Override
- public LDAPConfig getConfig() {
- return this.config;
- }
-
- @Override
- public void add(LDAPObject ldapObject) {
- // id will be assigned by the ldap server
- if (ldapObject.getUuid() != null) {
- throw new ModelException("Can't add object with already assigned uuid");
- }
-
- String entryDN = ldapObject.getDn().toString();
- BasicAttributes ldapAttributes = extractAttributes(ldapObject, true);
- this.operationManager.createSubContext(entryDN, ldapAttributes);
- ldapObject.setUuid(getEntryIdentifier(ldapObject));
-
- if (logger.isDebugEnabled()) {
- logger.debugf("Type with identifier [%s] and dn [%s] successfully added to LDAP store.", ldapObject.getUuid(), entryDN);
- }
- }
-
- @Override
- public void update(LDAPObject ldapObject) {
- BasicAttributes updatedAttributes = extractAttributes(ldapObject, false);
- NamingEnumeration attributes = updatedAttributes.getAll();
-
- String entryDn = ldapObject.getDn().toString();
- this.operationManager.modifyAttributes(entryDn, attributes);
-
- if (logger.isDebugEnabled()) {
- logger.debugf("Type with identifier [%s] and DN [%s] successfully updated to LDAP store.", ldapObject.getUuid(), entryDn);
- }
- }
-
- @Override
- public void remove(LDAPObject ldapObject) {
- this.operationManager.removeEntry(ldapObject.getDn().toString());
-
- if (logger.isDebugEnabled()) {
- logger.debugf("Type with identifier [%s] and DN [%s] successfully removed from LDAP store.", ldapObject.getUuid(), ldapObject.getDn().toString());
- }
- }
-
-
- @Override
- public List fetchQueryResults(LDAPQuery identityQuery) {
- if (identityQuery.getSorting() != null && !identityQuery.getSorting().isEmpty()) {
- throw new ModelException("LDAP Identity Store does not yet support sorted queries.");
- }
-
- List results = new ArrayList<>();
-
- try {
- String baseDN = identityQuery.getSearchDn();
-
- for (Condition condition : identityQuery.getConditions()) {
-
- // Check if we are searching by ID
- String uuidAttrName = getConfig().getUuidLDAPAttributeName();
- if (condition instanceof EqualCondition) {
- EqualCondition equalCondition = (EqualCondition) condition;
- if (equalCondition.getParameterName().equalsIgnoreCase(uuidAttrName)) {
- SearchResult search = this.operationManager
- .lookupById(baseDN, equalCondition.getValue().toString(), identityQuery.getReturningLdapAttributes());
-
- if (search != null) {
- results.add(populateAttributedType(search, identityQuery));
- }
-
- return results;
- }
- }
- }
-
-
- StringBuilder filter = createIdentityTypeSearchFilter(identityQuery);
-
- List search;
- if (getConfig().isPagination() && identityQuery.getLimit() > 0) {
- search = this.operationManager.searchPaginated(baseDN, filter.toString(), identityQuery);
- } else {
- search = this.operationManager.search(baseDN, filter.toString(), identityQuery.getReturningLdapAttributes(), identityQuery.getSearchScope());
- }
-
- for (SearchResult result : search) {
- if (!result.getNameInNamespace().equalsIgnoreCase(baseDN)) {
- results.add(populateAttributedType(result, identityQuery));
- }
- }
- } catch (Exception e) {
- throw new ModelException("Querying of LDAP failed " + identityQuery, e);
- }
-
- return results;
- }
-
- @Override
- public int countQueryResults(LDAPQuery identityQuery) {
- int limit = identityQuery.getLimit();
- int offset = identityQuery.getOffset();
-
- identityQuery.setLimit(0);
- identityQuery.setOffset(0);
-
- int resultCount = identityQuery.getResultList().size();
-
- identityQuery.setLimit(limit);
- identityQuery.setOffset(offset);
-
- return resultCount;
- }
-
- // *************** CREDENTIALS AND USER SPECIFIC STUFF
-
- @Override
- public void validatePassword(LDAPObject user, String password) throws AuthenticationException {
- String userDN = user.getDn().toString();
-
- if (logger.isTraceEnabled()) {
- logger.tracef("Using DN [%s] for authentication of user", userDN);
- }
-
- operationManager.authenticate(userDN, password);
- }
-
- @Override
- public void updatePassword(LDAPObject user, String password) {
- String userDN = user.getDn().toString();
-
- if (logger.isDebugEnabled()) {
- logger.debugf("Using DN [%s] for updating LDAP password of user", userDN);
- }
-
- if (getConfig().isActiveDirectory()) {
- updateADPassword(userDN, password);
- } else {
- ModificationItem[] mods = new ModificationItem[1];
-
- try {
- BasicAttribute mod0 = new BasicAttribute(LDAPConstants.USER_PASSWORD_ATTRIBUTE, password);
-
- mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, mod0);
-
- operationManager.modifyAttribute(userDN, mod0);
- } catch (ModelException me) {
- throw me;
- } catch (Exception e) {
- throw new ModelException("Error updating password.", e);
- }
- }
- }
-
-
- private void updateADPassword(String userDN, String password) {
- try {
- // Replace the "unicdodePwd" attribute with a new value
- // Password must be both Unicode and a quoted string
- String newQuotedPassword = "\"" + password + "\"";
- byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
-
- BasicAttribute unicodePwd = new BasicAttribute("unicodePwd", newUnicodePassword);
-
- List modItems = new ArrayList();
- modItems.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, unicodePwd));
-
- operationManager.modifyAttributes(userDN, modItems.toArray(new ModificationItem[] {}));
- } catch (ModelException me) {
- throw me;
- } catch (Exception e) {
- throw new ModelException(e);
- }
- }
-
- // ************ END CREDENTIALS AND USER SPECIFIC STUFF
-
- protected StringBuilder createIdentityTypeSearchFilter(final LDAPQuery identityQuery) {
- StringBuilder filter = new StringBuilder();
-
- for (Condition condition : identityQuery.getConditions()) {
- condition.applyCondition(filter);
- }
-
- filter.insert(0, "(&");
- filter.append(getObjectClassesFilter(identityQuery.getObjectClasses()));
- filter.append(")");
-
- if (logger.isTraceEnabled()) {
- logger.tracef("Using filter for LDAP search: %s . Searching in DN: %s", filter, identityQuery.getSearchDn());
- }
- return filter;
- }
-
-
- private StringBuilder getObjectClassesFilter(Collection objectClasses) {
- StringBuilder builder = new StringBuilder();
-
- if (!objectClasses.isEmpty()) {
- for (String objectClass : objectClasses) {
- builder.append("(").append(LDAPConstants.OBJECT_CLASS).append(LDAPConstants.EQUAL).append(objectClass).append(")");
- }
- } else {
- builder.append("(").append(LDAPConstants.OBJECT_CLASS).append(LDAPConstants.EQUAL).append("*").append(")");
- }
-
- return builder;
- }
-
-
- private LDAPObject populateAttributedType(SearchResult searchResult, LDAPQuery ldapQuery) {
- Set readOnlyAttrNames = ldapQuery.getReturningReadOnlyLdapAttributes();
- Set lowerCasedAttrNames = new TreeSet<>();
- for (String attrName : ldapQuery.getReturningLdapAttributes()) {
- lowerCasedAttrNames.add(attrName.toLowerCase());
- }
-
- try {
- String entryDN = searchResult.getNameInNamespace();
- Attributes attributes = searchResult.getAttributes();
-
- LDAPObject ldapObject = new LDAPObject();
- LDAPDn dn = LDAPDn.fromString(entryDN);
- ldapObject.setDn(dn);
- ldapObject.setRdnAttributeName(dn.getFirstRdnAttrName());
-
- NamingEnumeration extends Attribute> ldapAttributes = attributes.getAll();
-
- while (ldapAttributes.hasMore()) {
- Attribute ldapAttribute = ldapAttributes.next();
-
- try {
- ldapAttribute.get();
- } catch (NoSuchElementException nsee) {
- continue;
- }
-
- String ldapAttributeName = ldapAttribute.getID();
-
- if (ldapAttributeName.equalsIgnoreCase(getConfig().getUuidLDAPAttributeName())) {
- Object uuidValue = ldapAttribute.get();
- ldapObject.setUuid(this.operationManager.decodeEntryUUID(uuidValue));
- }
-
- // Note: UUID is normally not populated here. It's populated just in case that it's used for name of other attribute as well
- if (!ldapAttributeName.equalsIgnoreCase(getConfig().getUuidLDAPAttributeName()) || (lowerCasedAttrNames.contains(ldapAttributeName.toLowerCase()))) {
- Set attrValues = new LinkedHashSet<>();
- NamingEnumeration> enumm = ldapAttribute.getAll();
- while (enumm.hasMoreElements()) {
- String attrVal = enumm.next().toString().trim();
- attrValues.add(attrVal);
- }
-
- if (ldapAttributeName.equalsIgnoreCase(LDAPConstants.OBJECT_CLASS)) {
- ldapObject.setObjectClasses(attrValues);
- } else {
- ldapObject.setAttribute(ldapAttributeName, attrValues);
-
- // readOnlyAttrNames are lower-cased
- if (readOnlyAttrNames.contains(ldapAttributeName.toLowerCase())) {
- ldapObject.addReadOnlyAttributeName(ldapAttributeName);
- }
- }
- }
- }
-
- if (logger.isTraceEnabled()) {
- logger.tracef("Found ldap object and populated with the attributes. LDAP Object: %s", ldapObject.toString());
- }
- return ldapObject;
-
- } catch (Exception e) {
- throw new ModelException("Could not populate attribute type " + searchResult.getNameInNamespace() + ".", e);
- }
- }
-
-
- protected BasicAttributes extractAttributes(LDAPObject ldapObject, boolean isCreate) {
- BasicAttributes entryAttributes = new BasicAttributes();
-
- for (Map.Entry> attrEntry : ldapObject.getAttributes().entrySet()) {
- String attrName = attrEntry.getKey();
- Set attrValue = attrEntry.getValue();
-
- // ldapObject.getReadOnlyAttributeNames() are lower-cased
- if (!ldapObject.getReadOnlyAttributeNames().contains(attrName.toLowerCase()) && (isCreate || !ldapObject.getRdnAttributeName().equalsIgnoreCase(attrName))) {
-
- if (attrValue == null) {
- // Shouldn't happen
- logger.warnf("Attribute '%s' is null on LDAP object '%s' . Using empty value to be saved to LDAP", attrName, ldapObject.getDn().toString());
- attrValue = Collections.emptySet();
- }
-
- // Ignore empty attributes during create
- if (isCreate && attrValue.isEmpty()) {
- continue;
- }
-
- BasicAttribute attr = new BasicAttribute(attrName);
- for (String val : attrValue) {
- if (val == null || val.toString().trim().length() == 0) {
- val = LDAPConstants.EMPTY_ATTRIBUTE_VALUE;
- }
- attr.add(val);
- }
-
- entryAttributes.put(attr);
- }
- }
-
- // Don't extract object classes for update
- if (isCreate) {
- BasicAttribute objectClassAttribute = new BasicAttribute(LDAPConstants.OBJECT_CLASS);
-
- for (String objectClassValue : ldapObject.getObjectClasses()) {
- objectClassAttribute.add(objectClassValue);
-
- if (objectClassValue.equalsIgnoreCase(LDAPConstants.GROUP_OF_NAMES)
- || objectClassValue.equalsIgnoreCase(LDAPConstants.GROUP_OF_ENTRIES)
- || objectClassValue.equalsIgnoreCase(LDAPConstants.GROUP_OF_UNIQUE_NAMES)) {
- entryAttributes.put(LDAPConstants.MEMBER, LDAPConstants.EMPTY_MEMBER_ATTRIBUTE_VALUE);
- }
- }
-
- entryAttributes.put(objectClassAttribute);
- }
-
- return entryAttributes;
- }
-
-
- protected String getEntryIdentifier(final LDAPObject ldapObject) {
- try {
- // we need this to retrieve the entry's identifier from the ldap server
- String uuidAttrName = getConfig().getUuidLDAPAttributeName();
- List search = this.operationManager.search(ldapObject.getDn().toString(), "(" + ldapObject.getDn().getFirstRdn() + ")", Arrays.asList(uuidAttrName), SearchControls.OBJECT_SCOPE);
- Attribute id = search.get(0).getAttributes().get(getConfig().getUuidLDAPAttributeName());
-
- if (id == null) {
- throw new ModelException("Could not retrieve identifier for entry [" + ldapObject.getDn().toString() + "].");
- }
-
- return this.operationManager.decodeEntryUUID(id.get());
- } catch (NamingException ne) {
- throw new ModelException("Could not retrieve identifier for entry [" + ldapObject.getDn().toString() + "].");
- }
- }
-}
diff --git a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java b/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java
deleted file mode 100644
index 02cd122b21c..00000000000
--- a/federation/ldap/src/main/java/org/keycloak/federation/ldap/idm/store/ldap/LDAPOperationManager.java
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.federation.ldap.idm.store.ldap;
-
-import org.jboss.logging.Logger;
-import org.keycloak.federation.ldap.LDAPConfig;
-import org.keycloak.federation.ldap.idm.query.internal.LDAPQuery;
-import org.keycloak.models.LDAPConstants;
-import org.keycloak.models.ModelException;
-
-import javax.naming.AuthenticationException;
-import javax.naming.Binding;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.ModificationItem;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-import javax.naming.ldap.Control;
-import javax.naming.ldap.InitialLdapContext;
-import javax.naming.ldap.LdapContext;
-import javax.naming.ldap.PagedResultsControl;
-import javax.naming.ldap.PagedResultsResponseControl;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-/**
- *
This class provides a set of operations to manage LDAP trees.
- * Modifies the given {@link javax.naming.directory.Attribute} instance using the given DN. This method performs a REPLACE_ATTRIBUTE
- * operation.
- *