/**
* Copyright (c) 2011 SUSE LLC
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.common.security;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* This is a utility class containing static methods for handling creation and
* validation of security tokens used for preventing from CSRF attacks.
*/
public final class CSRFTokenValidator {
private static String tokenKey = "csrf_token";
private static String defaultAlgorithm = "SHA1PRNG";
/* utility class, no public constructor */
private CSRFTokenValidator() {
}
/**
* Create a new CSRF token using the given algorithm, throws a runtime
* exception in case of an algorithm is used that is not available.
*
* @param alg
* @return token as a String
* @throws CSRFTokenException
*/
private static String createNewToken(String alg) throws CSRFTokenException {
String tokenValue = null;
try {
tokenValue = String.valueOf(SecureRandom.getInstance(alg).nextLong());
}
catch (NoSuchAlgorithmException e) {
throw new CSRFTokenException(e.getMessage(), e);
}
return tokenValue;
}
/**
* Return the CSRF token from the given session, create a new token if
* there is currently none associated with this session.
*
* @param session HttpSession to retrieve the token from
* @return token Security token retrieved from the session
*/
public static String getToken(HttpSession session) {
String tokenValue = (String) session.getAttribute(tokenKey);
if (tokenValue == null) {
// Create new token if necessary
tokenValue = createNewToken(defaultAlgorithm);
session.setAttribute(tokenKey, tokenValue);
}
return tokenValue;
}
/**
* Validate a given request within its own session, throws a runtime
* exception leading to internal server error in case of failure.
*
* @param request HTTPServletRequest to validate the token for
* @throws CSRFTokenException In case the validation failed
*/
public static void validate(HttpServletRequest request) throws CSRFTokenException {
HttpSession session = request.getSession();
if (session.getAttribute(tokenKey) == null) {
throw new CSRFTokenException("Session does not contain a CSRF security token");
}
if (request.getParameter(tokenKey) == null) {
throw new CSRFTokenException("Request does not contain a CSRF security token");
}
if (!session.getAttribute(tokenKey).equals(request.getParameter(tokenKey))) {
throw new CSRFTokenException("Validation of CSRF security token failed");
}
}
}