blob: f611c26532d7863f8ab6283f389afdea6623d8b1 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/*
25 * @test
26 * @bug 6287172
27 * @summary SASL + Digest-MD5, charset quoted
28 */
29
30import java.io.BufferedReader;
31import java.io.InputStreamReader;
32import java.io.IOException;
33import java.util.Map;
34import java.util.TreeMap;
35import java.util.logging.Logger;
36import javax.security.auth.callback.Callback;
37import javax.security.auth.callback.NameCallback;
38import javax.security.auth.callback.PasswordCallback;
39import javax.security.auth.callback.UnsupportedCallbackException;
40import javax.security.sasl.RealmCallback;
41import javax.security.sasl.Sasl;
42import javax.security.sasl.SaslClient;
43import javax.security.sasl.SaslException;
44import javax.security.sasl.SaslServer;
45import javax.security.auth.callback.CallbackHandler;
46import com.sun.security.auth.callback.DialogCallbackHandler;
47import com.sun.security.auth.callback.TextCallbackHandler;
48
49/*
50 * According to RFC 2831, DIGEST-MD5 servers must generate challenge strings
51 * whose charset and algorithm values are not enclosed within quotes.
52 * For example,
53 * challenge: realm="127.0.0.1",nonce="8GBOabRGeIqZB5BiaYJ1NDTuteV+D7n+qbSTH1fo",qop="auth",charset=utf-8,algorithm=md5-sess
54 */
55public class NoQuoteParams {
56
57 private static Logger logger = Logger.getLogger("global");
58 private static final String DIGEST_MD5 = "DIGEST-MD5";
59 private static final byte[] EMPTY = new byte[0];
60
61 private static CallbackHandler authCallbackHandler =
62 new SampleCallbackHandler();
63
64 public static void main(String[] args) throws Exception {
65
66 Map<String, String> props = new TreeMap<String, String>();
67 props.put(Sasl.QOP, "auth");
68
69 // client
70 SaslClient client = Sasl.createSaslClient(new String[]{ DIGEST_MD5 },
71 "user1", "xmpp", "127.0.0.1", props, authCallbackHandler);
72 if (client == null) {
73 throw new Exception("Unable to find client implementation for: " +
74 DIGEST_MD5);
75 }
76
77 byte[] response = client.hasInitialResponse()
78 ? client.evaluateChallenge(EMPTY) : EMPTY;
79 logger.info("initial: " + new String(response));
80
81 // server
82 byte[] challenge = null;
83 SaslServer server = Sasl.createSaslServer(DIGEST_MD5, "xmpp",
84 "127.0.0.1", props, authCallbackHandler);
85 if (server == null) {
86 throw new Exception("Unable to find server implementation for: " +
87 DIGEST_MD5);
88 }
89
90 if (!client.isComplete() || !server.isComplete()) {
91 challenge = server.evaluateResponse(response);
92
93 logger.info("challenge: " + new String(challenge));
94
95 if (challenge != null) {
96 response = client.evaluateChallenge(challenge);
97 }
98 }
99
100 String challengeString = new String(challenge, "UTF-8").toLowerCase();
101
102 if (challengeString.indexOf("\"md5-sess\"") > 0 ||
103 challengeString.indexOf("\"utf-8\"") > 0) {
104 throw new Exception("The challenge string's charset and " +
105 "algorithm values must not be enclosed within quotes");
106 }
107
108 client.dispose();
109 server.dispose();
110 }
111}
112
113class SampleCallbackHandler implements CallbackHandler {
114
115 public void handle(Callback[] callbacks)
116 throws java.io.IOException, UnsupportedCallbackException {
117 for (int i = 0; i < callbacks.length; i++) {
118 if (callbacks[i] instanceof NameCallback) {
119 NameCallback cb = (NameCallback)callbacks[i];
120 cb.setName(getInput(cb.getPrompt()));
121
122 } else if (callbacks[i] instanceof PasswordCallback) {
123 PasswordCallback cb = (PasswordCallback)callbacks[i];
124
125 String pw = getInput(cb.getPrompt());
126 char[] passwd = new char[pw.length()];
127 pw.getChars(0, passwd.length, passwd, 0);
128
129 cb.setPassword(passwd);
130
131 } else if (callbacks[i] instanceof RealmCallback) {
132 RealmCallback cb = (RealmCallback)callbacks[i];
133 cb.setText(getInput(cb.getPrompt()));
134
135 } else {
136 throw new UnsupportedCallbackException(callbacks[i]);
137 }
138 }
139 }
140
141 /**
142 * In real world apps, this would typically be a TextComponent or
143 * similar widget.
144 */
145 private String getInput(String prompt) throws IOException {
146 return "dummy-value";
147 }
148}