1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19* @author Vera Y. Petrashkova
20*/
21
22package org.apache.harmony.auth.tests.javax.security.sasl;
23
24import java.io.IOException;
25import java.security.Provider;
26import java.security.Security;
27import java.util.Map;
28
29import javax.security.auth.callback.Callback;
30import javax.security.auth.callback.CallbackHandler;
31import javax.security.auth.callback.NameCallback;
32import javax.security.auth.callback.PasswordCallback;
33import javax.security.auth.callback.TextOutputCallback;
34import javax.security.auth.callback.UnsupportedCallbackException;
35import javax.security.sasl.Sasl;
36import javax.security.sasl.SaslClient;
37import javax.security.sasl.SaslClientFactory;
38import javax.security.sasl.SaslException;
39
40import junit.framework.TestCase;
41
42import org.apache.harmony.auth.tests.support.SpiEngUtils;
43
44/**
45 * Test for Sasl class
46 */
47public class Sasl3Test extends TestCase {
48    private static final String CLNTSRV = "SaslClientFactory.";
49
50    private static final String fClientClass = mySaslClientFactory.class.getName();;
51
52    private Provider [] provs;
53    private boolean initProvs;
54
55    @Override
56    protected void setUp() throws Exception {
57        super.setUp();
58        if (!initProvs) {
59            provs = Security.getProviders();
60            initProvs = true;
61        }
62        if (provs != null) {
63            for (Provider element : provs) {
64                Security.removeProvider(element.getName());
65            }
66        }
67    }
68
69    protected Provider[] mProv;
70
71    private void addProviders() {
72        for (Provider element : mProv) {
73            Security.insertProviderAt(element, 1);
74        }
75    }
76
77    /*
78     * @see TestCase#tearDown()
79     */
80    @Override
81    protected void tearDown() throws Exception {
82        super.tearDown();
83        if (mProv != null) {
84            for (Provider element : mProv) {
85                Security.removeProvider(element.getName());
86            }
87        }
88        if (provs != null) {
89            for (int i = 0; i < provs.length; i++) {
90                Security.insertProviderAt(provs[i], (i+1));
91            }
92        }
93    }
94
95    /**
96     * Test for <code>createSaslClient(String[] mechanisms,
97     *      String authanticationID, String protocol, String serverName,
98     *      Map prop, CallbackHandler cbh))</code>
99     * method Assertions: throws NullPointerException when mechanisms is null;
100     * throws SaslException when parameters (protocol, cbh, mechanisms) are
101     * wrong.
102     *
103     * All providers are previously removed and 2 new providers were added.
104     */
105    public void testCreateClient01() throws SaslException {
106        mProv = new Provider[] {
107                (new SpiEngUtils()).new MyProvider("MySaslClientProvider1",
108                        "Testing provider SaslClientFactory - 1", CLNTSRV
109                                .concat("NAME-1"), fClientClass),
110                (new SpiEngUtils()).new MyProvider("MySaslClientProvider2",
111                        "Testing provider SaslClientFactory - 2", CLNTSRV
112                                .concat("NAME-2"), fClientClass) };
113        addProviders();
114
115        CallbackHandler cbH = new cbHand();
116        try {
117            Sasl.createSaslClient(null, null, null, null, null, cbH);
118            fail("NullPointerException should be thrown when mechanisms is null");
119        } catch (NullPointerException e) {
120        }
121        try {
122            Sasl.createSaslClient(new String[] { "NAME-2" }, null, "protocol",
123                    null, null, cbH);
124            fail("SaslException should be thrown when CallbackHandler is wrong");
125        } catch (SaslException e) {
126        }
127        cbH = new cbHandN();
128        try {
129            Sasl.createSaslClient(new String[] { "NAME-1" }, null, "protocol",
130                    null, null, cbH);
131            fail("SaslException should be thrown when mechanisms is wrong");
132        } catch (SaslException e) {
133        }
134        try {
135            Sasl.createSaslClient(new String[] { "NAME-2" }, null, null, null,
136                    null, cbH);
137            fail("SaslException should be thrown when protocol is null");
138        } catch (SaslException e) {
139        }
140    }
141
142    /**
143     * Test for <code>createSaslClient(String[] mechanisms,
144     *      String authanticationID, String protocol, String serverName,
145     *      Map prop, CallbackHandler cbh))</code>
146     * method Assertions: throws NullPointerException when mechanisms is null;
147     * returns null SaslClient.
148     *
149     * All providers are previously removed.
150     */
151    public void testCreateClient02() throws SaslException {
152        try {
153            Sasl.createSaslClient(null, null, null, null, null, null);
154            fail("NullPointerException should be thrown when mechanisms is null");
155        } catch (NullPointerException e) {
156        }
157        assertNull("Not null result", Sasl.createSaslClient(
158                new String[] { "NAME-999" }, null, null, null, null, null));
159    }
160
161    /**
162     * Test for <code>createSaslClient(String[] mechanisms,
163     *      String authanticationID, String protocol, String serverName,
164     *      Map prop, CallbackHandler cbh))</code>
165     * method
166     *
167     * Assertions: returns SaslClient; throws SaslClient for NAME-1 mechanism
168     *
169     * All providers are previously removed and 2 new providers were added.
170     */
171    public void testCreateClient03() throws SaslException {
172        mProv = new Provider[] {
173                (new SpiEngUtils()).new MyProvider("MySaslClientProvider1",
174                        "Testing provider SaslClientFactory - 1", CLNTSRV
175                                .concat("NAME-1"), fClientClass),
176                (new SpiEngUtils()).new MyProvider("MySaslClientProvider2",
177                        "Testing provider SaslClientFactory - 2", CLNTSRV
178                                .concat("NAME-2"), fClientClass) };
179        addProviders();
180
181        CallbackHandler cbH = new cbHandN();
182        SaslClient saslC = Sasl.createSaslClient(new String[] { "NAME-2" },
183                null, "protocol", null, null, cbH);
184        assertNotNull("Null result", saslC);
185        try {
186            saslC.unwrap(null, 1, 1);
187            fail("SaslException sould be thrown");
188        } catch (SaslException e) {
189        }
190        assertFalse("Incorrect isComplete() result", saslC.isComplete());
191        // try to create client for wrong mechanism
192        try {
193            saslC = Sasl.createSaslClient(new String[] { "NAME-1" }, null,
194                    "protocol", null, null, cbH);
195            fail("SaslException sould be thrown");
196        } catch (SaslException e) {
197        }
198    }
199
200    /**
201     * Test for <code>createSaslClient(String[] mechanisms,
202     *      String authanticationID, String protocol, String serverName,
203     *      Map prop, CallbackHandler cbh))</code>
204     * method
205     *
206     * Assertions: returns SaslClient; throws SaslClient for NAME-1 mechanism
207     *
208     * All providers are previously removed and 1 new provider was added.
209     */
210    public void testCreateClient04() throws SaslException {
211        mProv = new Provider[] { (new SpiEngUtils()).new MyProvider(
212                "MySaslClientProvider1",
213                "Testing provider SaslClientFactory - 1", CLNTSRV
214                        .concat("NAME-1"), fClientClass) };
215        mProv[0].put(CLNTSRV.concat("NAME-2"), fClientClass);
216        addProviders();
217        CallbackHandler cbH = new cbHandN();
218        SaslClient saslC = Sasl.createSaslClient(new String[] { "NAME-2" },
219                null, "protocol", null, null, cbH);
220        assertNotNull("Null result for NAME-2", saslC);
221        assertFalse("Incorrect isComplete() result", saslC.isComplete());
222        // try to create client for wrong mechanism
223        try {
224            saslC = Sasl.createSaslClient(new String[] { "NAME-1" }, null,
225                    "protocol", null, null, cbH);
226            fail("SaslException sould be thrown");
227        } catch (SaslException e) {
228        }
229    }
230
231    /**
232     * Test for <code>createSaslClient(String[] mechanisms,
233     *      String authanticationID, String protocol, String serverName,
234     *      Map prop, CallbackHandler cbh))</code>
235     * method
236     *
237     * Assertions: return null client when there is no provider supported some
238     * mechanism returns SaslClient when incorrect mechanism is used
239     *
240     * All providers are previously removed and 2 new providers were added.
241     */
242    public void testCreateClient05() throws SaslException {
243        mProv = new Provider[] {
244                (new SpiEngUtils()).new MyProvider("MySaslClientProvider1",
245                        "Testing provider SaslClientFactory - 1", CLNTSRV
246                                .concat("NAME-2"), fClientClass.concat("Ext")),
247                (new SpiEngUtils()).new MyProvider("MySaslClientProvider2",
248                        "Testing provider SaslClientFactory - 2", CLNTSRV
249                                .concat("NAME-1"), fClientClass),
250                (new SpiEngUtils()).new MyProvider("MySaslClientProvider3",
251                        "Testing provider SaslClientFactory - 3", CLNTSRV
252                                .concat("NAME-6"), fClientClass) };
253        addProviders();
254
255        CallbackHandler cbH = new cbHandN();
256
257        SaslClient saslC;
258        // try to create SaslClient for wrong mechanism
259        // there is no provider supported NAME-77, NAME-66 mechanisms
260
261        assertNull("Not null object was created for wrong mechanism", Sasl
262                .createSaslClient(new String[] { "NAME-77", "NAME-66" }, null,
263                        "protocol", null, null, cbH));
264
265        saslC = Sasl.createSaslClient(new String[] { "NAME-2" }, null,
266                "protocol", null, null, cbH);
267        assertNotNull("Null result for NAME-2", saslC);
268        try {
269            saslC.unwrap(null, 1, 1);
270            fail("SaslException sould be thrown");
271        } catch (SaslException e) {
272        }
273        assertFalse("Incorrect isComplete() result", saslC.isComplete());
274        // NAME-1 was defined in some provider but it is supported in
275        // another provider
276        try {
277            Sasl.createSaslClient(new String[] { "NAME-1" }, null, "protocol",
278                    null, null, cbH);
279            fail("SaslException sould be thrown");
280        } catch (SaslException e) {
281        }
282        // NAME-6 and NAME-5 were defined in one provider but they are
283        // supported
284        // in another provider
285        saslC = Sasl.createSaslClient(new String[] { "NAME-6", "NAME-5" },
286                null, "protocol", null, null, cbH);
287        assertNotNull("Null result for NAME-6 and NAME-5", saslC);
288    }
289
290    /*
291     * Additional classes for creating SaslClient and SaslServer objects
292     */
293
294    public static class mySaslClientFactory implements SaslClientFactory {
295        public mySaslClientFactory() {
296            super();
297        }
298
299        public String[] getMechanismNames(Map<String, ?> prop) {
300            return new String[] { "NAME-1", "NAME-2", "NAME-3", "NAME-4" };
301        }
302
303        public SaslClient createSaslClient(String[] mech, String id,
304                String protocol, String srvName, Map<String, ?> prop, CallbackHandler hnd)
305                throws SaslException {
306            if (mech == null) {
307                throw new SaslException();
308            }
309            if ("NAME-1".equals(mech[0])) {
310                throw new SaslException("Incorrect mechanisms");
311            }
312            if (protocol == null) {
313                throw new SaslException("Protocol is null");
314            }
315            TextOutputCallback[] cb = { new TextOutputCallback(
316                    TextOutputCallback.INFORMATION, "Information") };
317            try {
318                hnd.handle(cb);
319            } catch (UnsupportedCallbackException e) {
320                throw new SaslException("Incorrect callback handlere", e);
321            } catch (IOException e) {
322                throw new SaslException("Incorrect callback handlere", e);
323            }
324            return new mySaslClient();
325        }
326
327        public class mySaslClient implements SaslClient {
328            public mySaslClient() {
329                super();
330            }
331
332            public Object getNegotiatedProperty(String s) {
333                return "";
334            }
335
336            public String getMechanismName() {
337                return "Proba";
338            }
339
340            public boolean isComplete() {
341                return false;
342            }
343
344            public boolean hasInitialResponse() {
345                return false;
346            }
347
348            public void dispose() throws SaslException {
349            }
350
351            public byte[] evaluateChallenge(byte[] challenge) throws SaslException {
352                return new byte[0];
353            }
354
355            public byte[] unwrap(byte[] incoming, int offset, int len)
356                    throws SaslException {
357                throw new SaslException();
358            }
359
360            public byte[] wrap(byte[] outgoing, int offset, int len)
361                    throws SaslException {
362                return new byte[0];
363            }
364        }
365    }
366
367    public static class mySaslClientFactoryExt extends mySaslClientFactory {
368        @Override
369        public String[] getMechanismNames(Map<String, ?> prop) {
370            return new String[] { "NAME-5", "NAME-6" };
371        }
372
373        @Override
374        public SaslClient createSaslClient(String[] mech, String id,
375                String protocol, String srvName, Map<String, ?> prop, CallbackHandler hnd)
376                throws SaslException {
377            if (mech == null) {
378                throw new SaslException();
379            }
380            return new mySaslClient();
381        }
382    }
383
384    public static class cbHand implements CallbackHandler {
385        public cbHand() {
386        }
387
388        public void handle(Callback[] callbacks) throws IOException,
389                UnsupportedCallbackException {
390            for (Callback element : callbacks) {
391                if (element instanceof NameCallback) {
392                    NameCallback nc = (NameCallback) element;
393                    nc.setName("Ok");
394                } else if (element instanceof PasswordCallback) {
395                    PasswordCallback pc = (PasswordCallback) element;
396                    System.err.print(pc.getPrompt());
397                    System.err.flush();
398                    pc.setPassword(new char[] { 'O', 'k' });
399                } else {
400                    throw new UnsupportedCallbackException(element,
401                            "Callback should be NamCallback or PasswordCallback");
402                }
403            }
404        }
405    }
406
407    public static class cbHandN implements CallbackHandler {
408        public cbHandN() {
409        }
410
411        public void handle(Callback[] callbacks) throws IOException,
412                UnsupportedCallbackException {
413            for (Callback element : callbacks) {
414                if (element instanceof TextOutputCallback) {
415                    TextOutputCallback toc = (TextOutputCallback) element;
416                    if (toc.getMessageType() != TextOutputCallback.INFORMATION) {
417                        throw new IOException("Unsupported message type: "
418                                + toc.getMessageType());
419                    }
420                } else {
421                    throw new UnsupportedCallbackException(element,
422                            "Callback should be TextOutputCallback");
423                }
424            }
425        }
426    }
427}
428