}
void validateAndDecode(String entryPointKey, String expectedRealm) throws BadCredentialsException {
// Check all required parameters were supplied (ie RFC 2069)
if ((username == null) || (realm == null) || (nonce == null) || (uri == null) || (response == null)) {
throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.missingMandatory",
new Object[]{section212response}, "Missing mandatory digest value; received header {0}"));
}
// Check all required parameters for an "auth" qop were supplied (ie RFC 2617)
if ("auth".equals(qop)) {
if ((nc == null) || (cnonce == null)) {
if (logger.isDebugEnabled()) {
logger.debug("extracted nc: '" + nc + "'; cnonce: '" + cnonce + "'");
}
throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.missingAuth",
new Object[]{section212response}, "Missing mandatory digest value; received header {0}"));
}
}
// Check realm name equals what we expected
if (!expectedRealm.equals(realm)) {
throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.incorrectRealm",
new Object[]{realm, expectedRealm},
"Response realm name '{0}' does not match system realm name of '{1}'"));
}
// Check nonce was Base64 encoded (as sent by DigestAuthenticationEntryPoint)
if (!Base64.isBase64(nonce.getBytes())) {
throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceEncoding",
new Object[]{nonce}, "Nonce is not encoded in Base64; received nonce {0}"));
}
// Decode nonce from Base64
// format of nonce is:
// base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
String nonceAsPlainText = new String(Base64.decode(nonce.getBytes()));
String[] nonceTokens = StringUtils.delimitedListToStringArray(nonceAsPlainText, ":");
if (nonceTokens.length != 2) {
throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceNotTwoTokens",
new Object[]{nonceAsPlainText}, "Nonce should have yielded two tokens but was {0}"));
}
// Extract expiry time from nonce
try {
nonceExpiryTime = new Long(nonceTokens[0]).longValue();
} catch (NumberFormatException nfe) {
throw new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceNotNumeric",
new Object[]{nonceAsPlainText},
"Nonce token should have yielded a numeric first token, but was {0}"));
}
// Check signature of nonce matches this expiry time
String expectedNonceSignature = DigestAuthUtils.md5Hex(nonceExpiryTime + ":" + entryPointKey);
if (!expectedNonceSignature.equals(nonceTokens[1])) {
new BadCredentialsException(messages.getMessage("DigestAuthenticationFilter.nonceCompromised",
new Object[]{nonceAsPlainText}, "Nonce token compromised {0}"));
}
}