// DigestAuthPrincipal.java // $Id: DigestAuthPrincipal.java,v 1.5 1999/06/18 12:48:25 ylafon Exp $ // (c) COPYRIGHT MIT, INRIA and Keio, 1999. // Please first read the full copyright statement in file COPYRIGHT.html package org.w3c.jigsaw.acl; import java.security.Principal; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.w3c.jigsaw.http.Request; import org.w3c.www.http.HttpCredential; import org.w3c.util.StringUtils; /** * @version $Revision: 1.5 $ * @author Benoît Mahé (bmahe@w3.org) */ public class DigestAuthPrincipal extends HTTPPrincipal { String dac_user = null; String dac_realm = null; String dac_nonce = null; String dac_uri = null; String dac_response = null; String dac_algorithm = null; String dac_method = null; String nonce = null; String old_nonce = null; String algo = null; boolean stale = false; boolean no_user = false; public boolean isStale() { return stale; } public boolean equals(Object another) { if (no_user) return false; if (another instanceof AclPrincipal) { AclPrincipal aclp = (AclPrincipal) another; String username = aclp.getName(); String realm = aclp.getRealm(); String passwd = aclp.getPassword(); if (!dac_user.equals(username)) return false; if (!dac_realm.equals(realm)) return false; if (dac_algorithm != null && !dac_algorithm.equals(this.algo)) return false; if (!dac_nonce.equals(this.nonce)) { if (!dac_nonce.equals(this.old_nonce)) { // check if the user knows the right passwd String a1, a2, ha1, ha2; a1 = username + ":" + realm + ":" + passwd; a2 = dac_method + ":" + dac_uri; MessageDigest md = null; try { md = MessageDigest.getInstance(this.algo); } catch (NoSuchAlgorithmException algex) { // fatal error, can't authenticate return false; } md.update(a1.getBytes()); ha1 = StringUtils.toHexString(md.digest()); md.reset(); md.update(a2.getBytes()); ha2 = StringUtils.toHexString(md.digest()); md.reset(); String kd, hkd; // KD( H(A1), unq(nonce-value) ":" H(A2) kd = ha1 + ":" + dac_nonce + ":" + ha2; md.update(kd.getBytes()); hkd = StringUtils.toHexString(md.digest()); stale = hkd.equals(dac_response); return false; } else { stale = true; } } // basic things have been checked... now try the real thing String a1, a2, ha1, ha2; a1 = username + ":" + realm + ":" + passwd; a2 = dac_method + ":" + dac_uri; MessageDigest md = null; try { md = MessageDigest.getInstance(this.algo); } catch (NoSuchAlgorithmException algex) { // fatal error, can't authenticate return false; } md.update(a1.getBytes()); ha1 = StringUtils.toHexString(md.digest()); md.reset(); md.update(a2.getBytes()); ha2 = StringUtils.toHexString(md.digest()); md.reset(); String kd, hkd; if (stale) // KD( H(A1), unq(nonce-value) ":" H(A2) kd = ha1 + ":" + old_nonce + ":" + ha2; else kd = ha1 + ":" + nonce + ":" + ha2; md.update(kd.getBytes()); hkd = StringUtils.toHexString(md.digest()); if (!hkd.equals(dac_response)) return false; // yeah!!! return true; } else if (another instanceof DigestAuthPrincipal) { return false; } return false; } public String toString() { if (dac_user != null) return dac_user; return "Digest"; } public int hashCode() { if (dac_nonce != null) return dac_nonce.hashCode(); else return -1; } public String getName() { return dac_user; } public DigestAuthPrincipal(Request request, String nonce, String old_nonce, String algo) throws InvalidAuthException { super(request); HttpCredential credential = (request.isProxy() ? request.getProxyAuthorization() : request.getAuthorization()); if ((credential == null) || ( ! credential.getScheme().equalsIgnoreCase("Digest"))) { no_user = true; } else { no_user = false; dac_user = credential.getAuthParameter("username"); dac_uri = credential.getAuthParameter("uri"); dac_response = credential.getAuthParameter("response"); dac_realm = credential.getAuthParameter("realm"); dac_method = request.getMethod(); dac_nonce = credential.getAuthParameter("nonce"); this.nonce = nonce; this.old_nonce = old_nonce; this.algo = algo; if (dac_user == null || dac_uri == null || dac_response == null || dac_realm == null) { String msg = ("Invalid authentication header"); throw new InvalidAuthException(msg); } } } public DigestAuthPrincipal(Request request) throws InvalidAuthException { super(request); throw new InvalidAuthException("Bad call for authentification"); } }