1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $RCSfile$
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Revision$
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * $Date$
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Copyright 2003-2007 Jive Software.
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * you may not use this file except in compliance with the License.
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * You may obtain a copy of the License at
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *     http://www.apache.org/licenses/LICENSE-2.0
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Unless required by applicable law or agreed to in writing, software
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * distributed under the License is distributed on an "AS IS" BASIS,
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * See the License for the specific language governing permissions and
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * limitations under the License.
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.jivesoftware.smack.sasl;
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.XMPPException;
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.SASLAuthentication;
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.packet.Packet;
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.jivesoftware.smack.util.StringUtils;
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.IOException;
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.Map;
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.HashMap;
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.CallbackHandler;
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.UnsupportedCallbackException;
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.Callback;
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.NameCallback;
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.auth.callback.PasswordCallback;
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.sasl.RealmCallback;
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.sasl.RealmChoiceCallback;
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport de.measite.smack.Sasl;
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.sasl.SaslClient;
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport org.apache.harmony.javax.security.sasl.SaslException;
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Base class for SASL mechanisms. Subclasses must implement these methods:
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * <ul>
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *  <li>{@link #getName()} -- returns the common name of the SASL mechanism.</li>
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </ul>
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Subclasses will likely want to implement their own versions of these mthods:
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *  <li>{@link #authenticate(String, String, String)} -- Initiate authentication stanza using the
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *  deprecated method.</li>
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *  <li>{@link #authenticate(String, String, CallbackHandler)} -- Initiate authentication stanza
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *  using the CallbackHandler method.</li>
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *  <li>{@link #challengeReceived(String)} -- Handle a challenge from the server.</li>
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * </ul>
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Jay Kline
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic abstract class SASLMechanism implements CallbackHandler {
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    private SASLAuthentication saslAuthentication;
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected SaslClient sc;
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected String authenticationId;
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected String password;
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected String hostname;
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public SASLMechanism(SASLAuthentication saslAuthentication) {
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.saslAuthentication = saslAuthentication;
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Builds and sends the <tt>auth</tt> stanza to the server. Note that this method of
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * authentication is not recommended, since it is very inflexable.  Use
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * {@link #authenticate(String, String, CallbackHandler)} whenever possible.
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param username the username of the user being authenticated.
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param host     the hostname where the user account resides.
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param password the password for this account.
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws IOException If a network error occurs while authenticating.
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If a protocol error occurs or the user is not authenticated.
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void authenticate(String username, String host, String password) throws IOException, XMPPException {
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        //Since we were not provided with a CallbackHandler, we will use our own with the given
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        //information
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        //Set the authenticationID as the username, since they must be the same in this case.
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.authenticationId = username;
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.password = password;
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        this.hostname = host;
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        String[] mechanisms = { getName() };
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        Map<String,String> props = new HashMap<String,String>();
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, this);
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        authenticate();
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Builds and sends the <tt>auth</tt> stanza to the server. The callback handler will handle
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * any additional information, such as the authentication ID or realm, if it is needed.
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param username the username of the user being authenticated.
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param host     the hostname where the user account resides.
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param cbh      the CallbackHandler to obtain user information.
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws IOException If a network error occures while authenticating.
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws XMPPException If a protocol error occurs or the user is not authenticated.
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void authenticate(String username, String host, CallbackHandler cbh) throws IOException, XMPPException {
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        String[] mechanisms = { getName() };
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        Map<String,String> props = new HashMap<String,String>();
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, cbh);
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        authenticate();
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected void authenticate() throws IOException, XMPPException {
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        String authenticationText = null;
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        try {
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if(sc.hasInitialResponse()) {
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                byte[] response = sc.evaluateChallenge(new byte[0]);
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                authenticationText = StringUtils.encodeBase64(response, false);
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        } catch (SaslException e) {
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            throw new XMPPException("SASL authentication failed", e);
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Send the authentication to the server
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        getSASLAuthentication().send(new AuthMechanism(getName(), authenticationText));
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * The server is challenging the SASL mechanism for the stanza he just sent. Send a
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * response to the server's challenge.
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @param challenge a base64 encoded string representing the challenge.
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @throws IOException if an exception sending the response occurs.
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void challengeReceived(String challenge) throws IOException {
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        byte response[];
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if(challenge != null) {
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            response = sc.evaluateChallenge(StringUtils.decodeBase64(challenge));
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        } else {
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            response = sc.evaluateChallenge(new byte[0]);
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        Packet responseStanza;
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        if (response == null) {
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            responseStanza = new Response();
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        else {
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            responseStanza = new Response(StringUtils.encodeBase64(response, false));
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        // Send the authentication to the server
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        getSASLAuthentication().send(responseStanza);
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Returns the common name of the SASL mechanism. E.g.: PLAIN, DIGEST-MD5 or GSSAPI.
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * @return the common name of the SASL mechanism.
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected abstract String getName();
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    protected SASLAuthentication getSASLAuthentication() {
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        return saslAuthentication;
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     *
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        for (int i = 0; i < callbacks.length; i++) {
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (callbacks[i] instanceof NameCallback) {
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                NameCallback ncb = (NameCallback)callbacks[i];
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                ncb.setName(authenticationId);
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            } else if(callbacks[i] instanceof PasswordCallback) {
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                PasswordCallback pcb = (PasswordCallback)callbacks[i];
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                pcb.setPassword(password.toCharArray());
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            } else if(callbacks[i] instanceof RealmCallback) {
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                RealmCallback rcb = (RealmCallback)callbacks[i];
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                rcb.setText(hostname);
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            } else if(callbacks[i] instanceof RealmChoiceCallback){
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                //unused
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                //RealmChoiceCallback rccb = (RealmChoiceCallback)callbacks[i];
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            } else {
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen               throw new UnsupportedCallbackException(callbacks[i]);
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         }
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * Initiating SASL authentication by select a mechanism.
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public class AuthMechanism extends Packet {
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        final private String name;
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        final private String authenticationText;
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public AuthMechanism(String name, String authenticationText) {
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (name == null) {
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                throw new NullPointerException("SASL mechanism name shouldn't be null.");
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.name = name;
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.authenticationText = authenticationText;
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public String toXML() {
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            StringBuilder stanza = new StringBuilder();
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("<auth mechanism=\"").append(name);
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (authenticationText != null &&
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    authenticationText.trim().length() > 0) {
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                stanza.append(authenticationText);
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("</auth>");
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return stanza.toString();
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A SASL challenge stanza.
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static class Challenge extends Packet {
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        final private String data;
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public Challenge(String data) {
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.data = data;
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public String toXML() {
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            StringBuilder stanza = new StringBuilder();
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("<challenge xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (data != null &&
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    data.trim().length() > 0) {
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                stanza.append(data);
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("</challenge>");
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return stanza.toString();
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A SASL response stanza.
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public class Response extends Packet {
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        final private String authenticationText;
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public Response() {
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            authenticationText = null;
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public Response(String authenticationText) {
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (authenticationText == null || authenticationText.trim().length() == 0) {
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                this.authenticationText = null;
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            else {
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                this.authenticationText = authenticationText;
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public String toXML() {
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            StringBuilder stanza = new StringBuilder();
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("<response xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (authenticationText != null) {
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                stanza.append(authenticationText);
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("</response>");
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return stanza.toString();
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A SASL success stanza.
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static class Success extends Packet {
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        final private String data;
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public Success(String data) {
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.data = data;
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public String toXML() {
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            StringBuilder stanza = new StringBuilder();
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (data != null &&
285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    data.trim().length() > 0) {
286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                stanza.append(data);
287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("</success>");
289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return stanza.toString();
290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    /**
294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     * A SASL failure stanza.
295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen     */
296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    public static class Failure extends Packet {
297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        final private String condition;
298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public Failure(String condition) {
300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            this.condition = condition;
301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        /**
304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * Get the SASL related error condition.
305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         *
306d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         * @return the SASL related error condition.
307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen         */
308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public String getCondition() {
309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return condition;
310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        public String toXML() {
313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            StringBuilder stanza = new StringBuilder();
314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">");
315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            if (condition != null &&
316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                    condition.trim().length() > 0) {
317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen                stanza.append("<").append(condition).append("/>");
318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            }
319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            stanza.append("</failure>");
320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen            return stanza.toString();
321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen        }
322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen    }
323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
324