/extras/sslengine/src/test/java/org/mortbay/jetty/security/SSLEngineTest.java
Java | 398 lines | 279 code | 64 blank | 55 comment | 14 complexity | bf42b92405c42e935dfc080e9dac885e MD5 | raw file
- //========================================================================
- //Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
- //------------------------------------------------------------------------
- //Licensed under the Apache License, Version 2.0 (the "License");
- //you may not use this file except in compliance with the License.
- //You may obtain a copy of the License at
- //http://www.apache.org/licenses/LICENSE-2.0
- //Unless required by applicable law or agreed to in writing, software
- //distributed under the License is distributed on an "AS IS" BASIS,
- //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- //See the License for the specific language governing permissions and
- //limitations under the License.
- //========================================================================
- // JettyTest.java --
- //
- // Junit test that shows the Jetty SSL bug.
- //
- package org.mortbay.jetty.security;
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.net.HttpURLConnection;
- import java.net.Socket;
- import java.net.URL;
- import java.security.cert.CertificateException;
- import java.security.cert.X509Certificate;
- import javax.net.ssl.HostnameVerifier;
- import javax.net.ssl.HttpsURLConnection;
- import javax.net.ssl.SSLContext;
- import javax.net.ssl.SSLSession;
- import javax.net.ssl.TrustManager;
- import javax.net.ssl.X509TrustManager;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import junit.framework.TestCase;
- import org.mortbay.jetty.Connector;
- import org.mortbay.jetty.Server;
- import org.mortbay.jetty.handler.AbstractHandler;
- import org.mortbay.jetty.security.SslSelectChannelConnector;
- import org.mortbay.jetty.servlet.ServletHandler;
- import org.mortbay.jetty.servlet.ServletHolder;
- import org.mortbay.util.IO;
- /**
- * HttpServer Tester.
- */
- public class SSLEngineTest extends TestCase
- {
- // ~ Static fields/initializers
- // ---------------------------------------------
- // Useful constants
- private static final int BODY_SIZE = 300;
- private static final String HELLO_WORLD="Hello world\r\n";
- private static final String JETTY_VERSION=Server.getVersion();
- private static final String PROTOCOL_VERSION="2.0";
- /** The request. */
- private static final String REQUEST0_HEADER="POST / HTTP/1.1\n"+"Host: localhost\n"+"Content-Type: text/xml\n"+"Content-Length: ";
- private static final String REQUEST1_HEADER="POST / HTTP/1.1\n"+"Host: localhost\n"+"Content-Type: text/xml\n"+"Connection: close\n"+"Content-Length: ";
- private static final String REQUEST_CONTENT="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
- +"<requests xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"+" xsi:noNamespaceSchemaLocation=\"commander.xsd\" version=\""
- +PROTOCOL_VERSION+"\">\n"+"</requests>";
-
- private static final String REQUEST0=REQUEST0_HEADER+REQUEST_CONTENT.getBytes().length+"\n\n"+REQUEST_CONTENT;
- private static final String REQUEST1=REQUEST1_HEADER+REQUEST_CONTENT.getBytes().length+"\n\n"+REQUEST_CONTENT;
- /** The expected response. */
- private static final String RESPONSE0="HTTP/1.1 200 OK\n"+"Content-Length: "+HELLO_WORLD.length()+"\n"+"Server: Jetty("+JETTY_VERSION+")\n"+'\n'+"Hello world\n";
- private static final String RESPONSE1="HTTP/1.1 200 OK\n"+"Connection: close\n"+"Server: Jetty("+JETTY_VERSION+")\n"+'\n'+"Hello world\n";
- private static class CredulousTM implements TrustManager, X509TrustManager
- {
- public X509Certificate[] getAcceptedIssuers()
- {
- return null;
- }
- public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
- {
- return;
- }
- public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
- {
- return;
- }
- }
-
- private static final TrustManager[] s_dummyTrustManagers=new TrustManager[] { new CredulousTM() };
- /**
- * Feed the server the entire request at once.
- *
- * @throws Exception
- */
- public void testBigResponse() throws Exception
- {
- Server server=new Server();
- SslSelectChannelConnector connector=new SslSelectChannelConnector();
- String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
-
- connector.setPort(0);
- connector.setKeystore(keystore);
- connector.setPassword("storepwd");
- connector.setKeyPassword("keypwd");
- server.setConnectors(new Connector[]
- { connector });
- server.setHandler(new HelloWorldHandler());
- server.start();
-
- SSLContext ctx=SSLContext.getInstance("SSLv3");
- ctx.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
- int port=connector.getLocalPort();
- Socket client=ctx.getSocketFactory().createSocket("localhost",port);
- OutputStream os=client.getOutputStream();
- String request =
- "GET /?dump=102400 HTTP/1.1\r\n"+
- "Host: localhost:8080\r\n"+
- "Connection: close\r\n"+
- "\r\n";
-
- os.write(request.getBytes());
- os.flush();
-
- String response = IO.toString(client.getInputStream());
- System.err.println("response "+response.length());
- assertTrue(response.length()>102400);
- }
- // ~ Methods
- // ----------------------------------------------------------------
- /**
- * Feed the server the entire request at once.
- *
- * @throws Exception
- */
- public void testRequest1_jetty_https() throws Exception
- {
- Server server=new Server();
- SslSelectChannelConnector connector=new SslSelectChannelConnector();
- String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
-
- connector.setPort(0);
- connector.setKeystore(keystore);
- connector.setPassword("storepwd");
- connector.setKeyPassword("keypwd");
- server.setConnectors(new Connector[]
- { connector });
- server.setHandler(new HelloWorldHandler());
- final int numConns=200;
- Socket[] socket=new Socket[numConns];
-
- try
- {
- server.start();
- SSLContext ctx=SSLContext.getInstance("SSLv3");
- ctx.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
- int port=connector.getLocalPort();
- for (int i=0; i<numConns; ++i)
- {
- // System.err.println("write:"+i);
- socket[i]=ctx.getSocketFactory().createSocket("localhost",port);
- OutputStream os=socket[i].getOutputStream();
- os.write(REQUEST0.getBytes());
- os.write(REQUEST0.getBytes());
- os.flush();
- }
- for (int i=0; i<numConns; ++i)
- {
- // System.err.println("flush:"+i);
- OutputStream os=socket[i].getOutputStream();
- os.write(REQUEST1.getBytes());
- os.flush();
- }
- for (int i=0; i<numConns; ++i)
- {
- // System.err.println("read:"+i);
- // Read the response.
- String responses=readResponse(socket[i]);
- // Check the response
- assertEquals(String.format("responses %d",i),RESPONSE0+RESPONSE0+RESPONSE1,responses);
- }
- }
- finally
- {
- for (int i=0; i<numConns; ++i)
- {
- if (socket[i]!=null)
- {
- socket[i].close();
- }
- }
- server.stop();
- }
- }
- /**
- * Read entire response from the client. Close the output.
- *
- * @param client
- * Open client socket.
- *
- * @return The response string.
- *
- * @throws IOException
- */
- private static String readResponse(Socket client) throws IOException
- {
- BufferedReader br=null;
- try
- {
- br=new BufferedReader(new InputStreamReader(client.getInputStream()));
- StringBuilder sb=new StringBuilder(1000);
- String line;
- while ((line=br.readLine())!=null)
- {
- sb.append(line);
- sb.append('\n');
- }
- return sb.toString();
- }
- finally
- {
- if (br!=null)
- {
- br.close();
- }
- }
- }
- private static class HelloWorldHandler extends AbstractHandler
- {
- public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException
- {
- PrintWriter out=response.getWriter();
- try
- {
- out.print(HELLO_WORLD);
- if (request.getParameter("dump")!=null)
- {
- char[] buf = new char[Integer.valueOf(request.getParameter("dump"))];
- for (int i=0;i<buf.length;i++)
- buf[i]=(char)('0'+(i%10));
- out.write(buf);
- }
- }
- finally
- {
- out.close();
- }
- }
- }
- public void testServletPost() throws Exception
- {
- Server server=new Server();
- SslSelectChannelConnector connector=new SslSelectChannelConnector();
- String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
-
- connector.setPort(0);
- connector.setKeystore(keystore);
- connector.setPassword("storepwd");
- connector.setKeyPassword("keypwd");
- connector.setTruststore(keystore);
- connector.setTrustPassword("storepwd");
- server.setConnectors(new Connector[]
- { connector });
- ServletHandler handler = new ServletHandler();
- TestServlet servlet = new TestServlet();
- handler.addServletWithMapping(new ServletHolder(servlet),"/test");
- server.addHandler(handler);
-
- try
- {
- SSLContext context = SSLContext.getInstance("SSL");
- context.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
- HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
- server.start();
- URL url = new URL("https://localhost:"+connector.getLocalPort()+"/test");
- HttpURLConnection conn = (HttpURLConnection)url.openConnection();
- if (conn instanceof HttpsURLConnection)
- {
- ((HttpsURLConnection)conn).setHostnameVerifier(new HostnameVerifier()
- {
- public boolean verify(String urlHostName, SSLSession session)
- {
- return true;
- }
- });
- }
- conn.setConnectTimeout(10000);
- conn.setReadTimeout(100000);
- conn.setDoInput(true);
- conn.setDoOutput(true);
- conn.setRequestMethod("POST");
- conn.setRequestProperty("Content-Type","text/plain"); //$NON-NLS-1$
- conn.setChunkedStreamingMode(128);
- conn.connect();
- byte[] b = new byte[BODY_SIZE];
- for (int i = 0; i < BODY_SIZE; i++)
- {
- b[i] = 'x';
- }
- OutputStream os = conn.getOutputStream();
- os.write(b);
- os.flush();
- int rc = conn.getResponseCode();
- int len = 0;
- InputStream is = conn.getInputStream();
- int bytes=0;
- while ((len = is.read(b)) > -1)
- bytes+=len;
- is.close();
- assertEquals(BODY_SIZE,servlet.bytes);
- assertEquals(BODY_SIZE,bytes);
-
- }
- finally
- {
- server.stop();
- }
- }
- public static class TestServlet extends HttpServlet
- {
- public int bytes=0;
-
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- {
- resp.setContentType("text/plain");
- resp.setBufferSize(128);
- byte[] b = new byte[BODY_SIZE];
- int len = 0;
- InputStream is = req.getInputStream();
- // !!!! UNDER HTTPS, FIRST CHUNK IS READ HERE BUT THEN SERVER IS
- // WAITING FOR
- // !!!! MORE DATA
- while ((len = is.read(b)) > -1)
- {
- bytes+=len;
- }
- OutputStream os = resp.getOutputStream();
- for (int i = 0; i < BODY_SIZE; i++)
- {
- b[i] = 'x';
- }
- os.write(b);
- resp.flushBuffer();
- }
- }
- }