/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the license at
* https://glassfish.dev.java.net/public/CDDLv1.0.html or
* glassfish/bootstrap/legal/CDDLv1.0.txt.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at glassfish/bootstrap/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* you own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Copyright (c) Ericsson AB, 2004-2007. All rights reserved.
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
*/
package org.jvnet.glassfish.comms.security.auth.impl;
import static com.sun.enterprise.security.auth.digest.api.Constants.*;
import com.sun.enterprise.security.auth.digest.api.DigestAlgorithmParameter;
import com.sun.enterprise.security.auth.digest.impl.DigestAlgorithmParameterImpl;
import com.sun.enterprise.security.auth.digest.impl.KeyDigestAlgoParamImpl;
import com.sun.enterprise.security.auth.digest.impl.NestedDigestAlgoParamImpl;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletInputStream;
import javax.servlet.sip.SipServletRequest;
/**
*
* @author K.Venugopal@sun.com
*/
public class SipDigestParamGenerator {
protected String userName = null;
protected String realmName = null;
protected String nOnce = null;
protected String nc = null;
protected String cnonce = null;
protected String qop = null;
protected String uri = null;
protected String response = null;
protected String opaque = null;
protected String method = null;
protected byte[] entityBody = null;
protected String algorithm = "MD5";
private DigestAlgorithmParameter secret = null;
private DigestAlgorithmParameter key = null;
private Properties values = null;
public SipDigestParamGenerator() {
}
public DigestAlgorithmParameter[] generateParameters(
AlgorithmParameterSpec param) throws InvalidAlgorithmParameterException {
SipServletRequest request = null;
if (param instanceof SipAlgorithmParamImpl) {
request = ((SipAlgorithmParamImpl) param).getRequest();
} else {
throw new InvalidAlgorithmParameterException(param.getClass().toString());
}
boolean isProxy = ((SipAlgorithmParamImpl) param).isProxy();
List<String> params = null;
AuthHeaderProcessor ahp = new AuthHeaderProcessor();
if (!isProxy) {
params = ahp.getHeaderValues(request, "Authorization");
} else {
params = ahp.getHeaderValues(request, "Proxy-Authorization");
}
if (params == null) {
return null;
}
method = request.getMethod();
boolean matchedRealm = false;
String configuredRealm = ((SipAlgorithmParamImpl) param).getRealm();
Iterator<String> itr = params.iterator();
HeaderParser dhp = new HeaderParser();
while (itr.hasNext()) {
String value = itr.next();
if (matchedRealm) {
break;
} else {
userName = null;
realmName = null;
nOnce = null;
nc = null;
cnonce = null;
qop = null;
uri = null;
response = null;
}
values = dhp.parse(value);
realmName = values.getProperty("realm");
if (realmName != null && realmName.equals(configuredRealm)) {
matchedRealm = true;
}
userName = values.getProperty("username");
nc = values.getProperty("nc");
qop = values.getProperty("qop");
uri = values.getProperty("uri");
response = values.getProperty("response");
nOnce = values.getProperty("nonce");
cnonce = values.getProperty("cnonce");
}
ServletInputStream sis = null;
if ("auth-int".equals(qop)) {
try {
sis = request.getInputStream();
java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
while (true) {
byte[] data = new byte[1024];
int len = sis.read(data, 0, 1023);
if (len == -1) {
break;
}
bos.write(data, 0, len);
}
entityBody = bos.toByteArray();
if (entityBody == null) {
entityBody = "".getBytes();
}
} catch (IOException ex) {
Logger.getLogger("global").log(Level.SEVERE, null, ex);
} finally {
try {
sis.close();
} catch (IOException ex) {
Logger.getLogger("global").log(Level.SEVERE, null, ex);
}
}
}
if ((userName == null) || (realmName == null) || (nOnce == null) ||
(uri == null) || (response == null)) {
return null;
}
key = getA1();
DigestAlgorithmParameter a2 = getA2();
DigestAlgorithmParameterImpl p1 = new DigestAlgorithmParameterImpl(NONCE,
nOnce.getBytes());
com.sun.enterprise.security.auth.digest.api.DigestAlgorithmParameter[] list =
null;
if ("auth-int".equals(qop) || "auth".equals(qop)) {
DigestAlgorithmParameterImpl p2 = new DigestAlgorithmParameterImpl(NONCE_COUNT,
nc.getBytes());
DigestAlgorithmParameterImpl p3 = new DigestAlgorithmParameterImpl(CNONCE,
cnonce.getBytes());
DigestAlgorithmParameterImpl p4 = new DigestAlgorithmParameterImpl(QOP,
qop.getBytes());
list = new DigestAlgorithmParameter[5];
list[0] = p1;
list[1] = p2;
list[2] = p3;
list[3] = p4;
list[4] = (DigestAlgorithmParameter) a2;
} else {
list = new DigestAlgorithmParameter[2];
list[0] = p1;
list[1] = (DigestAlgorithmParameter) a2;
}
secret = new DigestAlgorithmParameterImpl(RESPONSE, response.getBytes());
com.sun.enterprise.security.auth.digest.api.DigestAlgorithmParameter[] data =
new DigestAlgorithmParameter[3];
data[0] = new NestedDigestAlgoParamImpl(DATA, list);
data[1] = secret;
data[2] = (DigestAlgorithmParameter) key;
return data;
}
protected Properties getParsedValues(){
return values;
}
protected DigestAlgorithmParameter getA1() {
return new KeyDigestAlgoParamImpl(algorithm, userName, realmName);
}
protected DigestAlgorithmParameter getA2() {
DigestAlgorithmParameterImpl p1 = new DigestAlgorithmParameterImpl(METHOD,
method.getBytes());
DigestAlgorithmParameterImpl p2 = new DigestAlgorithmParameterImpl(URI,
uri.getBytes());
if ("auth".equals(qop) || qop == null) {
DigestAlgorithmParameterImpl[] list = new DigestAlgorithmParameterImpl[2];
list[0] = p1;
list[1] = p2;
NestedDigestAlgoParamImpl a2 = new NestedDigestAlgoParamImpl(algorithm,
A2, list);
return a2;
} else if ("auth-int".equals(qop)) {
AlgorithmParameterSpec[] list = new AlgorithmParameterSpec[3];
DigestAlgorithmParameterImpl p3 = new DigestAlgorithmParameterImpl("enity-body",
algorithm, entityBody);
list[0] = p1;
list[1] = p2;
list[2] = p3;
NestedDigestAlgoParamImpl a2 = new NestedDigestAlgoParamImpl(algorithm,
A2, list);
return a2;
}
return null;
}
protected static String removeQuotes(String quotedString) {
return removeQuotes(quotedString, false);
}
protected static String removeQuotes(String quotedString,
boolean quotesRequired) {
//support both quoted and non-quoted
if ((quotedString.length() > 0) && (quotedString.charAt(0) != '"') &&
!quotesRequired) {
return quotedString;
} else if (quotedString.length() > 2) {
return quotedString.substring(1, quotedString.length() - 1);
} else {
return new String();
}
}
private void reset() {
userName = null;
realmName = null;
nOnce = null;
nc = null;
cnonce = null;
qop = null;
uri = null;
response = null;
opaque = null;
entityBody = null;
}
}