Annotation of java/classes/org/w3c/jigsaw/acl/DigestAuthPrincipal.java, revision 1.9
1.1 bmahe 1: // DigestAuthPrincipal.java
1.9 ! ylafon 2: // $Id: DigestAuthPrincipal.java,v 1.8 2005/02/18 17:32:40 ylafon Exp $
1.1 bmahe 3: // (c) COPYRIGHT MIT, INRIA and Keio, 1999.
4: // Please first read the full copyright statement in file COPYRIGHT.html
1.6 ylafon 5:
1.1 bmahe 6: package org.w3c.jigsaw.acl;
7:
1.8 ylafon 8: import java.io.UnsupportedEncodingException;
1.2 bmahe 9: import java.security.MessageDigest;
10: import java.security.NoSuchAlgorithmException;
1.1 bmahe 11: import org.w3c.jigsaw.http.Request;
1.9 ! ylafon 12: import org.w3c.util.StringUtils;
1.2 bmahe 13: import org.w3c.www.http.HttpCredential;
1.1 bmahe 14:
15: /**
1.9 ! ylafon 16: * @author Benoît Mahé (bmahe@w3.org)
! 17: * This algorithm used is based on RFC 2069
! 18: * @version $Revision: 1.8 $
1.1 bmahe 19: */
1.9 ! ylafon 20: public class DigestAuthPrincipal extends HTTPPrincipal {
1.6 ylafon 21:
1.8 ylafon 22: protected
1.9 ! ylafon 23: String dac_user = null;
! 24: String dac_realm = null;
! 25: String dac_nonce = null;
! 26: String dac_uri = null;
! 27: String dac_response = null;
1.2 bmahe 28: String dac_algorithm = null;
1.9 ! ylafon 29: String dac_method = null;
! 30: String nonce = null;
! 31: String old_nonce = null;
! 32: String algo = null;
! 33: boolean stale = false;
! 34: boolean no_user = false;
1.2 bmahe 35:
1.1 bmahe 36: public boolean isStale() {
1.9 ! ylafon 37: return stale;
1.1 bmahe 38: }
1.9 ! ylafon 39:
1.8 ylafon 40: /**
41: * Check that the challenge matches with the provided nonce
1.9 ! ylafon 42: *
1.8 ylafon 43: * @return true if it matches
44: */
1.9 ! ylafon 45: private boolean checkDigest2069(String username, String realm,
! 46: String password, String nonce) {
! 47: // check if the user knows the right passwd
! 48: String a1, a2, ha1, ha2;
! 49: StringBuilder sb = new StringBuilder(256);
! 50: // a1 = unq(username-value) ":" unq(realm-value) ":" passwd
! 51: sb.append(username).append(':').append(realm);
! 52: sb.append(':').append(password);
! 53: a1 = sb.toString();
! 54: // A2 = Method ":" digest-uri-value
! 55: sb = new StringBuilder(256);
! 56: sb.append(dac_method).append(':').append(dac_uri);
! 57: a2 = sb.toString();
! 58: MessageDigest md = null;
! 59: try {
! 60: md = MessageDigest.getInstance(this.algo);
! 61: } catch (NoSuchAlgorithmException algex) {
! 62: // fatal error, can't authenticate
! 63: return false;
! 64: }
! 65: try {
! 66: md.update(a1.getBytes("ISO-8859-1"));
! 67: ha1 = StringUtils.toHexString(md.digest());
! 68: md.reset();
! 69: md.update(a2.getBytes("ISO-8859-1"));
! 70: ha2 = StringUtils.toHexString(md.digest());
! 71: md.reset();
! 72: String kd, hkd;
! 73: // KD( H(A1), unq(nonce-value) ":" H(A2)
! 74: sb = new StringBuilder(256);
! 75: sb.append(ha1).append(':').append(nonce).append(':').append(ha2);
! 76: kd = sb.toString();
! 77: md.update(kd.getBytes("ISO-8859-1"));
! 78: hkd = StringUtils.toHexString(md.digest());
! 79: return hkd.equals(dac_response);
! 80: } catch (UnsupportedEncodingException ex) {
! 81: // in case iso-8859-1 is not known...
! 82: }
! 83: return false;
1.8 ylafon 84: }
1.9 ! ylafon 85:
1.1 bmahe 86: public boolean equals(Object another) {
1.9 ! ylafon 87: if (no_user)
! 88: return false;
! 89: if (another instanceof AclPrincipal) {
! 90: AclPrincipal aclp = (AclPrincipal) another;
! 91: String username = aclp.getName();
! 92: String realm = aclp.getRealm();
! 93: String passwd = aclp.getPassword();
! 94:
! 95: if (!dac_user.equals(username))
! 96: return false;
! 97: if (!dac_realm.equals(realm))
! 98: return false;
! 99: if (dac_algorithm != null && !dac_algorithm.equals(this.algo))
! 100: return false;
! 101: // are we using the current nonce?
! 102: if (!dac_nonce.equals(this.nonce)) {
! 103: // no, is it the old one?
! 104: if (dac_nonce.equals(this.old_nonce)) {
! 105: // yes, does it matches?
! 106: if (checkDigest2069(username, realm, passwd, old_nonce)) {
! 107: // it doesn't mean that we are validating an old nonce
! 108: // but it is a trick, allowing two nonces at the same
! 109: // time to populate "AuthenticationInfo" with the
! 110: // next nonce.
! 111: stale = true;
! 112: return true;
! 113: }
! 114: } else {
! 115: // reject but mark as atale if auth is ok with nonce.
! 116: if (checkDigest2069(username, realm, passwd, dac_nonce)) {
! 117: stale = true;
! 118: }
! 119: }
! 120: return false;
! 121: }
! 122: return checkDigest2069(username, realm, passwd, nonce);
! 123: } else if (another instanceof DigestAuthPrincipal) {
! 124: return false;
! 125: }
! 126: return false;
1.1 bmahe 127: }
128:
129: public String toString() {
1.9 ! ylafon 130: if (dac_user != null)
! 131: return dac_user;
! 132: return "Digest";
1.1 bmahe 133: }
134:
135: public int hashCode() {
1.9 ! ylafon 136: if (dac_nonce != null)
! 137: return dac_nonce.hashCode();
! 138: else return -1;
1.1 bmahe 139: }
140:
141: public String getName() {
1.9 ! ylafon 142: return dac_user;
1.1 bmahe 143: }
144:
1.9 ! ylafon 145: public DigestAuthPrincipal(Request request,
! 146: String nonce,
! 147: String old_nonce,
! 148: String algo)
! 149: throws InvalidAuthException {
! 150: super(request);
! 151: HttpCredential credential = (request.isProxy()
! 152: ? request.getProxyAuthorization()
! 153: : request.getAuthorization());
! 154: if ((credential == null) ||
! 155: (!credential.getScheme().equalsIgnoreCase("Digest"))) {
! 156: no_user = true;
! 157: } else {
! 158: no_user = false;
! 159: dac_user = credential.getAuthParameter("username");
! 160: dac_uri = credential.getAuthParameter("uri");
! 161: dac_response = credential.getAuthParameter("response");
! 162: dac_realm = credential.getAuthParameter("realm");
! 163: dac_method = request.getMethod();
! 164: dac_nonce = credential.getAuthParameter("nonce");
! 165: this.nonce = nonce;
! 166: this.old_nonce = old_nonce;
! 167: this.algo = algo;
! 168: if (dac_user == null || dac_uri == null || dac_response == null ||
! 169: dac_realm == null) {
! 170: String msg = ("Invalid authentication header");
! 171: throw new InvalidAuthException(msg);
! 172: }
! 173: }
1.1 bmahe 174: }
175:
1.5 ylafon 176: public DigestAuthPrincipal(Request request)
1.9 ! ylafon 177: throws InvalidAuthException {
! 178: super(request);
! 179: throw new InvalidAuthException("Bad call for authentification");
1.5 ylafon 180: }
1.8 ylafon 181:
182: protected DigestAuthPrincipal(Request request, String internal)
1.9 ! ylafon 183: throws InvalidAuthException {
! 184: super(request);
1.8 ylafon 185: }
1.1 bmahe 186: }
Webmaster