/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* https://opensso.dev.java.net/public/CDDLv1.0.html or
* opensso/legal/CDDLv1.0.txt
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: ReplayPasswd.java,v 1.6 2009/11/04 22:50:35 manish_rustagi Exp $
*
* Portions Copyrighted 2011-2016 ForgeRock AS.
*/
package com.sun.identity.authentication.spi;
import com.iplanet.am.util.Misc;
import com.iplanet.am.util.SystemProperties;
import com.iplanet.sso.SSOToken;
import com.iplanet.sso.SSOException;
import com.sun.identity.authentication.service.AuthUtils;
import com.sun.identity.authentication.util.ISAuthConstants;
import com.sun.identity.idm.AMIdentity;
import com.sun.identity.idm.IdRepoException;
import com.sun.identity.idm.IdUtils;
import com.sun.identity.shared.debug.Debug;
import com.sun.identity.shared.encode.Base64;
import com.sun.identity.shared.encode.CookieUtils;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Cookie;
import org.forgerock.openam.utils.StringUtils;
/**
* This class is used to set the encrypted password as a session property.
* It reads the value of the property "com.sun.am.replaypasswd.key" which is
* the key that is to be used for DES Encryption. Once the password is
* encrypted, it assigns a session property "sunIdentityUserPassword" with
* this value.
* This class is also used to set "sharepoint_login_attr_value" as a session
* property to support Sharepoint. It reads the value of the property
* "com.sun.am.sharepoint_login_attr_name" which indicates the user token that
* Sharepoint uses for authentication and gets its corresponding attribute
* value from the user datastore.It will then put this as a value of
* "sharepoint_login_attr_value" session property.
* This class also sets the "owaAuthCookie" for the all the domains for which
* "iPlanetdirectoryPro" cookie is set.
*/
public class ReplayPasswd implements AMPostAuthProcessInterface {
private static final String CIPHER_INSTANCE_NAME =
"DES/ECB/NoPadding";
private static final String REPLAY_PASSWORD_KEY =
"com.sun.am.replaypasswd.key";
private static final String SUN_IDENTITY_USER_PASSWORD =
"sunIdentityUserPassword";
private static final String IIS_OWA_ENABLED =
"com.sun.am.iis_owa_enabled";
private static final String OWA_AUTH_COOKIE =
"owaAuthCookie";
private static final String OWA_AUTH_COOKIE_VALUE =
"amOwaValue";
private static final String SHAREPOINT_LOGIN_ATTR_NAME =
"com.sun.am.sharepoint_login_attr_name";
private static final String SHAREPOINT_LOGIN_ATTR_VALUE =
"sharepoint_login_attr_value";
private static Debug debug = Debug.getInstance("ReplayPasswd");
/**
* Post processing on successful authentication.
* @param requestParamsMap contains HttpServletRequest parameters
* @param request HttpServlet request
* @param response HttpServlet response
* @param ssoToken user's session
* @throws AuthenticationException if there is an error while setting
* the session password property
*/
public void onLoginSuccess(Map requestParamsMap,
HttpServletRequest request,
HttpServletResponse response,
SSOToken ssoToken) throws AuthenticationException {
if (request == null) {
debug.message("ReplayPasswd.onLoginSuccess: request is not available, password is not saved.");
return;
}
if (debug.messageEnabled()) {
debug.message("ReplayPasswd.onLoginSuccess called: Req:" + request.getRequestURL());
}
try {
if (requestParamsMap == null) {
debug.warning("ReplayPasswd: unable to get user password as requestParamsMap is null");
} else {
String userpasswd = (String) requestParamsMap.get(ISAuthConstants.SHARED_STATE_PASSWORD);
if (StringUtils.isNotEmpty(userpasswd)) {
String encryptedPassword = encryptPassword(userpasswd);
if (StringUtils.isNotBlank(encryptedPassword)) {
ssoToken.setProperty(SUN_IDENTITY_USER_PASSWORD, encryptedPassword);
} else if (debug.warningEnabled()) {
debug.warning("ReplayPasswd: unable to set encrypted Password as encrypted value is empty");
}
} else if (debug.warningEnabled()) {
debug.warning("ReplayPasswd: unable to get user password to encrypt");
}
}
String iisOwaEnabled = SystemProperties.get(IIS_OWA_ENABLED);
String strAttributeName = SystemProperties.get(SHAREPOINT_LOGIN_ATTR_NAME);
if (Boolean.parseBoolean(iisOwaEnabled)) {
// Set OWA Auth Cookie
Cookie owaAuthCookie;
for (String domain : AuthUtils.getCookieDomainsForRequest(request)) {
owaAuthCookie = CookieUtils.newCookie(OWA_AUTH_COOKIE, OWA_AUTH_COOKIE_VALUE, "/", domain);
CookieUtils.addCookieToResponse(response, owaAuthCookie);
}
}
if (strAttributeName != null && !strAttributeName.trim().equals("")) {
AMIdentity amIdentityUser = IdUtils.getIdentity(ssoToken);
Map attrMap = amIdentityUser.getAttributes();
String strAttributeValue = Misc.getMapAttr(attrMap, strAttributeName, null);
if (strAttributeValue != null) {
ssoToken.setProperty(SHAREPOINT_LOGIN_ATTR_VALUE, strAttributeValue);
}
if (debug.messageEnabled()) {
debug.message("ReplayPasswd.onLoginSuccess: " + strAttributeName + "=" + strAttributeValue);
}
}
if (debug.messageEnabled()) {
debug.message("ReplayPasswd.onLoginSuccess: Replay password concluded successfully");
}
} catch (IdRepoException ire) {
debug.error("ReplayPasswd.onLoginSuccess: IOException while fetching user attributes: " + ire);
} catch (NoSuchAlgorithmException noe) {
debug.error("ReplayPasswd.onLoginSuccess: NoSuchAlgorithmException"
+ " while setting session password property: " + noe);
} catch (InvalidKeyException ike) {
debug.error("ReplayPasswd.onLoginSuccess: InvalidKeyException "
+ "while setting session password property: " + ike);
} catch (IllegalBlockSizeException ibe) {
debug.error("ReplayPasswd.onLoginSuccess:IllegalBlockSizeException"
+ " while setting session password property: " + ibe);
} catch (NoSuchPaddingException npe) {
debug.error("ReplayPasswd.onLoginSuccess: NoSuchPaddingException "
+ "while setting session password property: " + npe);
} catch (BadPaddingException bpe) {
debug.error("ReplayPasswd.onLoginSuccess: BadPaddingException "
+ "while setting session password property: " + bpe);
} catch (SSOException sse) {
debug.error("ReplayPasswd.onLoginSuccess: SSOException while setting session password property: "
+ sse);
}
}
/**
* Post processing on failed authentication.
* @param requestParamsMap contains HttpServletRequest parameters
* @param req HttpServlet request
* @param res HttpServlet response
* @throws AuthenticationException if there is an error
*/
public void onLoginFailure(Map requestParamsMap,
HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException {
debug.message("ReplayPasswd.onLoginFailure: called");
}
/**
* Post processing on Logout.
* @param req HttpServlet request
* @param res HttpServlet response
* @param ssoToken user's session
* @throws AuthenticationException if there is an error
*/
public void onLogout(HttpServletRequest req,
HttpServletResponse res,
SSOToken ssoToken) throws AuthenticationException {
debug.message("ReplayPasswd.onLogout called");
}
/**
* Encrypts the provided password.
* @param userpasswd the password
* @return the encrypted password
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
* @throws InvalidKeyException
* @throws IllegalBlockSizeException
* @throws BadPaddingException
* @throws SSOException
*/
private String encryptPassword(String userpasswd) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, SSOException {
String deskeystr = SystemProperties.get(REPLAY_PASSWORD_KEY);
if (StringUtils.isBlank(deskeystr)){
if (debug.messageEnabled()) {
debug.message("ReplayPasswd.encodePassword: cannot encode password, Replay PaswordKey is empty");
}
return null;
}
byte[] desKey = Base64.decode(deskeystr);
SecretKeySpec keySpec = new SecretKeySpec(desKey, "DES");
Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE_NAME);
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
// The array size must be a multiply of 8 (DES block size)
int length = userpasswd.length() + (8 - userpasswd.length() % 8);
byte[] data = new byte[length];
System.arraycopy(userpasswd.getBytes(), 0, data, 0, userpasswd.length());
byte[] ciphertext = cipher.doFinal(data);
return Base64.encode(ciphertext);
}
}