DigestClientAuthenticationpublic class DigestClientAuthentication extends Object implements AuthenticationListenerDigest Client Authentication. |
Fields Summary |
---|
private static final String | MD5MD5 value. | private static final String | MD5_SESSMD5-sess value. | private String | realmAuthorization category. | private String | algorithmAlgorithm name. | private String | uriURI to be validated. | private String | nonceNonce. | private String | methodAuthorization method. | private String | cnonceClient nonce. | private String | qopQop. | private String | nonceCountParCnonce counter value. | private Vector | credentialsCredentials containing the keys. | private static final char[] | toHexHexadecimal conversion table. |
Constructors Summary |
---|
public DigestClientAuthentication(Vector credentials)Constructor with initial credentials.
this.credentials = credentials;
/*
* need revisit
try {
rs = RecordStore.openRecordStore("pass", true);
}
catch (Exception e) {
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"exception raised: " + e.getMessage());
}
}
*/
|
Methods Summary |
---|
public AuthorizationHeader | createAuthorizationHeader(java.lang.String scheme)Creates a new AuthorizationHeader based on the newly supplied
scheme value.
if (scheme == null) {
throw new NullPointerException("null arg scheme ");
}
AuthorizationHeader auth = new AuthorizationHeader();
auth.setScheme(scheme);
return auth;
| public Request | createNewRequest(SipStack sipStack, Request originalRequest, Response response, int count)Creates a new request.
Exception ex = null;
try {
Request newRequest = (Request) originalRequest.clone();
CSeqHeader cseqHeader = newRequest.getCSeqHeader();
cseqHeader.setSequenceNumber(cseqHeader.getSequenceNumber() + 1);
// Proxy-Authenticate header:
ProxyAuthenticateHeader proxyAuthHeader =
(ProxyAuthenticateHeader)
response.getHeader(ProxyAuthenticateHeader.NAME);
// WWWAuthenticate header:
WWWAuthenticateHeader wwwAuthenticateHeader =
(WWWAuthenticateHeader)
response.getHeader(WWWAuthenticateHeader.NAME);
// Cseq header:
cseqHeader = response.getCSeqHeader();
method = cseqHeader.getMethod();
// RFC 2617, 3.2.2:
// digest-uri
// The URI from Request-URI of the Request-Line
uri = originalRequest.getRequestURI().toString();
String opaque = null;
if (proxyAuthHeader == null) {
if (wwwAuthenticateHeader == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR,
LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"ERROR: No ProxyAuthenticate header " +
"or WWWAuthenticateHeader " +
"in the response!");
}
return null;
}
algorithm = wwwAuthenticateHeader.getAlgorithm();
nonce = wwwAuthenticateHeader.getNonce();
realm = wwwAuthenticateHeader.getRealm();
if (realm == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR,
LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"ERROR: the realm is not part " +
"of the 401 response!");
}
return null;
}
qop = wwwAuthenticateHeader.getParameter("qop");
opaque = wwwAuthenticateHeader.getParameter("opaque");
} else {
algorithm = proxyAuthHeader.getAlgorithm();
nonce = proxyAuthHeader.getNonce();
realm = proxyAuthHeader.getRealm();
if (realm == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR,
LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"ERROR: the realm is not part " +
"of the 407 response!");
}
return null;
}
qop = proxyAuthHeader.getParameter("qop");
opaque = proxyAuthHeader.getParameter("opaque");
}
if (algorithm == null) {
algorithm = MD5; // default value
}
if (!algorithm.equalsIgnoreCase(MD5) &&
!algorithm.equalsIgnoreCase(MD5_SESS)) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR,
LogChannels.LC_JSR180,
"Algorithm parameter is wrong: " + algorithm);
}
return null;
}
Credentials credentials = getCredentials(realm);
if (credentials == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR,
LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"ERROR: unable to retrieve " +
"the credentials from RMS!");
}
return null;
}
if (nonce == null) {
nonce = "";
}
String digestEntityBody = null;
if (qop != null) {
cnonce = toHexString(Utils.digest(
("" + System.currentTimeMillis() + ":ETag:" +
credentials.getPassword()).getBytes()));
if (qop.equalsIgnoreCase("auth-int")) {
String entityBody =
new String(originalRequest.getRawContent());
if (entityBody == null) {
entityBody = "";
}
digestEntityBody = toHexString(
Utils.digest(entityBody.getBytes()));
}
}
AuthenticationHeader header = null;
if (proxyAuthHeader == null) {
header =
createAuthorizationHeader("Digest");
} else {
header =
createProxyAuthorizationHeader("Digest");
}
header.setParameter("username",
credentials.getUserName());
header.setParameter("realm", realm);
header.setParameter("uri", uri);
header.setParameter("algorithm", algorithm);
header.setParameter("nonce", nonce);
if (qop != null) {
// RFC 2617, 3.2.2
// qop contains a comma-separated list
// we should find "auth" or "auth-int"
Lexer qopLexer = new Lexer("qop", qop);
boolean foundAuth = false;
String currToken;
while (qopLexer.lookAhead(0) != '\0") {
currToken =
qopLexer.byteStringNoComma().toLowerCase();
if (currToken.equals("auth") ||
currToken.equals("auth-int")) {
foundAuth = true;
qop = currToken;
break;
}
}
if (!foundAuth) { // wrong qop value
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING,
LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"the digest response is null " +
"for the Authorization header!");
}
return null;
}
header.setParameter("qop", qop);
// RFC 2617, 3.2.2
header.setParameter("cnonce", cnonce);
// constructing 8LHEX
String nonceCount = Integer.toHexString(count);
nonceCountPar = "";
int lengthNonceCount = nonceCount.length();
if (lengthNonceCount < 8) {
for (int i = lengthNonceCount; i < 8; i++) {
nonceCountPar += "0";
}
}
nonceCountPar += nonceCount;
header.setParameter("nc", nonceCountPar);
}
String digestResponse =
generateResponse(
credentials.getUserName(),
credentials.getPassword(),
digestEntityBody);
if (digestResponse == null) {
if (Logging.REPORT_LEVEL <= Logging.WARNING) {
Logging.report(Logging.WARNING,
LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"the digest response is null " +
"for the Authorization header!");
}
return null;
}
header.setParameter("response", digestResponse);
if (opaque != null) {
header.setParameter("opaque", opaque);
}
newRequest.setHeader(header);
return newRequest;
} catch (ParseException pe) {
ex = pe;
} catch (javax.microedition.sip.SipException se) {
ex = se;
}
if (ex != null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"createNewRequest() " +
"exception raised: " + ex.getMessage());
}
}
return null;
| public ProxyAuthorizationHeader | createProxyAuthorizationHeader(java.lang.String scheme)Creates a new ProxyAuthorizationHeader based on the newly supplied
scheme value.
if (scheme == null) {
throw new NullPointerException("bad scheme arg");
}
ProxyAuthorizationHeader p = new ProxyAuthorizationHeader();
p.setScheme(scheme);
return p;
| private java.lang.String | generateResponse(java.lang.String userName, java.lang.String password, java.lang.String digestEntityBody)Generates the response message.
if (userName == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(): " +
"ERROR: no userName parameter");
}
return null;
}
if (realm == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(): " +
"ERROR: no realm parameter");
}
return null;
}
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(): " +
"Trying to generate a response " +
"for the user: " +
userName +
" , with " +
"the realm: " +
realm);
}
if (password == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(): " +
"ERROR: no password parameter");
}
return null;
}
if (method == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(): " +
"ERROR: no method parameter");
}
return null;
}
if (uri == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(): " +
"ERROR: no uri parameter");
}
return null;
}
if (nonce == null) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(): " +
"ERROR: no nonce parameter");
}
return null;
}
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(), userName: " +
userName + "!");
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(), realm: " + realm + "!");
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(), password: " + password + "!");
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(), uri: " + uri + "!");
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(), nonce: " + nonce + "!");
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(), method: " + method + "!");
}
// RFC 2617, 3.2.2.2
String A1 = userName + ":" + realm + ":" + password;
if (algorithm.equalsIgnoreCase(MD5_SESS)) {
byte[] A1bytes = Utils.digest(A1.getBytes());
byte[] tmp = (":" + nonce + ":" + cnonce).getBytes();
byte[] join = new byte[A1bytes.length + tmp.length];
System.arraycopy(A1bytes, 0, join, 0, A1bytes.length);
System.arraycopy(tmp, 0, join, A1bytes.length, tmp.length);
A1 = new String(join);
}
String A2 = method.toUpperCase() + ":" + uri;
// RFC 2617, 3.2.2.3 - body is empty
if (qop != null) {
if (qop.equalsIgnoreCase("auth-int")) {
A2 += ":" + digestEntityBody;
}
}
byte mdbytes[] = Utils.digest(A1.getBytes());
String HA1 = toHexString(mdbytes);
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(), HA1:" + HA1 + "!");
}
mdbytes = Utils.digest(A2.getBytes());
String HA2 = toHexString(mdbytes);
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(), HA2: " + HA2 + "!");
}
String KD = HA1 + ":" + nonce;
if (qop != null) { // RFC 2617, 3.2.2.1
KD += ":" + nonceCountPar + ":" + cnonce + ":" + qop;
}
KD += ":" + HA2;
mdbytes = Utils.digest(KD.getBytes());
String response = toHexString(mdbytes);
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"generateResponse(): " +
"response generated: " + response);
}
return response;
| public Credentials | getCredentials(java.lang.String realm)Gets the credentials to use int the authentication request.
Enumeration e = credentials.elements();
while (e.hasMoreElements()) {
Credentials credentials = (Credentials) e.nextElement();
if (credentials.getRealm().equals(realm)) {
return credentials;
}
}
return null;
/*
* need revisit
try {
byte[] recData = new byte[200];
int len;
for (int i = 1; i <= rs.getNumRecords(); i++) {
len = rs.getRecord(i, recData, 0);
String data = new String(recData, 0, len);
if (Logging.REPORT_LEVEL <= Logging.INFORMATION) {
Logging.report(Logging.INFORMATION, LogChannels.LC_JSR180,
"DigestClientAuthentication, " +
"data recovered from RMS: " + data);
}
int realmIndex = data.indexOf(":");
String rmsRealm = data.substring(0, realmIndex);
int userNameIndex = data.indexOf(":", realmIndex+1);
String userName = data.substring(realmIndex+1, userNameIndex);
if (realm.equals(rmsRealm.trim())) {
Credentials credentials =
new Credentials(realm, userName,
data.substring(userNameIndex + 1));
return credentials;
}
}
return null;
}
catch (Exception e) {
if (Logging.REPORT_LEVEL <= Logging.ERROR) {
Logging.report(Logging.ERROR, LogChannels.LC_JSR180,
"DigestClientAuthentication, getCredentials() " +
"exception raised:", e.getMessage());
}
return null;
}
*/
| public static java.lang.String | toHexString(byte[] b)Converts an array of bytes to an hexadecimal string.
int pos = 0;
char[] c = new char[b.length * 2];
for (int i = 0; i < b.length; i++) {
c[pos++] = toHex[ (b[i] >> 4) & 0x0F];
c[pos++] = toHex[b[i] & 0x0f];
}
return new String(c);
|
|