/*
* 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.http;
import com.novell.ldapchai.ChaiFactory;
import com.novell.ldapchai.ChaiUser;
import com.novell.ldapchai.exception.ChaiUnavailableException;
import com.novell.ldapchai.provider.ChaiProvider;
import password.pwm.Permission;
import password.pwm.PwmApplication;
import password.pwm.bean.UserIdentity;
import password.pwm.bean.UserInfoBean;
import password.pwm.config.PwmSetting;
import password.pwm.config.UserPermission;
import password.pwm.config.profile.DeleteAccountProfile;
import password.pwm.config.profile.HelpdeskProfile;
import password.pwm.config.profile.Profile;
import password.pwm.config.profile.ProfileType;
import password.pwm.config.profile.UpdateAttributesProfile;
import password.pwm.error.ErrorInformation;
import password.pwm.error.PwmError;
import password.pwm.error.PwmUnrecoverableException;
import password.pwm.ldap.LdapOperationsHelper;
import password.pwm.ldap.LdapPermissionTester;
import password.pwm.ldap.LdapUserDataReader;
import password.pwm.ldap.UserDataReader;
import password.pwm.util.PasswordData;
import password.pwm.util.logging.PwmLogger;
import password.pwm.util.macro.MacroMachine;
import java.io.Serializable;
import java.util.List;
/**
* Wraps an <i>HttpSession</i> to provide additional PWM-related session
* management activities.
* <p/>
*
* @author Jason D. Rivard
*/
public class SessionManager implements Serializable {
// ------------------------------ FIELDS ------------------------------
private static final PwmLogger LOGGER = PwmLogger.forClass(SessionManager.class);
private ChaiProvider chaiProvider;
private final PwmSession pwmSession;
private transient UserDataReader userDataReader;
// --------------------------- CONSTRUCTORS ---------------------------
public SessionManager(final PwmSession pwmSession) {
this.pwmSession = pwmSession;
}
// --------------------- GETTER / SETTER METHODS ---------------------
public ChaiProvider getChaiProvider()
throws ChaiUnavailableException, PwmUnrecoverableException
{
if (chaiProvider == null) {
throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_AUTHENTICATION_REQUIRED,"ldap connection is not available for session"));
}
return chaiProvider;
}
public void setChaiProvider(final ChaiProvider chaiProvider) {
this.chaiProvider = chaiProvider;
}
public void updateUserPassword(final PwmApplication pwmApplication, final UserIdentity userIdentity, final PasswordData userPassword)
throws PwmUnrecoverableException
{
this.closeConnections();
try {
this.chaiProvider = LdapOperationsHelper.createChaiProvider(
pwmSession.getLabel(),
userIdentity.getLdapProfile(pwmApplication.getConfig()),
pwmApplication.getConfig(),
userIdentity.getUserDN(),
userPassword
);
final String userDN = userIdentity.getUserDN();
ChaiFactory.createChaiEntry(userDN,chaiProvider).isValid();
} catch (ChaiUnavailableException e) {
final ErrorInformation errorInformation = new ErrorInformation(
PwmError.ERROR_DIRECTORY_UNAVAILABLE,
"error updating cached chaiProvider connection/password: " + e.getMessage());
throw new PwmUnrecoverableException(errorInformation);
}
}
// ------------------------ CANONICAL METHODS ------------------------
public void closeConnections() {
if (chaiProvider != null) {
try {
LOGGER.debug(pwmSession.getLabel(), "closing user ldap connection");
chaiProvider.close();
chaiProvider = null;
} catch (Exception e) {
LOGGER.error(pwmSession.getLabel(), "error while closing user connection: " + e.getMessage());
}
}
if (userDataReader != null) {
userDataReader = null;
}
}
// -------------------------- OTHER METHODS --------------------------
public ChaiUser getActor(final PwmApplication pwmApplication)
throws ChaiUnavailableException, PwmUnrecoverableException {
if (!pwmSession.isAuthenticated()) {
throw new IllegalStateException("user not logged in");
}
final UserIdentity userDN = pwmSession.getUserInfoBean().getUserIdentity();
if (userDN == null || userDN.getUserDN() == null || userDN.getUserDN().length() < 1) {
throw new IllegalStateException("user not logged in");
}
return ChaiFactory.createChaiUser(userDN.getUserDN(), this.getChaiProvider());
}
public boolean hasActiveLdapConnection() {
return this.chaiProvider != null && this.chaiProvider.isConnected();
}
public ChaiUser getActor(final PwmApplication pwmApplication, final UserIdentity userIdentity)
throws PwmUnrecoverableException
{
try {
if (!pwmSession.isAuthenticated()) {
throw new PwmUnrecoverableException(PwmError.ERROR_AUTHENTICATION_REQUIRED);
}
final UserIdentity thisIdentity = pwmSession.getUserInfoBean().getUserIdentity();
if (thisIdentity.getLdapProfileID() == null || userIdentity.getLdapProfileID() == null) {
throw new PwmUnrecoverableException(PwmError.ERROR_NO_LDAP_CONNECTION);
}
final ChaiProvider provider = this.getChaiProvider();
return ChaiFactory.createChaiUser(userIdentity.getUserDN(), provider);
} catch (ChaiUnavailableException e) {
throw PwmUnrecoverableException.fromChaiException(e);
}
}
public UserDataReader getUserDataReader(final PwmApplication pwmApplication)
throws PwmUnrecoverableException
{
if (pwmSession == null || !pwmSession.isAuthenticated()) {
return null;
}
if (userDataReader == null) {
/*
userDataReader = LdapUserDataReader.appProxiedReader(pwmApplication,
pwmSession.getUserInfoBean().getUserIdentity());
*/
final UserIdentity userIdentity = pwmSession.getUserInfoBean().getUserIdentity();
try {
userDataReader = LdapUserDataReader.selfProxiedReader(pwmApplication, pwmSession, userIdentity);
} catch (ChaiUnavailableException e) {
throw PwmUnrecoverableException.fromChaiException(e);
}
}
return userDataReader;
}
public void clearUserDataReader() {
userDataReader = null;
}
public void incrementRequestCounterKey() {
if (this.pwmSession != null) {
this.pwmSession.getLoginInfoBean().setReqCounter(
this.pwmSession.getLoginInfoBean().getReqCounter() + 1)
;
LOGGER.trace(pwmSession.getLabel(), "incremented request counter to " + this.pwmSession.getLoginInfoBean().getReqCounter());
}
}
public boolean checkPermission(final PwmApplication pwmApplication, final Permission permission)
throws PwmUnrecoverableException
{
final boolean devDebugMode = pwmApplication.getConfig().isDevDebugMode();
if (devDebugMode) {
LOGGER.trace(pwmSession.getLabel(), String.format("entering checkPermission(%s, %s, %s)", permission, pwmSession, pwmApplication));
}
if (!pwmSession.isAuthenticated()) {
if (devDebugMode) {
LOGGER.trace(pwmSession.getLabel(), "user is not authenticated, returning false for permission check");
}
return false;
}
Permission.PermissionStatus status = pwmSession.getUserSessionDataCacheBean().getPermission(permission);
if (status == Permission.PermissionStatus.UNCHECKED) {
if (devDebugMode) {
LOGGER.debug(pwmSession.getLabel(), String.format("checking permission %s for user %s", permission.toString(), pwmSession.getUserInfoBean().getUserIdentity().toDelimitedKey()));
}
final PwmSetting setting = permission.getPwmSetting();
final List<UserPermission> userPermission = pwmApplication.getConfig().readSettingAsUserPermission(setting);
final boolean result = LdapPermissionTester.testUserPermissions(pwmApplication, pwmSession.getLabel(), pwmSession.getUserInfoBean().getUserIdentity(), userPermission);
status = result ? Permission.PermissionStatus.GRANTED : Permission.PermissionStatus.DENIED;
pwmSession.getUserSessionDataCacheBean().setPermission(permission, status);
LOGGER.debug(pwmSession.getLabel(), String.format("permission %s for user %s is %s",
permission.toString(), pwmSession.getUserInfoBean().getUserIdentity().toDelimitedKey(),
status.toString()));
}
return status == Permission.PermissionStatus.GRANTED;
}
public MacroMachine getMacroMachine(final PwmApplication pwmApplication)
throws PwmUnrecoverableException
{
final UserDataReader userDataReader = this.getUserDataReader(pwmApplication);
final UserInfoBean userInfoBean = pwmSession.isAuthenticated()
? pwmSession.getUserInfoBean()
: null;
return new MacroMachine(pwmApplication, pwmSession.getLabel(), userInfoBean, pwmSession.getLoginInfoBean(), userDataReader);
}
public Profile getProfile(final PwmApplication pwmApplication, final ProfileType profileType) {
if (profileType.isAuthenticated() && !pwmSession.isAuthenticated()) {
return null;
}
final String profileID = pwmSession.getUserInfoBean().getProfileIDs().get(profileType);
if (profileID != null) {
return pwmApplication.getConfig().profileMap(profileType).get(profileID);
}
return null;
}
public HelpdeskProfile getHelpdeskProfile(final PwmApplication pwmApplication) {
return (HelpdeskProfile)getProfile(pwmApplication, ProfileType.Helpdesk);
}
public UpdateAttributesProfile getUpdateAttributeProfile(final PwmApplication pwmApplication) {
return (UpdateAttributesProfile)getProfile(pwmApplication, ProfileType.UpdateAttributes);
}
public DeleteAccountProfile getSelfDeleteProfile(final PwmApplication pwmApplication) {
return (DeleteAccountProfile) getProfile(pwmApplication, ProfileType.DeleteAccount);
}
}