149 lines
5.4 KiB
Java
149 lines
5.4 KiB
Java
/*
|
|
* Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
|
* have any questions.
|
|
*/
|
|
|
|
/*
|
|
* @test
|
|
* @bug 6287172
|
|
* @summary SASL + Digest-MD5, charset quoted
|
|
*/
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.InputStreamReader;
|
|
import java.io.IOException;
|
|
import java.util.Map;
|
|
import java.util.TreeMap;
|
|
import java.util.logging.Logger;
|
|
import javax.security.auth.callback.Callback;
|
|
import javax.security.auth.callback.NameCallback;
|
|
import javax.security.auth.callback.PasswordCallback;
|
|
import javax.security.auth.callback.UnsupportedCallbackException;
|
|
import javax.security.sasl.RealmCallback;
|
|
import javax.security.sasl.Sasl;
|
|
import javax.security.sasl.SaslClient;
|
|
import javax.security.sasl.SaslException;
|
|
import javax.security.sasl.SaslServer;
|
|
import javax.security.auth.callback.CallbackHandler;
|
|
import com.sun.security.auth.callback.DialogCallbackHandler;
|
|
import com.sun.security.auth.callback.TextCallbackHandler;
|
|
|
|
/*
|
|
* According to RFC 2831, DIGEST-MD5 servers must generate challenge strings
|
|
* whose charset and algorithm values are not enclosed within quotes.
|
|
* For example,
|
|
* challenge: realm="127.0.0.1",nonce="8GBOabRGeIqZB5BiaYJ1NDTuteV+D7n+qbSTH1fo",qop="auth",charset=utf-8,algorithm=md5-sess
|
|
*/
|
|
public class NoQuoteParams {
|
|
|
|
private static Logger logger = Logger.getLogger("global");
|
|
private static final String DIGEST_MD5 = "DIGEST-MD5";
|
|
private static final byte[] EMPTY = new byte[0];
|
|
|
|
private static CallbackHandler authCallbackHandler =
|
|
new SampleCallbackHandler();
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
|
|
Map<String, String> props = new TreeMap<String, String>();
|
|
props.put(Sasl.QOP, "auth");
|
|
|
|
// client
|
|
SaslClient client = Sasl.createSaslClient(new String[]{ DIGEST_MD5 },
|
|
"user1", "xmpp", "127.0.0.1", props, authCallbackHandler);
|
|
if (client == null) {
|
|
throw new Exception("Unable to find client implementation for: " +
|
|
DIGEST_MD5);
|
|
}
|
|
|
|
byte[] response = client.hasInitialResponse()
|
|
? client.evaluateChallenge(EMPTY) : EMPTY;
|
|
logger.info("initial: " + new String(response));
|
|
|
|
// server
|
|
byte[] challenge = null;
|
|
SaslServer server = Sasl.createSaslServer(DIGEST_MD5, "xmpp",
|
|
"127.0.0.1", props, authCallbackHandler);
|
|
if (server == null) {
|
|
throw new Exception("Unable to find server implementation for: " +
|
|
DIGEST_MD5);
|
|
}
|
|
|
|
if (!client.isComplete() || !server.isComplete()) {
|
|
challenge = server.evaluateResponse(response);
|
|
|
|
logger.info("challenge: " + new String(challenge));
|
|
|
|
if (challenge != null) {
|
|
response = client.evaluateChallenge(challenge);
|
|
}
|
|
}
|
|
|
|
String challengeString = new String(challenge, "UTF-8").toLowerCase();
|
|
|
|
if (challengeString.indexOf("\"md5-sess\"") > 0 ||
|
|
challengeString.indexOf("\"utf-8\"") > 0) {
|
|
throw new Exception("The challenge string's charset and " +
|
|
"algorithm values must not be enclosed within quotes");
|
|
}
|
|
|
|
client.dispose();
|
|
server.dispose();
|
|
}
|
|
}
|
|
|
|
class SampleCallbackHandler implements CallbackHandler {
|
|
|
|
public void handle(Callback[] callbacks)
|
|
throws java.io.IOException, UnsupportedCallbackException {
|
|
for (int i = 0; i < callbacks.length; i++) {
|
|
if (callbacks[i] instanceof NameCallback) {
|
|
NameCallback cb = (NameCallback)callbacks[i];
|
|
cb.setName(getInput(cb.getPrompt()));
|
|
|
|
} else if (callbacks[i] instanceof PasswordCallback) {
|
|
PasswordCallback cb = (PasswordCallback)callbacks[i];
|
|
|
|
String pw = getInput(cb.getPrompt());
|
|
char[] passwd = new char[pw.length()];
|
|
pw.getChars(0, passwd.length, passwd, 0);
|
|
|
|
cb.setPassword(passwd);
|
|
|
|
} else if (callbacks[i] instanceof RealmCallback) {
|
|
RealmCallback cb = (RealmCallback)callbacks[i];
|
|
cb.setText(getInput(cb.getPrompt()));
|
|
|
|
} else {
|
|
throw new UnsupportedCallbackException(callbacks[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* In real world apps, this would typically be a TextComponent or
|
|
* similar widget.
|
|
*/
|
|
private String getInput(String prompt) throws IOException {
|
|
return "dummy-value";
|
|
}
|
|
}
|