PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLEngineTest.java

https://github.com/dekellum/jetty
Java | 371 lines | 284 code | 52 blank | 35 comment | 15 complexity | 7957003359d509c924172eb2e05613bb MD5 | raw file
  1. // ========================================================================
  2. // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
  3. // ------------------------------------------------------------------------
  4. // All rights reserved. This program and the accompanying materials
  5. // are made available under the terms of the Eclipse Public License v1.0
  6. // and Apache License v2.0 which accompanies this distribution.
  7. // The Eclipse Public License is available at
  8. // http://www.eclipse.org/legal/epl-v10.html
  9. // The Apache License v2.0 is available at
  10. // http://www.opensource.org/licenses/apache2.0.php
  11. // You may elect to redistribute this code under either of these licenses.
  12. // ========================================================================
  13. // JettyTest.java --
  14. //
  15. // Junit test that shows the Jetty SSL bug.
  16. //
  17. package org.eclipse.jetty.server.ssl;
  18. import static org.junit.Assert.assertEquals;
  19. import static org.junit.Assert.assertNotNull;
  20. import static org.junit.Assert.assertTrue;
  21. import java.io.BufferedReader;
  22. import java.io.IOException;
  23. import java.io.InputStream;
  24. import java.io.InputStreamReader;
  25. import java.io.OutputStream;
  26. import java.io.PrintWriter;
  27. import java.net.HttpURLConnection;
  28. import java.net.Socket;
  29. import java.net.SocketTimeoutException;
  30. import java.net.URL;
  31. import javax.net.ssl.HostnameVerifier;
  32. import javax.net.ssl.HttpsURLConnection;
  33. import javax.net.ssl.SSLContext;
  34. import javax.net.ssl.SSLSession;
  35. import javax.net.ssl.TrustManager;
  36. import javax.net.ssl.X509TrustManager;
  37. import javax.servlet.ServletException;
  38. import javax.servlet.ServletOutputStream;
  39. import javax.servlet.http.HttpServletRequest;
  40. import javax.servlet.http.HttpServletResponse;
  41. import org.eclipse.jetty.http.ssl.SslContextFactory;
  42. import org.eclipse.jetty.server.Connector;
  43. import org.eclipse.jetty.server.Request;
  44. import org.eclipse.jetty.server.Server;
  45. import org.eclipse.jetty.server.handler.AbstractHandler;
  46. import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
  47. import org.eclipse.jetty.util.IO;
  48. import org.junit.AfterClass;
  49. import org.junit.BeforeClass;
  50. import org.junit.Test;
  51. /**
  52. *
  53. */
  54. public class SSLEngineTest
  55. {
  56. // Useful constants
  57. private static final String HELLO_WORLD="Hello world. The quick brown fox jumped over the lazy dog. How now brown cow. The rain in spain falls mainly on the plain.\n";
  58. private static final String JETTY_VERSION=Server.getVersion();
  59. private static final String PROTOCOL_VERSION="2.0";
  60. /** The request. */
  61. private static final String REQUEST0_HEADER="POST /r0 HTTP/1.1\n"+"Host: localhost\n"+"Content-Type: text/xml\n"+"Content-Length: ";
  62. private static final String REQUEST1_HEADER="POST /r1 HTTP/1.1\n"+"Host: localhost\n"+"Content-Type: text/xml\n"+"Connection: close\n"+"Content-Length: ";
  63. private static final String REQUEST_CONTENT="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
  64. +"<requests xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"+" xsi:noNamespaceSchemaLocation=\"commander.xsd\" version=\""
  65. +PROTOCOL_VERSION+"\">\n"+"</requests>";
  66. private static final String REQUEST0=REQUEST0_HEADER+REQUEST_CONTENT.getBytes().length+"\n\n"+REQUEST_CONTENT;
  67. private static final String REQUEST1=REQUEST1_HEADER+REQUEST_CONTENT.getBytes().length+"\n\n"+REQUEST_CONTENT;
  68. /** The expected response. */
  69. 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;
  70. private static final String RESPONSE1="HTTP/1.1 200 OK\n"+"Connection: close\n"+"Server: Jetty("+JETTY_VERSION+")\n"+'\n'+HELLO_WORLD;
  71. private static final int BODY_SIZE=300;
  72. private static final TrustManager[] s_dummyTrustManagers=new TrustManager[]
  73. {
  74. new X509TrustManager()
  75. {
  76. public java.security.cert.X509Certificate[] getAcceptedIssuers()
  77. {
  78. return null;
  79. }
  80. public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType)
  81. {
  82. }
  83. public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType)
  84. {
  85. }
  86. }
  87. };
  88. private static Server server;
  89. private static SslSelectChannelConnector connector;
  90. @BeforeClass
  91. public static void startServer() throws Exception
  92. {
  93. server=new Server();
  94. connector=new SslSelectChannelConnector();
  95. String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
  96. connector.setPort(0);
  97. SslContextFactory cf = connector.getSslContextFactory();
  98. cf.setKeyStore(keystore);
  99. cf.setKeyStorePassword("storepwd");
  100. cf.setKeyManagerPassword("keypwd");
  101. connector.setRequestBufferSize(512);
  102. connector.setRequestHeaderSize(512);
  103. server.setConnectors(new Connector[]{connector });
  104. server.setHandler(new HelloWorldHandler());
  105. server.start();
  106. }
  107. @AfterClass
  108. public static void stopServer() throws Exception
  109. {
  110. server.stop();
  111. server.join();
  112. }
  113. @Test
  114. public void testBigResponse() throws Exception
  115. {
  116. SSLContext ctx=SSLContext.getInstance("TLS");
  117. ctx.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
  118. int port=connector.getLocalPort();
  119. Socket client=ctx.getSocketFactory().createSocket("localhost",port);
  120. OutputStream os=client.getOutputStream();
  121. String request =
  122. "GET /?dump=102400 HTTP/1.1\r\n"+
  123. "Host: localhost:8080\r\n"+
  124. "Connection: close\r\n"+
  125. "\r\n";
  126. os.write(request.getBytes());
  127. os.flush();
  128. String response = IO.toString(client.getInputStream());
  129. assertTrue(response.length()>102400);
  130. }
  131. @Test
  132. public void testRequestJettyHttps() throws Exception
  133. {
  134. final int loops=10;
  135. final int numConns=10;
  136. Socket[] client=new Socket[numConns];
  137. SSLContext ctx=SSLContext.getInstance("SSLv3");
  138. ctx.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
  139. int port=connector.getLocalPort();
  140. try
  141. {
  142. for (int l=0;l<loops;l++)
  143. {
  144. System.err.print('.');
  145. try
  146. {
  147. for (int i=0; i<numConns; ++i)
  148. {
  149. // System.err.println("write:"+i);
  150. client[i]=ctx.getSocketFactory().createSocket("localhost",port);
  151. OutputStream os=client[i].getOutputStream();
  152. os.write(REQUEST0.getBytes());
  153. os.write(REQUEST0.getBytes());
  154. os.flush();
  155. }
  156. for (int i=0; i<numConns; ++i)
  157. {
  158. // System.err.println("flush:"+i);
  159. OutputStream os=client[i].getOutputStream();
  160. os.write(REQUEST1.getBytes());
  161. os.flush();
  162. }
  163. for (int i=0; i<numConns; ++i)
  164. {
  165. // System.err.println("read:"+i);
  166. // Read the response.
  167. String responses=readResponse(client[i]);
  168. // Check the response
  169. assertEquals(String.format("responses %d %d",l,i),RESPONSE0+RESPONSE0+RESPONSE1,responses);
  170. }
  171. }
  172. finally
  173. {
  174. for (int i=0; i<numConns; ++i)
  175. {
  176. if (client[i]!=null)
  177. {
  178. client[i].close();
  179. }
  180. }
  181. }
  182. }
  183. }
  184. finally
  185. {
  186. System.err.println();
  187. }
  188. }
  189. @Test
  190. public void testServletPost() throws Exception
  191. {
  192. stopServer();
  193. StreamHandler handler = new StreamHandler();
  194. server.setHandler(handler);
  195. server.start();
  196. SSLContext context = SSLContext.getInstance("SSL");
  197. context.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
  198. HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
  199. URL url = new URL("https://localhost:"+connector.getLocalPort()+"/test");
  200. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
  201. if (conn instanceof HttpsURLConnection)
  202. {
  203. ((HttpsURLConnection)conn).setHostnameVerifier(new HostnameVerifier()
  204. {
  205. public boolean verify(String urlHostName, SSLSession session)
  206. {
  207. return true;
  208. }
  209. });
  210. }
  211. conn.setConnectTimeout(10000);
  212. conn.setReadTimeout(100000);
  213. conn.setDoInput(true);
  214. conn.setDoOutput(true);
  215. conn.setRequestMethod("POST");
  216. conn.setRequestProperty("Content-Type","text/plain");
  217. conn.setChunkedStreamingMode(128);
  218. conn.connect();
  219. byte[] b = new byte[BODY_SIZE];
  220. for (int i = 0; i < BODY_SIZE; i++)
  221. {
  222. b[i] = 'x';
  223. }
  224. OutputStream os = conn.getOutputStream();
  225. os.write(b);
  226. os.flush();
  227. int len = 0;
  228. InputStream is = conn.getInputStream();
  229. int bytes=0;
  230. while ((len = is.read(b)) > -1)
  231. bytes+=len;
  232. is.close();
  233. assertEquals(BODY_SIZE,handler.bytes);
  234. assertEquals(BODY_SIZE,bytes);
  235. }
  236. /**
  237. * Reads entire response from the client. Close the output.
  238. *
  239. * @param client Open client socket.
  240. * @return The response string.
  241. * @throws IOException in case of I/O errors
  242. */
  243. private static String readResponse(Socket client) throws IOException
  244. {
  245. BufferedReader br=null;
  246. StringBuilder sb=new StringBuilder(1000);
  247. try
  248. {
  249. client.setSoTimeout(5000);
  250. br=new BufferedReader(new InputStreamReader(client.getInputStream()));
  251. String line;
  252. while ((line=br.readLine())!=null)
  253. {
  254. sb.append(line);
  255. sb.append('\n');
  256. }
  257. }
  258. catch(SocketTimeoutException e)
  259. {
  260. System.err.println("Test timedout: "+e.toString());
  261. e.printStackTrace(); // added to see if we can get more info from failures on CI
  262. }
  263. finally
  264. {
  265. if (br!=null)
  266. {
  267. br.close();
  268. }
  269. }
  270. return sb.toString();
  271. }
  272. private static class HelloWorldHandler extends AbstractHandler
  273. {
  274. public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
  275. {
  276. // System.err.println("HANDLE "+request.getRequestURI());
  277. String ssl_id = (String)request.getAttribute("javax.servlet.request.ssl_session_id");
  278. assertNotNull(ssl_id);
  279. if (request.getParameter("dump")!=null)
  280. {
  281. ServletOutputStream out=response.getOutputStream();
  282. byte[] buf = new byte[Integer.valueOf(request.getParameter("dump"))];
  283. for (int i=0;i<buf.length;i++)
  284. buf[i]=(byte)('0'+(i%10));
  285. out.write(buf);
  286. out.close();
  287. }
  288. else
  289. {
  290. PrintWriter out=response.getWriter();
  291. out.print(HELLO_WORLD);
  292. out.close();
  293. }
  294. }
  295. }
  296. private static class StreamHandler extends AbstractHandler
  297. {
  298. private int bytes=0;
  299. public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
  300. {
  301. response.setContentType("text/plain");
  302. response.setBufferSize(128);
  303. byte[] b = new byte[BODY_SIZE];
  304. int len = 0;
  305. InputStream is = request.getInputStream();
  306. while ((len = is.read(b)) > -1)
  307. {
  308. bytes+=len;
  309. }
  310. OutputStream os = response.getOutputStream();
  311. for (int i = 0; i < BODY_SIZE; i++)
  312. {
  313. b[i] = 'x';
  314. }
  315. os.write(b);
  316. response.flushBuffer();
  317. }
  318. }
  319. }