/*
* Password Management Servlets (PWM)
* http://www.pwm-project.org
*
* Copyright (c) 2006-2009 Novell, Inc.
* Copyright (c) 2009-2017 The PWM Project
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package password.pwm.config.function;
import com.novell.ldapchai.ChaiEntry;
import com.novell.ldapchai.ChaiFactory;
import com.novell.ldapchai.provider.ChaiProvider;
import password.pwm.AppProperty;
import password.pwm.PwmApplication;
import password.pwm.PwmConstants;
import password.pwm.bean.SessionLabel;
import password.pwm.bean.UserIdentity;
import password.pwm.config.Configuration;
import password.pwm.config.PwmSetting;
import password.pwm.config.SettingUIFunction;
import password.pwm.config.UserPermission;
import password.pwm.config.stored.StoredConfigurationImpl;
import password.pwm.error.ErrorInformation;
import password.pwm.error.PwmError;
import password.pwm.error.PwmOperationalException;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.http.PwmRequest;
import password.pwm.i18n.Display;
import password.pwm.ldap.LdapPermissionTester;
import password.pwm.util.LocaleHelper;
import password.pwm.util.java.TimeDuration;
import password.pwm.util.logging.PwmLogger;
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class UserMatchViewerFunction implements SettingUIFunction {
private static final PwmLogger LOGGER = PwmLogger.forClass(UserMatchViewerFunction.class);
@Override
public Serializable provideFunction(
final PwmRequest pwmRequest,
final StoredConfigurationImpl storedConfiguration,
final PwmSetting setting,
final String profile,
final String extraData)
throws Exception
{
final PwmApplication pwmApplication = pwmRequest.getPwmApplication();
final Date startSearchTime = new Date();
final int maxResultSize = Integer.parseInt(pwmApplication.getConfig().readAppProperty(AppProperty.CONFIG_EDITOR_QUERY_FILTER_TEST_LIMIT));
final Collection<UserIdentity> users = discoverMatchingUsers(pwmApplication, maxResultSize, storedConfiguration, setting, profile);
final TimeDuration searchDuration = TimeDuration.fromCurrent(startSearchTime);
final UserMatchViewerResults userMatchViewerResults = new UserMatchViewerResults();
final boolean sizeExceeded = users.size() >= maxResultSize;
userMatchViewerResults.setUsers(users);
userMatchViewerResults.setSearchOperationSummary(
LocaleHelper.getLocalizedMessage(
Display.Display_SearchResultsInfo, pwmRequest,
String.valueOf(users.size()),
searchDuration.asLongString(pwmRequest.getLocale())
));
userMatchViewerResults.setSizeExceeded(sizeExceeded);
return userMatchViewerResults;
}
public Collection<UserIdentity> discoverMatchingUsers(
final PwmApplication pwmApplication,
final int maxResultSize,
final StoredConfigurationImpl storedConfiguration,
final PwmSetting setting,
final String profile
)
throws Exception
{
final Configuration config = new Configuration(storedConfiguration);
final PwmApplication tempApplication = new PwmApplication(pwmApplication.getPwmEnvironment().makeRuntimeInstance(config));
final List<UserPermission> permissions = (List<UserPermission>)storedConfiguration.readSetting(setting,profile).toNativeObject();
for (final UserPermission userPermission : permissions) {
if (userPermission.getType() == UserPermission.Type.ldapQuery) {
if (userPermission.getLdapBase() != null && !userPermission.getLdapBase().isEmpty()) {
testIfLdapDNIsValid(tempApplication, userPermission.getLdapBase(), userPermission.getLdapProfileID());
}
} else if (userPermission.getType() == UserPermission.Type.ldapGroup) {
testIfLdapDNIsValid(tempApplication, userPermission.getLdapBase(), userPermission.getLdapProfileID());
}
}
return LdapPermissionTester.discoverMatchingUsers(tempApplication, maxResultSize, permissions, SessionLabel.SYSTEM_LABEL).keySet();
}
private void testIfLdapDNIsValid(final PwmApplication pwmApplication, final String baseDN, final String profileID)
throws PwmOperationalException, PwmUnrecoverableException {
final Set<String> profileIDsToTest = new LinkedHashSet<>();
if (profileID == null || profileID.isEmpty()) {
profileIDsToTest.add(pwmApplication.getConfig().getDefaultLdapProfile().getIdentifier());
} else if (profileID.equals(PwmConstants.PROFILE_ID_ALL)) {
profileIDsToTest.addAll(pwmApplication.getConfig().getLdapProfiles().keySet());
} else {
profileIDsToTest.add(profileID);
}
for (final String loopID : profileIDsToTest) {
ChaiEntry chaiEntry = null;
try {
final ChaiProvider proxiedProvider = pwmApplication.getProxyChaiProvider(loopID);
chaiEntry = ChaiFactory.createChaiEntry(baseDN, proxiedProvider);
} catch (Exception e) {
LOGGER.error("error while testing entry DN for profile '" + profileID + "', error:" + profileID);
}
if (chaiEntry != null && !chaiEntry.isValid()) {
final String errorMsg = "entry DN '" + baseDN + "' is not valid for profile " + loopID;
throw new PwmOperationalException(new ErrorInformation(PwmError.ERROR_LDAP_DATA_ERROR, errorMsg));
}
}
}
public static class UserMatchViewerResults implements Serializable {
private Collection<UserIdentity> users;
private boolean sizeExceeded;
private String searchOperationSummary;
public Collection<UserIdentity> getUsers() {
return users;
}
public void setUsers(final Collection<UserIdentity> users) {
this.users = users;
}
public boolean isSizeExceeded() {
return sizeExceeded;
}
public void setSizeExceeded(final boolean sizeExceeded) {
this.sizeExceeded = sizeExceeded;
}
public String getSearchOperationSummary() {
return searchOperationSummary;
}
public void setSearchOperationSummary(final String searchOperationSummary) {
this.searchOperationSummary = searchOperationSummary;
}
}
}