SSLSocketFunctionalTest.java revision 8d8858e39800de641b50f6e8e864af9cf68bedea
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.provider.jsse;
19
20import java.io.IOException;
21import java.io.InputStream;
22import java.io.OutputStream;
23import java.util.Arrays;
24import javax.net.ssl.HandshakeCompletedEvent;
25import javax.net.ssl.HandshakeCompletedListener;
26import javax.net.ssl.SSLContext;
27import javax.net.ssl.SSLServerSocket;
28import javax.net.ssl.SSLSocket;
29
30import junit.framework.Test;
31import junit.framework.TestCase;
32import junit.framework.TestSuite;
33
34/**
35 * SSLSocketImplTest
36 */
37public class SSLSocketFunctionalTest extends TestCase {
38
39    /**
40     * The cipher suites used for functionality testing.
41     */
42    private String[] cipher_suites = {
43            "RSA_WITH_RC4_128_MD5",
44            "RSA_WITH_DES_CBC_SHA",
45            "DH_anon_EXPORT_WITH_DES40_CBC_SHA"
46    };
47
48    // turn on/off the debug logging
49    private boolean doLog = false;
50
51    /**
52     * Sets up the test case.
53     */
54    @Override
55    public void setUp() throws Exception {
56        if (doLog) {
57            System.out.println("========================");
58            System.out.println("====== Running the test: " + getName());
59            System.out.println("========================");
60        }
61    }
62
63    public void testContextInitialized2() throws Throwable {
64        doTestSelfInteraction(JSSETestData.getContext());
65    }
66
67    public void doTestInteraction(SSLContext context, SSLContext ctx_other)
68            throws Throwable {
69        SSLContext ctx1, ctx2;
70
71        ctx1 = context;
72        ctx2 = ctx_other;
73
74        int k = 1;
75
76        SSLServerSocket ssocket = (SSLServerSocket) ctx1
77                .getServerSocketFactory().createServerSocket(0);
78        ssocket.setUseClientMode(false);
79        ssocket.setEnabledCipherSuites(
80                ((k & 1) > 0)
81                        ? new String[] { "TLS_" + cipher_suites[0] }
82                        : new String[] { "SSL_" + cipher_suites[0] });
83
84        SSLSocket csocket = (SSLSocket) ctx2
85                .getSocketFactory().createSocket("localhost",
86                        ssocket.getLocalPort());
87        csocket.setEnabledProtocols(new String[] { "TLSv1" });
88        csocket.setUseClientMode(true);
89        csocket.setEnabledCipherSuites(
90                (((k & 2) >> 1) > 0)
91                        ? new String[] { "TLS_" + cipher_suites[0] }
92                        : new String[] { "SSL_" + cipher_suites[0] });
93        doTest(ssocket, csocket);
94    }
95
96    public void _doTestInteraction(SSLContext context, SSLContext ctx_other)
97            throws Throwable {
98        for (int i = 0; i < cipher_suites.length; i++) {
99            if (doLog) {
100                System.out.println("======== Checking the work on cipher: "
101                        + cipher_suites[i]);
102            }
103            SSLContext ctx1, ctx2;
104            // k: 00, 01, 10, 11;
105            // where 1 means implementation under the test,
106            // 0 - another implementation to interract with
107            for (int k = 0; k < 4; k++) {
108                if (doLog) {
109                    System.out.println("======== " + (k & 1) + " " + ((k & 2) >> 1));
110                }
111                ctx1 = ((k & 1) > 0) ? context : ctx_other;
112                ctx2 = (((k & 2) >> 1) > 0) ? context : ctx_other;
113
114                SSLServerSocket ssocket = (SSLServerSocket) ctx1
115                        .getServerSocketFactory().createServerSocket(0);
116                ssocket.setUseClientMode(false);
117                ssocket.setEnabledCipherSuites(
118                        ((k & 1) > 0)
119                                ? new String[] { "TLS_" + cipher_suites[i] }
120                                : new String[] { "SSL_" + cipher_suites[i] });
121
122                SSLSocket csocket = (SSLSocket) ctx2
123                        .getSocketFactory().createSocket("localhost",
124                                ssocket.getLocalPort());
125                csocket.setEnabledProtocols(new String[] { "TLSv1" });
126                csocket.setUseClientMode(true);
127                csocket.setEnabledCipherSuites(
128                        (((k & 2) >> 1) > 0)
129                                ? new String[] { "TLS_" + cipher_suites[i] }
130                                : new String[] { "SSL_" + cipher_suites[i] });
131                doTest(ssocket, csocket);
132            }
133        }
134    }
135
136    /**
137     * Tests the interaction with other implementation.
138     */
139    public void doTestSelfInteraction(SSLContext context)
140            throws Throwable {
141        String[] protocols = { "SSLv3", "TLSv1" };
142        for (int i = 0; i < cipher_suites.length; i++) {
143            for (int j = 0; j < 2; j++) {
144                if (doLog) {
145                    System.out.println("======= " + cipher_suites[i]);
146                }
147                SSLServerSocket ssocket = (SSLServerSocket) context
148                        .getServerSocketFactory().createServerSocket(0);
149                ssocket.setUseClientMode(false);
150                ssocket.setEnabledProtocols(new String[] { protocols[j] });
151                ssocket.setEnabledCipherSuites(
152                        new String[] { "TLS_" + cipher_suites[i] });
153
154                SSLSocket csocket = (SSLSocket) context
155                        .getSocketFactory().createSocket("localhost",
156                                ssocket.getLocalPort());
157                csocket.setEnabledProtocols(new String[] { protocols[j] });
158                csocket.setUseClientMode(true);
159                csocket.setEnabledCipherSuites(
160                        new String[] { "TLS_" + cipher_suites[i] });
161
162                doTest(ssocket, csocket);
163            }
164        }
165    }
166
167    private static class HandshakeListener
168            implements HandshakeCompletedListener {
169        boolean compleated = false;
170
171        public void handshakeCompleted(HandshakeCompletedEvent event) {
172            compleated = true;
173        }
174    }
175
176    /**
177     * Performs SSL connection between the sockets
178     *
179     * @return
180     */
181    public void doTest(SSLServerSocket ssocket, SSLSocket csocket)
182            throws Throwable {
183        final String server_message = "Hello from SSL Server Socket!";
184        final String client_message = "Hello from SSL Socket!";
185        Thread server = null;
186        Thread client = null;
187        final Throwable[] throwed = new Throwable[1];
188        try {
189            final SSLServerSocket ss = ssocket;
190            final SSLSocket s = csocket;
191            server = new Thread() {
192                @Override
193                public void run() {
194                    InputStream is = null;
195                    OutputStream os = null;
196                    SSLSocket s = null;
197                    try {
198                        s = (SSLSocket) ss.accept();
199                        if (doLog) {
200                            System.out.println("Socket accepted: " + s);
201                        }
202                        is = s.getInputStream();
203                        os = s.getOutputStream();
204                        // send the message to the client
205                        os.write(server_message.getBytes());
206                        // read the response
207                        byte[] buff = new byte[client_message.length()];
208                        int len = is.read(buff);
209                        if (doLog) {
210                            System.out.println("Received message of length "
211                                    + len + ": '" + new String(buff, 0, len) + "'");
212                        }
213                        assertTrue("Read message does not equal to expected",
214                                Arrays.equals(client_message.getBytes(), buff));
215                        os.write(-1);
216                        assertEquals("Read data differs from expected",
217                                255, is.read());
218                        if (doLog) {
219                            System.out.println("Server is closed: "
220                                    + s.isClosed());
221                        }
222                        assertEquals("Returned value should be -1",
223                                // initiate an exchange of closure alerts
224                                -1, is.read());
225                        if (doLog) {
226                            System.out.println("Server is closed: "
227                                    + s.isClosed());
228                        }
229                        assertEquals("Returned value should be -1",
230                                // initiate an exchange of closure alerts
231                                -1, is.read());
232                    } catch (Throwable e) {
233                        synchronized (throwed) {
234                            if (doLog) {
235                                e.printStackTrace();
236                            }
237                            if (throwed[0] == null) {
238                                throwed[0] = e;
239                            }
240                        }
241                    } finally {
242                        try {
243                            if (is != null) {
244                                is.close();
245                            }
246                        } catch (IOException ex) {
247                        }
248                        try {
249                            if (os != null) {
250                                os.close();
251                            }
252                        } catch (IOException ex) {
253                        }
254                        try {
255                            if (s != null) {
256                                s.close();
257                            }
258                        } catch (IOException ex) {
259                        }
260                    }
261                }
262            };
263
264            client = new Thread() {
265                @Override
266                public void run() {
267                    InputStream is = null;
268                    OutputStream os = null;
269                    try {
270                        assertTrue("Client was not connected", s.isConnected());
271                        if (doLog) {
272                            System.out.println("Client connected");
273                        }
274                        is = s.getInputStream();
275                        os = s.getOutputStream();
276                        s.startHandshake();
277                        if (doLog) {
278                            System.out.println("Client: HS was done");
279                        }
280                        // read the message from the server
281                        byte[] buff = new byte[server_message.length()];
282                        int len = is.read(buff);
283                        if (doLog) {
284                            System.out.println("Received message of length "
285                                    + len + ": '" + new String(buff, 0, len) + "'");
286                        }
287                        assertTrue("Read message does not equal to expected",
288                                Arrays.equals(server_message.getBytes(), buff));
289                        // send the response
290                        buff = (" " + client_message + " ").getBytes();
291                        os.write(buff, 1, buff.length - 2);
292                        assertEquals("Read data differs from expected",
293                                255, is.read());
294                        os.write(-1);
295                        if (doLog) {
296                            System.out.println("\n======== Closing ========");
297                        }
298                        if (doLog) {
299                            System.out.println("Client is closed: "
300                                    + s.isClosed());
301                        }
302                        s.close();
303                        if (doLog) {
304                            System.out.println("Client is closed: "
305                                    + s.isClosed());
306                        }
307                    } catch (Throwable e) {
308                        synchronized (throwed) {
309                            if (doLog) {
310                                e.printStackTrace();
311                            }
312                            if (throwed[0] == null) {
313                                throwed[0] = e;
314                            }
315                        }
316                    } finally {
317                        try {
318                            if (is != null) {
319                                is.close();
320                            }
321                        } catch (IOException ex) {
322                        }
323                        try {
324                            if (os != null) {
325                                os.close();
326                            }
327                        } catch (IOException ex) {
328                        }
329                        try {
330                            if (s != null) {
331                                s.close();
332                            }
333                        } catch (IOException ex) {
334                        }
335                    }
336                }
337            };
338
339            server.start();
340            client.start();
341
342            while (server.isAlive() || client.isAlive()) {
343                if (throwed[0] != null) {
344                    throw throwed[0];
345                }
346                try {
347                    Thread.sleep(500);
348                } catch (Exception e) {
349                }
350            }
351        } finally {
352            if (server != null) {
353                server.stop();
354            }
355            if (client != null) {
356                client.stop();
357            }
358        }
359        if (throwed[0] != null) {
360            throw throwed[0];
361        }
362    }
363
364    public static Test suite() {
365        return new TestSuite(SSLSocketFunctionalTest.class);
366    }
367
368}
369