public void challenge(HttpServletRequest req, HttpServletResponse resp) { boolean stale = false; if (this.maintainState) { String authHeader = req.getHeader("Authorization"); if (authHeader != null) { String headerFields = authHeader.substring("Digest: ".length() - 1); String nonce = HttpUtil.extractHeaderField(headerFields, "nonce"); String opaque = HttpUtil.extractHeaderField(headerFields, "opaque"); if (nonce != null && opaque != null) { StateEntry entry = (StateEntry) this.stateMap.remove(nonce + ":" + opaque); if (entry != null) { stale = entry.isStale(); } } } } String nonce = generateNonce(); String opaque = generateOpaque(); // FIXME: Why is getRealm() deprecated? String challengeHeader = "Digest realm=\"" + this.principalStore.getRealm() + "\""; challengeHeader += ", nonce=\"" + nonce + "\""; challengeHeader += ", opaque=\"" + opaque + "\""; challengeHeader += ", stale=" + stale; challengeHeader += ", algorithm=MD5"; challengeHeader += ", qop=auth"; if (this.maintainState) { Date timestamp = new Date(); StateEntry entry = new StateEntry(null, timestamp, nonce, 1, opaque); this.stateMap.put(nonce + ":" + opaque, entry); } try { resp.setHeader("WWW-Authenticate", challengeHeader); resp.sendError(HttpServletResponse.SC_UNAUTHORIZED); } catch (IOException e) { throw new AuthenticationProcessingException( "Unable to present authentication challenge to user", e); } }
public boolean postAuthentication(HttpServletRequest req, HttpServletResponse resp) { String authHeader = req.getHeader("Authorization"); if (authHeader == null) { return false; } String headerFields = authHeader.substring("Digest: ".length() - 1); String nonce = HttpUtil.extractHeaderField(headerFields, "nonce"); String opaque = HttpUtil.extractHeaderField(headerFields, "opaque"); if (nonce == null || opaque == null) { return false; } Principal principal = SecurityContext.getSecurityContext().getPrincipal(); if (principal == null) { return false; } if (this.maintainState) { StateEntry entry = (StateEntry) this.stateMap.remove(nonce + ":" + opaque); if (entry == null) { return false; } Date timestamp = new Date(); String nextNonce = this.generateNonce(); entry.setUsername(principal.getQualifiedName()); entry.setNonce(nextNonce); entry.setTimestamp(timestamp); entry.setNonceCount(entry.getNonceCount() + 1); entry.setStale(false); this.stateMap.put(nextNonce + ":" + opaque, entry); resp.addHeader("Authentication-Info", "nextnonce=" + nextNonce); } return false; }
private AuthResult doAuthenticate( HttpServletRequest request, String uri, String response, String nc, String nonce, String cnonce, String qop, String username, String opaque) { StateEntry stateEntry = null; if (this.maintainState) { stateEntry = this.stateMap.get(nonce + ":" + opaque); if (stateEntry != null) { if (!stateEntry.getNonce().equals(nonce)) { stateEntry.setStale(true); throw new AuthenticationException( "Authentication header field 'nonce': " + nonce + " does not match expected value: " + stateEntry.getNonce()); } try { long nonceCount = Long.parseLong(nc, 16); if (nonceCount != stateEntry.getNonceCount()) { throw new AuthenticationException( "Authentication header field 'nc', value " + nc + " did not match expected value " + stateEntry.getNonceCount()); } } catch (NumberFormatException e) { throw new InvalidAuthenticationRequestException( "Authentication header field 'nc' was not a hex number: " + nc); } } } Principal principal = principalFactory.getPrincipal(username, Principal.Type.USER); if (principal == null) { throw new AuthenticationException( "Unable to authenticate principal using HTTP/Digest for request" + request + ": no principal found"); } if (!this.principalStore.validatePrincipal(principal)) { throw new AuthenticationException("Unknown principal in HTTP/Digest request: " + principal); } String componentA1 = this.principalStore.getMD5HashString(principal); if (componentA1 == null) { throw new AuthenticationException("Password hash for principal " + principal + " not found"); } String componentA2 = MD5.md5sum(request.getMethod() + ":" + uri); StringBuffer b = new StringBuffer(); b.append(componentA1); b.append(":").append(nonce); if (nc != null) b.append(":").append(nc); if (cnonce != null) b.append(":").append(cnonce); if (qop != null) b.append(":").append(qop); b.append(":").append(componentA2); String serverDigest = MD5.md5sum(b.toString()); if (this.logger.isDebugEnabled()) { this.logger.debug("client digest: '" + response + "', server digest: '" + serverDigest + "'"); } if (!serverDigest.equals(response)) { throw new AuthenticationException( "Authentication failure for principal " + principal + " (incorrect password)"); } if (this.maintainState && stateEntry == null) { stateEntry = new StateEntry(null, new Date(), nonce, 1, opaque); stateEntry.setStale(true); this.stateMap.put(nonce + ":" + opaque, stateEntry); throw new AuthenticationException("Nothing known about request " + request); } else if (this.maintainState && stateEntry != null && stateEntry.isStale()) { throw new AuthenticationException( "Stale nonce header field in authentication request: " + request); } if (this.logger.isDebugEnabled()) { this.logger.debug("Successfully authenticated principal " + principal); } return new AuthResult(principal.getQualifiedName()); }