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
18package org.apache.harmony.xnet.tests.javax.net.ssl;
19
20import java.security.KeyManagementException;
21import java.security.KeyStore;
22import java.security.KeyStoreException;
23import java.security.NoSuchAlgorithmException;
24import java.security.NoSuchProviderException;
25import java.security.Provider;
26import java.security.SecureRandom;
27import java.security.Security;
28import java.security.UnrecoverableKeyException;
29
30import javax.net.ssl.KeyManager;
31import javax.net.ssl.KeyManagerFactory;
32import javax.net.ssl.SSLContext;
33import javax.net.ssl.SSLContextSpi;
34import javax.net.ssl.SSLEngine;
35import javax.net.ssl.SSLParameters;
36import javax.net.ssl.SSLPermission;
37import javax.net.ssl.SSLSessionContext;
38import javax.net.ssl.SSLServerSocketFactory;
39import javax.net.ssl.SSLSocketFactory;
40import javax.net.ssl.SSLSocket;
41import javax.net.ssl.TrustManager;
42import javax.net.ssl.TrustManagerFactory;
43
44import org.apache.harmony.security.fortress.Services;
45import org.apache.harmony.xnet.tests.support.SpiEngUtils;
46import org.apache.harmony.xnet.tests.support.MySSLContextSpi;
47import junit.framework.TestCase;
48
49/**
50 * Tests for <code>SSLContext</code> class constructors and methods.
51 */
52
53public class SSLContext1Test extends TestCase {
54
55    private static String srvSSLContext = "SSLContext";
56
57    public static String defaultProtocol = "TLS";
58
59    private static final String NotSupportMsg = "Default protocol is not supported";
60
61    private static String defaultProviderName = null;
62
63    private static Provider defaultProvider = null;
64
65    private static final String[] invalidValues = SpiEngUtils.invalidValues;
66
67    private static boolean DEFSupported = false;
68
69    private static final String NotSupportedMsg = "There is no suitable provider for SSLContext";
70
71    private static String[] validValues = new String[3];
72
73    static {
74        defaultProvider = SpiEngUtils.isSupport(defaultProtocol, srvSSLContext);
75        DEFSupported = (defaultProvider != null);
76        if (DEFSupported) {
77            defaultProviderName = (DEFSupported ? defaultProvider.getName()
78                    : null);
79            validValues[0] = defaultProtocol;
80            validValues[1] = defaultProtocol.toUpperCase();
81            validValues[2] = defaultProtocol.toLowerCase();
82        } else {
83            defaultProtocol = null;
84        }
85
86        SSLParameters staticSupportSSLParameter = new SSLParameters(new String[] {
87                "TLS_RSA_WITH_RC4_128_MD5", "TLS_RSA_WITH_RC4_128_SHA" },
88                new String[] { "TLSv1", "SSLv3" });
89
90        SSLParameters staticDefaultSSLParameter = new SSLParameters(new String[] {
91                "TLS_RSA_WITH_RC4_128_MD5", "TLS_RSA_WITH_RC4_128_SHA" },
92                new String[] { "TLSv1", "SSLv3" });
93    }
94
95    protected SSLContext[] createSSLCon() {
96        if (!DEFSupported) {
97            fail(defaultProtocol + " protocol is not supported");
98            return null;
99        }
100        SSLContext[] sslC = new SSLContext[3];
101        try {
102            sslC[0] = SSLContext.getInstance(defaultProtocol);
103            sslC[1] = SSLContext.getInstance(defaultProtocol, defaultProvider);
104            sslC[2] = SSLContext.getInstance(defaultProtocol,
105                    defaultProviderName);
106            return sslC;
107        } catch (Exception e) {
108            e.printStackTrace();
109            return null;
110        }
111    }
112
113    /**
114     * Test for <code>getInstance(String protocol)</code> method Assertion:
115     * returns SSLContext object
116     */
117    public void testSSLContext01() throws NoSuchAlgorithmException {
118        if (!DEFSupported) {
119            fail(NotSupportMsg);
120            return;
121        }
122        SSLContext sslContext;
123        for (int i = 0; i < validValues.length; i++) {
124            sslContext = SSLContext.getInstance(validValues[i]);
125            assertTrue("Not SSLContext object",
126                    sslContext instanceof SSLContext);
127            assertEquals("Invalid protocol", sslContext.getProtocol(),
128                    validValues[i]);
129        }
130    }
131
132    /**
133     * Test for <code>getInstance(String protocol)</code> method Assertion:
134     * throws NullPointerException when protocol is null; throws
135     * NoSuchAlgorithmException when protocol is not correct;
136     */
137    public void testSSLContext02() {
138        try {
139            SSLContext.getInstance(null);
140            fail("NoSuchAlgorithmException or NullPointerException should be thrown (protocol is null");
141        } catch (NoSuchAlgorithmException e) {
142        } catch (NullPointerException e) {
143        }
144        for (int i = 0; i < invalidValues.length; i++) {
145            try {
146                SSLContext.getInstance(invalidValues[i]);
147                fail("NoSuchAlgorithmException was not thrown as expected for provider: "
148                        .concat(invalidValues[i]));
149            } catch (NoSuchAlgorithmException e) {
150            }
151        }
152    }
153
154    /**
155     * Test for <code>getInstance(String protocol, String provider)</code>
156     * method Assertion: throws IllegalArgumentException when provider is null
157     * or empty
158     */
159    public void testSSLContext03() throws NoSuchProviderException,
160            NoSuchAlgorithmException {
161        if (!DEFSupported) {
162            fail(NotSupportMsg);
163            return;
164        }
165        String provider = null;
166        for (int i = 0; i < validValues.length; i++) {
167            try {
168                SSLContext.getInstance(defaultProtocol, provider);
169                fail("IllegalArgumentException must be thrown when provider is null");
170            } catch (IllegalArgumentException e) {
171            }
172            try {
173                SSLContext.getInstance(defaultProtocol, "");
174                fail("IllegalArgumentException must be thrown when provider is empty");
175            } catch (IllegalArgumentException e) {
176            }
177        }
178    }
179
180    /**
181     * Test for <code>getInstance(String protocol, String provider)</code>
182     * method Assertion: throws NullPointerException when protocol is null;
183     * throws NoSuchAlgorithmException when protocol is not correct;
184     */
185    public void testSSLContext04() throws NoSuchProviderException {
186        if (!DEFSupported) {
187            fail(NotSupportMsg);
188            return;
189        }
190        try {
191            SSLContext.getInstance(null, defaultProviderName);
192            fail("NoSuchAlgorithmException or NullPointerException should be thrown (protocol is null");
193        } catch (NoSuchAlgorithmException e) {
194        } catch (NullPointerException e) {
195        }
196        for (int i = 0; i < invalidValues.length; i++) {
197            try {
198                SSLContext.getInstance(invalidValues[i], defaultProviderName);
199                fail("NoSuchAlgorithmException was not thrown as expected (protocol: "
200                        .concat(invalidValues[i]).concat(")"));
201            } catch (NoSuchAlgorithmException e) {
202            }
203        }
204    }
205
206    /**
207     * Test for <code>getInstance(String protocol, String provider)</code>
208     * method Assertion: throws NoSuchProviderException when provider has
209     * invalid value
210     */
211    public void testSSLContext05() throws NoSuchAlgorithmException {
212        if (!DEFSupported) {
213            fail(NotSupportMsg);
214            return;
215        }
216        for (int i = 1; i < invalidValues.length; i++) {
217            for (int j = 0; j < validValues.length; j++) {
218                try {
219                    SSLContext.getInstance(validValues[j], invalidValues[i]);
220                    fail("NuSuchProviderException must be thrown (protocol: "
221                            .concat(validValues[j]).concat(" provider: ")
222                            .concat(invalidValues[i]).concat(")"));
223                } catch (NoSuchProviderException e) {
224                }
225            }
226        }
227    }
228
229    /**
230     * Test for <code>getInstance(String protocol, String provider)</code>
231     * method Assertion: returns instance of SSLContext
232     */
233    public void testSSLContext06() throws NoSuchAlgorithmException,
234            NoSuchProviderException {
235        if (!DEFSupported) {
236            fail(NotSupportMsg);
237            return;
238        }
239        SSLContext sslContext;
240        for (int i = 0; i < validValues.length; i++) {
241            sslContext = SSLContext.getInstance(validValues[i],
242                    defaultProviderName);
243            assertTrue("Not SSLContext object",
244                    sslContext instanceof SSLContext);
245            assertEquals("Invalid protocol", sslContext.getProtocol(),
246                    validValues[i]);
247            assertEquals("Invalid provider", sslContext.getProvider(),
248                    defaultProvider);
249        }
250    }
251
252    /**
253     * Test for <code>getInstance(String protocol, Provider provider)</code>
254     * method Assertion: throws IllegalArgumentException when provider is null
255     */
256    public void testSSLContext07() throws NoSuchAlgorithmException {
257        if (!DEFSupported) {
258            fail(NotSupportMsg);
259            return;
260        }
261        Provider provider = null;
262        for (int i = 0; i < validValues.length; i++) {
263            try {
264                SSLContext.getInstance(validValues[i], provider);
265                fail("IllegalArgumentException must be thrown when provider is null");
266            } catch (IllegalArgumentException e) {
267            }
268        }
269    }
270
271    /**
272     * Test for <code>getInstance(String protocol, Provider provider)</code>
273     * method Assertion: throws NullPointerException when protocol is null;
274     * throws NoSuchAlgorithmException when protocol is not correct;
275     */
276    public void testSSLContext08() {
277        if (!DEFSupported) {
278            fail(NotSupportMsg);
279            return;
280        }
281        try {
282            SSLContext.getInstance(null, defaultProvider);
283            fail("NoSuchAlgorithmException or NullPointerException should be thrown (protocol is null");
284        } catch (NoSuchAlgorithmException e) {
285        } catch (NullPointerException e) {
286        }
287        for (int i = 0; i < invalidValues.length; i++) {
288            try {
289                SSLContext.getInstance(invalidValues[i], defaultProvider);
290                fail("Expected NoSuchAlgorithmException was not thrown as expected");
291            } catch (NoSuchAlgorithmException e) {
292            }
293        }
294    }
295
296    /**
297     * Test for <code>getInstance(String protocol, Provider provider)</code>
298     * method Assertion: returns instance of SSLContext
299     */
300    public void testSSLContext09() throws NoSuchAlgorithmException {
301        if (!DEFSupported) {
302            fail(NotSupportMsg);
303            return;
304        }
305        SSLContext sslContext;
306        for (int i = 0; i < validValues.length; i++) {
307            sslContext = SSLContext
308                    .getInstance(validValues[i], defaultProvider);
309            assertTrue("Not SSLContext object",
310                    sslContext instanceof SSLContext);
311            assertEquals("Invalid protocol", sslContext.getProtocol(),
312                    validValues[i]);
313            assertEquals("Invalid provider", sslContext.getProvider(),
314                    defaultProvider);
315        }
316    }
317
318    /**
319     * Test for <code>getClientSessionContext()</code>
320     * <code>getServiceSessionContext()</code>
321     * methods Assertion: returns correspondent object
322     */
323    public void testSSLContext10() throws NoSuchAlgorithmException {
324        if (!DEFSupported) {
325            fail(NotSupportMsg);
326            return;
327        }
328        SSLContext[] sslC = createSSLCon();
329        assertNotNull("SSLContext objects were not created", sslC);
330        for (int i = 0; i < sslC.length; i++) {
331            assertTrue(sslC[i].getClientSessionContext() instanceof SSLSessionContext);
332            assertTrue(sslC[i].getServerSessionContext() instanceof SSLSessionContext);
333        }
334    }
335
336    /**
337     * Test for <code>getServerSocketFactory()</code>
338     * <code>getSocketFactory()</code>
339     * <code>init(KeyManager[] km, TrustManager[] tm, SecureRandom random)</code>
340     * methods Assertion: returns correspondent object
341     */
342
343    public void testSSLContext11() throws NoSuchAlgorithmException,
344            KeyManagementException, KeyStoreException,
345            UnrecoverableKeyException {
346        if (!DEFSupported) {
347            fail(NotSupportMsg);
348            return;
349        }
350        SSLContext[] sslC = createSSLCon();
351        assertNotNull("SSLContext objects were not created", sslC);
352        String tAlg = TrustManagerFactory.getDefaultAlgorithm();
353        String kAlg = KeyManagerFactory.getDefaultAlgorithm();
354        if (tAlg == null) {
355            fail("TrustManagerFactory default algorithm is not defined");
356            return;
357        }
358        if (kAlg == null) {
359            fail("KeyManagerFactory default algorithm is not defined");
360            return;
361        }
362        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kAlg);
363        KeyStore ks = null;
364        kmf.init(ks, new char[10]);
365        KeyManager[] kms = kmf.getKeyManagers();
366        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tAlg);
367        tmf.init(ks);
368        TrustManager[] tms = tmf.getTrustManagers();
369        for (int i = 0; i < sslC.length; i++) {
370            sslC[i].init(kms, tms, new SecureRandom());
371            assertTrue(sslC[i].getServerSocketFactory() instanceof SSLServerSocketFactory);
372            assertTrue(sslC[i].getSocketFactory() instanceof SSLSocketFactory);
373        }
374    }
375
376    /**
377     * Test for <code>SSLContext</code> constructor Assertion: returns
378     * SSLContext object
379     */
380    public void testSSLContext12() throws NoSuchAlgorithmException,
381            KeyManagementException {
382        if (!DEFSupported) {
383            fail(NotSupportMsg);
384            return;
385        }
386        SSLContextSpi spi = new MySSLContextSpi();
387        SSLContext sslContext = new MySSLContext(spi, defaultProvider,
388                defaultProtocol);
389        assertTrue("Not CertStore object", sslContext instanceof SSLContext);
390        assertEquals("Incorrect protocol", sslContext.getProtocol(),
391                defaultProtocol);
392        assertEquals("Incorrect provider", sslContext.getProvider(),
393                defaultProvider);
394        TrustManager[] tm = null;
395        KeyManager[] km = null;
396        sslContext.init(km, tm, new SecureRandom());
397        assertTrue(sslContext.createSSLEngine() instanceof SSLEngine);
398        assertTrue(sslContext.createSSLEngine("host host", 8888) instanceof SSLEngine);
399        try {
400            sslContext.init(km, tm, null);
401            fail("KeyManagementException should be thrown for null SEcureRandom");
402        } catch (KeyManagementException e) {
403        }
404
405        sslContext = new MySSLContext(null, null, null);
406        assertTrue("Not CertStore object", sslContext instanceof SSLContext);
407        assertNull("Incorrect protocol", sslContext.getProtocol());
408        assertNull("Incorrect provider", sslContext.getProvider());
409        try {
410            sslContext.createSSLEngine();
411            fail("NullPointerException should be thrown");
412        } catch (NullPointerException e) {
413        }
414        try {
415            sslContext.getSocketFactory();
416            fail("NullPointerException should be thrown");
417        } catch (NullPointerException e) {
418        }
419    }
420
421    public void testGetDefault() throws Exception {
422        //TODO: Need evaluation
423        class PrivateClassLoader extends ClassLoader {
424        }
425        try {
426            // register my provider and its service.
427            Security.addProvider(new MyProvider());
428            // FIXME
429            ClassLoader privateClassLoader = new PrivateClassLoader();
430            Class class1 = privateClassLoader
431                    .loadClass("org.apache.harmony.xnet.tests.javax.net.ssl.MySSLContext");
432            SSLContext sslContext = (SSLContext) class1.newInstance();
433            System.out.println(SSLContext.getInstance("Default"));
434            assertTrue((sslContext.getDefault()) instanceof SSLContext);
435        } catch (NoSuchAlgorithmException e) {
436            // expected
437        }
438    }
439
440
441    public void testGetDefaultSSLParameters() throws Exception {
442        SSLContext[] sslContexts = createSSLCon();
443        assertNotNull("SSLContext objects were not created", sslContexts);
444
445        for (int i = 0; i < sslContexts.length; i++) {
446            sslContexts[i].init(null, null, null);
447            SSLParameters defaultSSLParameters = sslContexts[i]
448                    .getDefaultSSLParameters();
449            SSLSocket sslSocket = (SSLSocket) (sslContexts[i]
450                    .getSocketFactory().createSocket());
451
452            String[] enabledCipherSuites = sslSocket.getEnabledCipherSuites();
453            String[] enabledProtocols = sslSocket.getEnabledProtocols();
454
455            for (int j = 0; j < enabledCipherSuites.length; j++)
456                assertEquals((defaultSSLParameters.getCipherSuites())[j],
457                        enabledCipherSuites[j]);
458            for (int k = 0; k < enabledProtocols.length; k++)
459                assertEquals((defaultSSLParameters.getProtocols())[k],
460                        enabledProtocols[k]);
461        }
462    }
463
464    public void testGetSupportedSSLParameters() throws Exception {
465        SSLContext[] sslContexts = createSSLCon();
466        assertNotNull("SSLContext objects were not created", sslContexts);
467
468        for (int i = 0; i < sslContexts.length; i++) {
469            sslContexts[i].init(null, null, null);
470            SSLParameters defaultSSLParameters = sslContexts[i]
471                    .getSupportedSSLParameters();
472            SSLSocket sslSocket = (SSLSocket) (sslContexts[i]
473                    .getSocketFactory().createSocket());
474            String[] supportedCipherSuites = sslSocket.getSupportedCipherSuites();
475            String[] supportedProtocols = sslSocket.getSupportedProtocols();
476
477            for (int j = 0; j < supportedCipherSuites.length; j++)
478                assertEquals((defaultSSLParameters.getCipherSuites())[j],
479                        supportedCipherSuites[j]);
480            for (int k = 0; k < supportedProtocols.length; k++)
481                assertEquals((defaultSSLParameters.getProtocols())[k],
482                        supportedProtocols[k]);
483        }
484    }
485}
486
487/**
488 * Addifional class to verify SSLContext constructor
489 */
490class MyProvider extends Provider {
491    MyProvider() {
492        super("MyProviderForSSLContextTest", 1.0, "Provider for testing");
493        put("SSLContext.Default", "org.apache.harmony.xnet.tests.javax.net.ssl.MySSLContext");
494    }
495}
496
497class MySSLContext extends SSLContext {
498    public MySSLContext(SSLContextSpi spi, Provider prov, String alg) {
499        super(spi, prov, alg);
500    }
501
502    public MySSLContext() {
503        super(null, null, null);
504    }
505}
506