PageRenderTime 63ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/extras/sslengine/src/test/java/org/mortbay/jetty/security/SSLEngineTest.java

https://github.com/toddlipcon/jetty-hadoop-fix
Java | 398 lines | 279 code | 64 blank | 55 comment | 14 complexity | bf42b92405c42e935dfc080e9dac885e MD5 | raw file
  1. //========================================================================
  2. //Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
  3. //------------------------------------------------------------------------
  4. //Licensed under the Apache License, Version 2.0 (the "License");
  5. //you may not use this file except in compliance with the License.
  6. //You may obtain a copy of the License at
  7. //http://www.apache.org/licenses/LICENSE-2.0
  8. //Unless required by applicable law or agreed to in writing, software
  9. //distributed under the License is distributed on an "AS IS" BASIS,
  10. //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. //See the License for the specific language governing permissions and
  12. //limitations under the License.
  13. //========================================================================
  14. // JettyTest.java --
  15. //
  16. // Junit test that shows the Jetty SSL bug.
  17. //
  18. package org.mortbay.jetty.security;
  19. import java.io.BufferedReader;
  20. import java.io.File;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.io.InputStreamReader;
  24. import java.io.OutputStream;
  25. import java.io.PrintWriter;
  26. import java.net.HttpURLConnection;
  27. import java.net.Socket;
  28. import java.net.URL;
  29. import java.security.cert.CertificateException;
  30. import java.security.cert.X509Certificate;
  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.http.HttpServlet;
  39. import javax.servlet.http.HttpServletRequest;
  40. import javax.servlet.http.HttpServletResponse;
  41. import junit.framework.TestCase;
  42. import org.mortbay.jetty.Connector;
  43. import org.mortbay.jetty.Server;
  44. import org.mortbay.jetty.handler.AbstractHandler;
  45. import org.mortbay.jetty.security.SslSelectChannelConnector;
  46. import org.mortbay.jetty.servlet.ServletHandler;
  47. import org.mortbay.jetty.servlet.ServletHolder;
  48. import org.mortbay.util.IO;
  49. /**
  50. * HttpServer Tester.
  51. */
  52. public class SSLEngineTest extends TestCase
  53. {
  54. // ~ Static fields/initializers
  55. // ---------------------------------------------
  56. // Useful constants
  57. private static final int BODY_SIZE = 300;
  58. private static final String HELLO_WORLD="Hello world\r\n";
  59. private static final String JETTY_VERSION=Server.getVersion();
  60. private static final String PROTOCOL_VERSION="2.0";
  61. /** The request. */
  62. private static final String REQUEST0_HEADER="POST / HTTP/1.1\n"+"Host: localhost\n"+"Content-Type: text/xml\n"+"Content-Length: ";
  63. private static final String REQUEST1_HEADER="POST / HTTP/1.1\n"+"Host: localhost\n"+"Content-Type: text/xml\n"+"Connection: close\n"+"Content-Length: ";
  64. private static final String REQUEST_CONTENT="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
  65. +"<requests xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"+" xsi:noNamespaceSchemaLocation=\"commander.xsd\" version=\""
  66. +PROTOCOL_VERSION+"\">\n"+"</requests>";
  67. private static final String REQUEST0=REQUEST0_HEADER+REQUEST_CONTENT.getBytes().length+"\n\n"+REQUEST_CONTENT;
  68. private static final String REQUEST1=REQUEST1_HEADER+REQUEST_CONTENT.getBytes().length+"\n\n"+REQUEST_CONTENT;
  69. /** The expected response. */
  70. 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";
  71. private static final String RESPONSE1="HTTP/1.1 200 OK\n"+"Connection: close\n"+"Server: Jetty("+JETTY_VERSION+")\n"+'\n'+"Hello world\n";
  72. private static class CredulousTM implements TrustManager, X509TrustManager
  73. {
  74. public X509Certificate[] getAcceptedIssuers()
  75. {
  76. return null;
  77. }
  78. public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
  79. {
  80. return;
  81. }
  82. public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
  83. {
  84. return;
  85. }
  86. }
  87. private static final TrustManager[] s_dummyTrustManagers=new TrustManager[] { new CredulousTM() };
  88. /**
  89. * Feed the server the entire request at once.
  90. *
  91. * @throws Exception
  92. */
  93. public void testBigResponse() throws Exception
  94. {
  95. Server server=new Server();
  96. SslSelectChannelConnector connector=new SslSelectChannelConnector();
  97. String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
  98. connector.setPort(0);
  99. connector.setKeystore(keystore);
  100. connector.setPassword("storepwd");
  101. connector.setKeyPassword("keypwd");
  102. server.setConnectors(new Connector[]
  103. { connector });
  104. server.setHandler(new HelloWorldHandler());
  105. server.start();
  106. SSLContext ctx=SSLContext.getInstance("SSLv3");
  107. ctx.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
  108. int port=connector.getLocalPort();
  109. Socket client=ctx.getSocketFactory().createSocket("localhost",port);
  110. OutputStream os=client.getOutputStream();
  111. String request =
  112. "GET /?dump=102400 HTTP/1.1\r\n"+
  113. "Host: localhost:8080\r\n"+
  114. "Connection: close\r\n"+
  115. "\r\n";
  116. os.write(request.getBytes());
  117. os.flush();
  118. String response = IO.toString(client.getInputStream());
  119. System.err.println("response "+response.length());
  120. assertTrue(response.length()>102400);
  121. }
  122. // ~ Methods
  123. // ----------------------------------------------------------------
  124. /**
  125. * Feed the server the entire request at once.
  126. *
  127. * @throws Exception
  128. */
  129. public void testRequest1_jetty_https() throws Exception
  130. {
  131. Server server=new Server();
  132. SslSelectChannelConnector connector=new SslSelectChannelConnector();
  133. String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
  134. connector.setPort(0);
  135. connector.setKeystore(keystore);
  136. connector.setPassword("storepwd");
  137. connector.setKeyPassword("keypwd");
  138. server.setConnectors(new Connector[]
  139. { connector });
  140. server.setHandler(new HelloWorldHandler());
  141. final int numConns=200;
  142. Socket[] socket=new Socket[numConns];
  143. try
  144. {
  145. server.start();
  146. SSLContext ctx=SSLContext.getInstance("SSLv3");
  147. ctx.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
  148. int port=connector.getLocalPort();
  149. for (int i=0; i<numConns; ++i)
  150. {
  151. // System.err.println("write:"+i);
  152. socket[i]=ctx.getSocketFactory().createSocket("localhost",port);
  153. OutputStream os=socket[i].getOutputStream();
  154. os.write(REQUEST0.getBytes());
  155. os.write(REQUEST0.getBytes());
  156. os.flush();
  157. }
  158. for (int i=0; i<numConns; ++i)
  159. {
  160. // System.err.println("flush:"+i);
  161. OutputStream os=socket[i].getOutputStream();
  162. os.write(REQUEST1.getBytes());
  163. os.flush();
  164. }
  165. for (int i=0; i<numConns; ++i)
  166. {
  167. // System.err.println("read:"+i);
  168. // Read the response.
  169. String responses=readResponse(socket[i]);
  170. // Check the response
  171. assertEquals(String.format("responses %d",i),RESPONSE0+RESPONSE0+RESPONSE1,responses);
  172. }
  173. }
  174. finally
  175. {
  176. for (int i=0; i<numConns; ++i)
  177. {
  178. if (socket[i]!=null)
  179. {
  180. socket[i].close();
  181. }
  182. }
  183. server.stop();
  184. }
  185. }
  186. /**
  187. * Read entire response from the client. Close the output.
  188. *
  189. * @param client
  190. * Open client socket.
  191. *
  192. * @return The response string.
  193. *
  194. * @throws IOException
  195. */
  196. private static String readResponse(Socket client) throws IOException
  197. {
  198. BufferedReader br=null;
  199. try
  200. {
  201. br=new BufferedReader(new InputStreamReader(client.getInputStream()));
  202. StringBuilder sb=new StringBuilder(1000);
  203. String line;
  204. while ((line=br.readLine())!=null)
  205. {
  206. sb.append(line);
  207. sb.append('\n');
  208. }
  209. return sb.toString();
  210. }
  211. finally
  212. {
  213. if (br!=null)
  214. {
  215. br.close();
  216. }
  217. }
  218. }
  219. private static class HelloWorldHandler extends AbstractHandler
  220. {
  221. public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) throws IOException, ServletException
  222. {
  223. PrintWriter out=response.getWriter();
  224. try
  225. {
  226. out.print(HELLO_WORLD);
  227. if (request.getParameter("dump")!=null)
  228. {
  229. char[] buf = new char[Integer.valueOf(request.getParameter("dump"))];
  230. for (int i=0;i<buf.length;i++)
  231. buf[i]=(char)('0'+(i%10));
  232. out.write(buf);
  233. }
  234. }
  235. finally
  236. {
  237. out.close();
  238. }
  239. }
  240. }
  241. public void testServletPost() throws Exception
  242. {
  243. Server server=new Server();
  244. SslSelectChannelConnector connector=new SslSelectChannelConnector();
  245. String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
  246. connector.setPort(0);
  247. connector.setKeystore(keystore);
  248. connector.setPassword("storepwd");
  249. connector.setKeyPassword("keypwd");
  250. connector.setTruststore(keystore);
  251. connector.setTrustPassword("storepwd");
  252. server.setConnectors(new Connector[]
  253. { connector });
  254. ServletHandler handler = new ServletHandler();
  255. TestServlet servlet = new TestServlet();
  256. handler.addServletWithMapping(new ServletHolder(servlet),"/test");
  257. server.addHandler(handler);
  258. try
  259. {
  260. SSLContext context = SSLContext.getInstance("SSL");
  261. context.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
  262. HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
  263. server.start();
  264. URL url = new URL("https://localhost:"+connector.getLocalPort()+"/test");
  265. HttpURLConnection conn = (HttpURLConnection)url.openConnection();
  266. if (conn instanceof HttpsURLConnection)
  267. {
  268. ((HttpsURLConnection)conn).setHostnameVerifier(new HostnameVerifier()
  269. {
  270. public boolean verify(String urlHostName, SSLSession session)
  271. {
  272. return true;
  273. }
  274. });
  275. }
  276. conn.setConnectTimeout(10000);
  277. conn.setReadTimeout(100000);
  278. conn.setDoInput(true);
  279. conn.setDoOutput(true);
  280. conn.setRequestMethod("POST");
  281. conn.setRequestProperty("Content-Type","text/plain"); //$NON-NLS-1$
  282. conn.setChunkedStreamingMode(128);
  283. conn.connect();
  284. byte[] b = new byte[BODY_SIZE];
  285. for (int i = 0; i < BODY_SIZE; i++)
  286. {
  287. b[i] = 'x';
  288. }
  289. OutputStream os = conn.getOutputStream();
  290. os.write(b);
  291. os.flush();
  292. int rc = conn.getResponseCode();
  293. int len = 0;
  294. InputStream is = conn.getInputStream();
  295. int bytes=0;
  296. while ((len = is.read(b)) > -1)
  297. bytes+=len;
  298. is.close();
  299. assertEquals(BODY_SIZE,servlet.bytes);
  300. assertEquals(BODY_SIZE,bytes);
  301. }
  302. finally
  303. {
  304. server.stop();
  305. }
  306. }
  307. public static class TestServlet extends HttpServlet
  308. {
  309. public int bytes=0;
  310. @Override
  311. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
  312. {
  313. resp.setContentType("text/plain");
  314. resp.setBufferSize(128);
  315. byte[] b = new byte[BODY_SIZE];
  316. int len = 0;
  317. InputStream is = req.getInputStream();
  318. // !!!! UNDER HTTPS, FIRST CHUNK IS READ HERE BUT THEN SERVER IS
  319. // WAITING FOR
  320. // !!!! MORE DATA
  321. while ((len = is.read(b)) > -1)
  322. {
  323. bytes+=len;
  324. }
  325. OutputStream os = resp.getOutputStream();
  326. for (int i = 0; i < BODY_SIZE; i++)
  327. {
  328. b[i] = 'x';
  329. }
  330. os.write(b);
  331. resp.flushBuffer();
  332. }
  333. }
  334. }