version 1.8, 2005/02/18 17:32:40
|
version 1.9, 2013/10/18 13:42:11
|
Line 6
|
Line 6
|
package org.w3c.jigsaw.acl; |
package org.w3c.jigsaw.acl; |
|
|
import java.io.UnsupportedEncodingException; |
import java.io.UnsupportedEncodingException; |
import java.security.Principal; |
|
import java.security.MessageDigest; |
import java.security.MessageDigest; |
import java.security.NoSuchAlgorithmException; |
import java.security.NoSuchAlgorithmException; |
|
|
import org.w3c.jigsaw.http.Request; |
import org.w3c.jigsaw.http.Request; |
import org.w3c.www.http.HttpCredential; |
|
import org.w3c.util.StringUtils; |
import org.w3c.util.StringUtils; |
|
import org.w3c.www.http.HttpCredential; |
|
|
/** |
/** |
|
* @author Benoît Mahé (bmahe@w3.org) |
|
* This algorithm used is based on RFC 2069 |
* @version $Revision$ |
* @version $Revision$ |
* @author Benoît Mahé (bmahe@w3.org) |
|
* This algorithm used is based on RFC 2069 |
|
*/ |
*/ |
public class DigestAuthPrincipal extends HTTPPrincipal { |
public class DigestAuthPrincipal extends HTTPPrincipal { |
|
|
protected |
protected |
String dac_user = null; |
String dac_user = null; |
String dac_realm = null; |
String dac_realm = null; |
String dac_nonce = null; |
String dac_nonce = null; |
String dac_uri = null; |
String dac_uri = null; |
String dac_response = null; |
String dac_response = null; |
String dac_algorithm = null; |
String dac_algorithm = null; |
String dac_method = null; |
String dac_method = null; |
String nonce = null; |
String nonce = null; |
String old_nonce = null; |
String old_nonce = null; |
String algo = null; |
String algo = null; |
boolean stale = false; |
boolean stale = false; |
boolean no_user = false; |
boolean no_user = false; |
|
|
public boolean isStale() { |
public boolean isStale() { |
return stale; |
return stale; |
} |
} |
|
|
/** |
/** |
* Check that the challenge matches with the provided nonce |
* Check that the challenge matches with the provided nonce |
|
* |
* @return true if it matches |
* @return true if it matches |
*/ |
*/ |
private boolean checkDigest2069(String username, String realm , |
private boolean checkDigest2069(String username, String realm, |
String password, String nonce) { |
String password, String nonce) { |
// check if the user knows the right passwd |
// check if the user knows the right passwd |
String a1, a2, ha1, ha2; |
String a1, a2, ha1, ha2; |
StringBuffer sb = new StringBuffer(256); |
StringBuilder sb = new StringBuilder(256); |
// a1 = unq(username-value) ":" unq(realm-value) ":" passwd |
// a1 = unq(username-value) ":" unq(realm-value) ":" passwd |
sb.append(username).append(':').append(realm); |
sb.append(username).append(':').append(realm); |
sb.append(':').append(password); |
sb.append(':').append(password); |
a1 = sb.toString(); |
a1 = sb.toString(); |
// A2 = Method ":" digest-uri-value |
// A2 = Method ":" digest-uri-value |
sb = new StringBuffer(256); |
sb = new StringBuilder(256); |
sb.append(dac_method).append(':').append(dac_uri); |
sb.append(dac_method).append(':').append(dac_uri); |
a2 = sb.toString(); |
a2 = sb.toString(); |
MessageDigest md = null; |
MessageDigest md = null; |
try { |
try { |
md = MessageDigest.getInstance(this.algo); |
md = MessageDigest.getInstance(this.algo); |
} catch (NoSuchAlgorithmException algex) { |
} catch (NoSuchAlgorithmException algex) { |
// fatal error, can't authenticate |
// fatal error, can't authenticate |
return false; |
return false; |
} |
} |
try { |
try { |
md.update(a1.getBytes("ISO-8859-1")); |
md.update(a1.getBytes("ISO-8859-1")); |
ha1 = StringUtils.toHexString(md.digest()); |
ha1 = StringUtils.toHexString(md.digest()); |
md.reset(); |
md.reset(); |
md.update(a2.getBytes("ISO-8859-1")); |
md.update(a2.getBytes("ISO-8859-1")); |
ha2 = StringUtils.toHexString(md.digest()); |
ha2 = StringUtils.toHexString(md.digest()); |
md.reset(); |
md.reset(); |
String kd, hkd; |
String kd, hkd; |
// KD( H(A1), unq(nonce-value) ":" H(A2) |
// KD( H(A1), unq(nonce-value) ":" H(A2) |
sb = new StringBuffer(256); |
sb = new StringBuilder(256); |
sb.append(ha1).append(':').append(nonce).append(':').append(ha2); |
sb.append(ha1).append(':').append(nonce).append(':').append(ha2); |
kd = sb.toString(); |
kd = sb.toString(); |
md.update(kd.getBytes("ISO-8859-1")); |
md.update(kd.getBytes("ISO-8859-1")); |
hkd = StringUtils.toHexString(md.digest()); |
hkd = StringUtils.toHexString(md.digest()); |
return hkd.equals(dac_response); |
return hkd.equals(dac_response); |
} catch (UnsupportedEncodingException ex) { |
} catch (UnsupportedEncodingException ex) { |
// in case iso-8859-1 is not known... |
// in case iso-8859-1 is not known... |
} |
} |
return false; |
return false; |
} |
} |
|
|
public boolean equals(Object another) { |
public boolean equals(Object another) { |
if (no_user) |
if (no_user) |
return false; |
return false; |
if (another instanceof AclPrincipal) { |
if (another instanceof AclPrincipal) { |
AclPrincipal aclp = (AclPrincipal) another; |
AclPrincipal aclp = (AclPrincipal) another; |
String username = aclp.getName(); |
String username = aclp.getName(); |
String realm = aclp.getRealm(); |
String realm = aclp.getRealm(); |
String passwd = aclp.getPassword(); |
String passwd = aclp.getPassword(); |
|
|
if (!dac_user.equals(username)) |
if (!dac_user.equals(username)) |
return false; |
return false; |
if (!dac_realm.equals(realm)) |
if (!dac_realm.equals(realm)) |
return false; |
return false; |
if (dac_algorithm != null && !dac_algorithm.equals(this.algo)) |
if (dac_algorithm != null && !dac_algorithm.equals(this.algo)) |
return false; |
return false; |
// are we using the current nonce? |
// are we using the current nonce? |
if (!dac_nonce.equals(this.nonce)) { |
if (!dac_nonce.equals(this.nonce)) { |
// no, is it the old one? |
// no, is it the old one? |
if (dac_nonce.equals(this.old_nonce)) { |
if (dac_nonce.equals(this.old_nonce)) { |
// yes, does it matches? |
// yes, does it matches? |
if (checkDigest2069(username, realm, passwd, old_nonce)) { |
if (checkDigest2069(username, realm, passwd, old_nonce)) { |
// it doesn't mean that we are validating an old nonce |
// it doesn't mean that we are validating an old nonce |
// but it is a trick, allowing two nonces at the same |
// but it is a trick, allowing two nonces at the same |
// time to populate "AuthenticationInfo" with the |
// time to populate "AuthenticationInfo" with the |
// next nonce. |
// next nonce. |
stale = true; |
stale = true; |
return true; |
return true; |
} |
} |
} else { |
} else { |
// reject but mark as atale if auth is ok with nonce. |
// reject but mark as atale if auth is ok with nonce. |
if (checkDigest2069(username, realm, passwd, dac_nonce)) { |
if (checkDigest2069(username, realm, passwd, dac_nonce)) { |
stale = true; |
stale = true; |
} |
} |
} |
} |
return false; |
return false; |
} |
} |
return checkDigest2069(username, realm, passwd, nonce); |
return checkDigest2069(username, realm, passwd, nonce); |
} else if (another instanceof DigestAuthPrincipal) { |
} else if (another instanceof DigestAuthPrincipal) { |
return false; |
return false; |
} |
} |
return false; |
return false; |
} |
} |
|
|
public String toString() { |
public String toString() { |
if (dac_user != null) |
if (dac_user != null) |
return dac_user; |
return dac_user; |
return "Digest"; |
return "Digest"; |
} |
} |
|
|
public int hashCode() { |
public int hashCode() { |
if (dac_nonce != null) |
if (dac_nonce != null) |
return dac_nonce.hashCode(); |
return dac_nonce.hashCode(); |
else return -1; |
else return -1; |
} |
} |
|
|
public String getName() { |
public String getName() { |
return dac_user; |
return dac_user; |
} |
} |
|
|
public DigestAuthPrincipal(Request request, |
public DigestAuthPrincipal(Request request, |
String nonce, |
String nonce, |
String old_nonce, |
String old_nonce, |
String algo) |
String algo) |
throws InvalidAuthException |
throws InvalidAuthException { |
{ |
super(request); |
super(request); |
HttpCredential credential = (request.isProxy() |
HttpCredential credential = (request.isProxy() |
? request.getProxyAuthorization() |
? request.getProxyAuthorization() |
: request.getAuthorization()); |
: request.getAuthorization()); |
if ((credential == null) || |
if ((credential == null) || |
(!credential.getScheme().equalsIgnoreCase("Digest"))) { |
( ! credential.getScheme().equalsIgnoreCase("Digest"))) { |
no_user = true; |
no_user = true; |
} else { |
} else { |
no_user = false; |
no_user = false; |
dac_user = credential.getAuthParameter("username"); |
dac_user = credential.getAuthParameter("username"); |
dac_uri = credential.getAuthParameter("uri"); |
dac_uri = credential.getAuthParameter("uri"); |
dac_response = credential.getAuthParameter("response"); |
dac_response = credential.getAuthParameter("response"); |
dac_realm = credential.getAuthParameter("realm"); |
dac_realm = credential.getAuthParameter("realm"); |
dac_method = request.getMethod(); |
dac_method = request.getMethod(); |
dac_nonce = credential.getAuthParameter("nonce"); |
dac_nonce = credential.getAuthParameter("nonce"); |
this.nonce = nonce; |
this.nonce = nonce; |
this.old_nonce = old_nonce; |
this.old_nonce = old_nonce; |
this.algo = algo; |
this.algo = algo; |
if (dac_user == null || dac_uri == null || dac_response == null || |
if (dac_user == null || dac_uri == null || dac_response == null || |
dac_realm == null) { |
dac_realm == null) { |
String msg = ("Invalid authentication header"); |
String msg = ("Invalid authentication header"); |
throw new InvalidAuthException(msg); |
throw new InvalidAuthException(msg); |
} |
} |
} |
} |
|
} |
} |
|
|
public DigestAuthPrincipal(Request request) |
public DigestAuthPrincipal(Request request) |
throws InvalidAuthException |
throws InvalidAuthException { |
{ |
super(request); |
super(request); |
throw new InvalidAuthException("Bad call for authentification"); |
throw new InvalidAuthException("Bad call for authentification"); |
|
} |
} |
|
|
protected DigestAuthPrincipal(Request request, String internal) |
protected DigestAuthPrincipal(Request request, String internal) |
throws InvalidAuthException |
throws InvalidAuthException { |
{ |
super(request); |
super(request); |
|
} |
} |
} |
} |