SSLSocketFunctionalTest.java revision 561ee011997c6c2f1befbfaa9d5f0a99771c1d63
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     * @return
179     */
180    public void doTest(SSLServerSocket ssocket, SSLSocket csocket)
181            throws Throwable {
182        final String server_message = "Hello from SSL Server Socket!";
183        final String client_message = "Hello from SSL Socket!";
184        Thread server = null;
185        Thread client = null;
186        final Throwable[] throwed = new Throwable[1];
187        try {
188            final SSLServerSocket ss = ssocket;
189            final SSLSocket s = csocket;
190            server = new Thread() {
191                @Override
192                public void run() {
193                    InputStream is = null;
194                    OutputStream os = null;
195                    SSLSocket s = null;
196                    try {
197                        s = (SSLSocket) ss.accept();
198                        if (doLog) {
199                            System.out.println("Socket accepted: " + s);
200                        }
201                        is = s.getInputStream();
202                        os = s.getOutputStream();
203                        // send the message to the client
204                        os.write(server_message.getBytes());
205                        // read the response
206                        byte[] buff = new byte[client_message.length()];
207                        int len = is.read(buff);
208                        if (doLog) {
209                            System.out.println("Received message of length "
210                                + len + ": '" + new String(buff, 0, len)+"'");
211                        }
212                        assertTrue("Read message does not equal to expected",
213                                Arrays.equals(client_message.getBytes(), buff));
214                        os.write(-1);
215                        assertEquals("Read data differs from expected",
216                                255, is.read());
217                        if (doLog) {
218                            System.out.println("Server is closed: "
219                                    +s.isClosed());
220                        }
221                        assertEquals("Returned value should be -1",
222                        // initiate an exchange of closure alerts
223                                -1, is.read());
224                        if (doLog) {
225                            System.out.println("Server is closed: "
226                                    +s.isClosed());
227                        }
228                        assertEquals("Returned value should be -1",
229                        // initiate an exchange of closure alerts
230                                -1, is.read());
231                    } catch (Throwable e) {
232                        synchronized (throwed) {
233                            if (doLog) {
234                                e.printStackTrace();
235                            }
236                            if (throwed[0] == null) {
237                                throwed[0] = e;
238                            }
239                        }
240                    } finally {
241                        try {
242                            if (is != null) {
243                                is.close();
244                            }
245                        } catch (IOException ex) {}
246                        try {
247                            if (os != null) {
248                                os.close();
249                            }
250                        } catch (IOException ex) {}
251                        try {
252                            if (s != null) {
253                                s.close();
254                            }
255                        } catch (IOException ex) {}
256                    }
257                }
258            };
259
260            client = new Thread() {
261                @Override
262                public void run() {
263                    InputStream is = null;
264                    OutputStream os = null;
265                    try {
266                        assertTrue("Client was not connected", s.isConnected());
267                        if (doLog) {
268                            System.out.println("Client connected");
269                        }
270                        is = s.getInputStream();
271                        os = s.getOutputStream();
272                        s.startHandshake();
273                        if (doLog) {
274                            System.out.println("Client: HS was done");
275                        }
276                        // read the message from the server
277                        byte[] buff = new byte[server_message.length()];
278                        int len = is.read(buff);
279                        if (doLog) {
280                            System.out.println("Received message of length "
281                                + len + ": '" + new String(buff, 0, len)+"'");
282                        }
283                        assertTrue("Read message does not equal to expected",
284                                Arrays.equals(server_message.getBytes(), buff));
285                        // send the response
286                        buff = (" "+client_message+" ").getBytes();
287                        os.write(buff, 1, buff.length-2);
288                        assertEquals("Read data differs from expected",
289                                255, is.read());
290                        os.write(-1);
291                        if (doLog) {
292                            System.out.println("\n======== Closing ========");
293                        }
294                        if (doLog) {
295                            System.out.println("Client is closed: "
296                                    +s.isClosed());
297                        }
298                        s.close();
299                        if (doLog) {
300                            System.out.println("Client is closed: "
301                                    +s.isClosed());
302                        }
303                    } catch (Throwable e) {
304                        synchronized (throwed) {
305                            if (doLog) {
306                                e.printStackTrace();
307                            }
308                            if (throwed[0] == null) {
309                                throwed[0] = e;
310                            }
311                        }
312                    } finally {
313                        try {
314                            if (is != null) {
315                                is.close();
316                            }
317                        } catch (IOException ex) {}
318                        try {
319                            if (os != null) {
320                                os.close();
321                            }
322                        } catch (IOException ex) {}
323                        try {
324                            if (s != null) {
325                                s.close();
326                            }
327                        } catch (IOException ex) {}
328                    }
329                }
330            };
331
332            server.start();
333            client.start();
334
335            while (server.isAlive() || client.isAlive()) {
336                if (throwed[0] != null) {
337                    throw throwed[0];
338                }
339                try {
340                    Thread.sleep(500);
341                } catch (Exception e) { }
342            }
343        } finally {
344            if (server != null) {
345                server.stop();
346            }
347            if (client != null) {
348                client.stop();
349            }
350        }
351        if (throwed[0] != null) {
352            throw throwed[0];
353        }
354    }
355
356    public static Test suite() {
357        return new TestSuite(SSLSocketFunctionalTest.class);
358    }
359
360    public static void main(String[] args) {
361        junit.textui.TestRunner.run(suite());
362    }
363}
364
365