/*
* Copyright (c) 2012-2013 EMC Corporation
* All Rights Reserved
*/
package com.emc.storageos.security.authentication;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.emc.storageos.security.authentication.InternalApiSignatureKeyGenerator.SignatureKeyType;
import java.net.URLDecoder;
/**
* Abstract authentication filter which has support for processing HMAC signatures
*/
public abstract class AbstractHMACAuthFilter extends AbstractAuthenticationFilter {
private static final Logger _log = LoggerFactory.getLogger(AbstractHMACAuthFilter.class);
public static final String INTERNODE_HMAC = "Internode-HMAC";
public static final String INTERNODE_TIMESTAMP = "Internode-Timestamp";
public static final String SIGNATURE_ALGO = "HmacSHA1";
private InternalApiSignatureKeyGenerator _keyGenerator;
/**
* Set key generator
*
* @see SignatureKeyGenerator
*/
public void setKeyGenerator(InternalApiSignatureKeyGenerator keyGenerator) {
_keyGenerator = keyGenerator;
}
/**
* Verifies signature on the request using the specified signature key type
*
* @param type specifies the type of key to use for verification (vdc or internal api)
* @param req
* @return true if the signature is good, false otherwise
*/
protected boolean verifySignature(HttpServletRequest req, SignatureKeyType type) {
// To Do - add more fields to signature
StringBuilder buf = new StringBuilder(req.getRequestURL().toString().toLowerCase());
if (req.getQueryString() != null) {
buf.append("?" + req.getQueryString().toLowerCase());
}
String timestamp = req.getHeader(INTERNODE_TIMESTAMP);
if (timestamp != null && !timestamp.isEmpty()) {
buf.append(req.getHeader(INTERNODE_TIMESTAMP));
} else {
return false;
}
_log.debug("buf: " + buf.toString());
String headerSignature = req.getHeader(INTERNODE_HMAC);
if (!trySignature(buf.toString(), headerSignature, type)) {
_log.info("Failed with signature key type {}. Reloading cached keys and trying again", type.toString());
_keyGenerator.loadKeys();
return trySignature(buf.toString(), headerSignature, type);
}
return true;
}
/**
* Attempts to validate signature of given type
*
* @param buf the buffer to validate
* @param headerSignature the header signature to compare to
* @param type the type of key (vdc or internal api)
* @return
*/
private boolean trySignature(String buf, String headerSignature, SignatureKeyType type) {
String signature = _keyGenerator.sign(buf.toString(), type);
_log.debug("signature: " + (signature != null ? signature : "null"));
_log.debug("headerSignature: " + (headerSignature != null ? headerSignature : "null"));
if (StringUtils.isNotBlank(headerSignature) && StringUtils.isNotBlank(signature) &&
headerSignature.equals(signature)) {
return true;
}
return false;
}
/**
* Verifies signature on the request using internal api key
*
* @param req
* @return true if the signature is good, false otherwise
*/
protected boolean verifySignature(HttpServletRequest req) {
return verifySignature(req, SignatureKeyType.INTERNAL_API);
}
}