001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.test.security.test;
023:
024: import javax.net.ssl.KeyManagerFactory;
025: import javax.net.ssl.SSLContext;
026: import javax.net.ssl.TrustManager;
027: import javax.net.ssl.TrustManagerFactory;
028:
029: import java.io.InputStream;
030: import java.io.IOException;
031: import java.io.OutputStream;
032: import java.net.InetAddress;
033: import java.net.ServerSocket;
034: import java.net.Socket;
035: import java.net.URL;
036: import java.security.KeyStore;
037: import java.security.Security;
038: import java.text.SimpleDateFormat;
039: import java.util.Date;
040: import java.util.TimeZone;
041: import javax.management.ObjectName;
042: import javax.net.ServerSocketFactory;
043: import javax.net.ssl.SSLServerSocket;
044: import javax.net.ssl.SSLServerSocketFactory;
045:
046: import junit.extensions.TestSetup;
047: import junit.framework.Test;
048: import junit.framework.TestSuite;
049:
050: import org.apache.log4j.Category;
051: import org.jboss.test.JBossTestCase;
052: import org.jboss.test.JBossTestSetup;
053: import org.jboss.test.util.SecurityProviderUtil;
054:
055: /** Test of using https urls inside of the JBoss server. This testcase
056: creates a simple https server and deploys a service that tries to
057: connect to the server using the https url passed to the service.
058:
059: @author Scott.Stark@jboss.org
060: @version $Revision: 57211 $
061: */
062: public class HttpsUnitTestCase extends JBossTestCase {
063: static final String JAR = "https-service.sar";
064: static final String KEYSTORE_PASSWORD = "unit-tests";
065:
066: public HttpsUnitTestCase(String name) {
067: super (name);
068: }
069:
070: /** Test the JSSE installation
071: */
072: public void testJSSE() throws Exception {
073: log.debug("+++ testJSSE");
074: ServerSocketFactory factory = SSLServerSocketFactory
075: .getDefault();
076: SSLServerSocket sslSocket = (SSLServerSocket) factory
077: .createServerSocket(0);
078: int port = sslSocket.getLocalPort();
079:
080: String[] cipherSuites = sslSocket.getEnabledCipherSuites();
081: for (int i = 0; i < cipherSuites.length; i++) {
082: getLog().debug(
083: "Cipher Suite " + i + " = " + cipherSuites[i]);
084: }
085: sslSocket.close();
086: }
087:
088: /** Test a login against the SRP service using the SRPLoginModule
089: */
090: public void testHttpsURL() throws Exception {
091: log.debug("+++ testHttpsURL");
092: // Setup the SSL listening port
093: String httpsURL = initServer();
094: log.debug("Setup SSL socket, URL=" + httpsURL);
095: // Have the service in JBoss use the https url
096: ObjectName name = new ObjectName(
097: "jboss.security.tests:service=HttpsClient");
098: String method = "readURL";
099: Object[] args = { httpsURL };
100: String[] sig = { "java.lang.String" };
101: String reply = (String) invoke(name, method, args, sig);
102: log.debug("Reply for url=" + httpsURL + " is: " + reply);
103: }
104:
105: private String initServer() throws Exception {
106: String httpsURL = null;
107: SSLContext sslCtx = null;
108: try {
109: sslCtx = SSLContext.getInstance("TLS");
110: ClassLoader loader = getClass().getClassLoader();
111: URL keyStoreURL = loader.getResource("tst.keystore");
112: if (keyStoreURL == null)
113: throw new IOException(
114: "Failed to find resource tst.keystore");
115: log.debug("Opening KeyStore: " + keyStoreURL);
116: KeyStore keyStore = KeyStore.getInstance("JKS");
117: InputStream is = keyStoreURL.openStream();
118: keyStore.load(is, KEYSTORE_PASSWORD.toCharArray());
119: String algorithm = KeyManagerFactory.getDefaultAlgorithm();
120: KeyManagerFactory keyMgr = KeyManagerFactory
121: .getInstance(algorithm);
122: keyMgr.init(keyStore, KEYSTORE_PASSWORD.toCharArray());
123: algorithm = TrustManagerFactory.getDefaultAlgorithm();
124: TrustManagerFactory trustMgr = TrustManagerFactory
125: .getInstance(algorithm);
126: trustMgr.init(keyStore);
127: TrustManager[] trustMgrs = trustMgr.getTrustManagers();
128: sslCtx.init(keyMgr.getKeyManagers(), trustMgrs, null);
129: } catch (Exception e) {
130: log.error("Failed to init SSLContext", e);
131: throw new IOException(
132: "Failed to get SSLContext for TLS algorithm");
133: }
134:
135: ServerSocketFactory factory = sslCtx.getServerSocketFactory();
136: ServerSocket serverSocket = factory.createServerSocket(0);
137: getLog().debug("Created serverSocket: " + serverSocket);
138: int port = serverSocket.getLocalPort();
139: InetAddress addr = serverSocket.getInetAddress();
140: httpsURL = "https://" + getServerHost() + ":" + port + '/';
141: AcceptThread thread = new AcceptThread(serverSocket, getLog(),
142: httpsURL);
143: synchronized (httpsURL) {
144: log.debug("Starting server socket thread");
145: thread.start();
146: log.debug("Waiting for accept thread notify");
147: httpsURL.wait();
148: }
149: return httpsURL;
150: }
151:
152: /**
153: * Setup the test suite.
154: */
155: public static Test suite() throws Exception {
156: TestSuite suite = new TestSuite();
157: suite.addTest(new TestSuite(HttpsUnitTestCase.class));
158:
159: // Create an initializer for the test suite
160: TestSetup wrapper = new JBossTestSetup(suite) {
161: protected void setUp() throws Exception {
162: super .setUp();
163: deploy(JAR);
164: //Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
165: Security.addProvider(SecurityProviderUtil
166: .getJSSEProvider());
167: }
168:
169: protected void tearDown() throws Exception {
170: undeploy(JAR);
171: super .tearDown();
172: }
173: };
174: return wrapper;
175: }
176:
177: /** A subclass of Thread that processes a single request sent to
178: the serverSocket.
179: */
180: static class AcceptThread extends Thread {
181: ServerSocket serverSocket;
182: Category log;
183: Object lock;
184:
185: AcceptThread(ServerSocket serverSocket, Category log,
186: Object lock) {
187: super ("AcceptThread");
188: super .setDaemon(true);
189: this .serverSocket = serverSocket;
190: this .log = log;
191: this .lock = lock;
192: }
193:
194: public void run() {
195: SimpleDateFormat fmt = new SimpleDateFormat(
196: "E, dd MMM yyyy HH:mm:ss z");
197: fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
198: Date now = new Date();
199: String dateString = fmt.format(now);
200: String content = "<html><head><title>HttpsUnitTestCase</title></head>"
201: + "<body>" + dateString + "</body></html>\r\n";
202: String reply = "HTTP/1.1 200 OK\r\n" + "Date: "
203: + dateString + "\r\n"
204: + "Server: HttpsUnitTestCase/JSSE SSL\r\n"
205: + "Last-Modified: " + dateString + "\r\n"
206: + "Content-Length: " + content.length() + "\r\n"
207: + "Connection: close\r\n"
208: + "Content-Type: text/html\r\n\r\n" + content;
209:
210: while (true) {
211: try {
212: log.debug("Waiting for client connection");
213: synchronized (lock) {
214: lock.notify();
215: }
216: Socket client = serverSocket.accept();
217: log.debug("Accepted client: " + client);
218: InputStream is = client.getInputStream();
219: OutputStream os = client.getOutputStream();
220: byte[] buffer = new byte[4096];
221: int bytes = is.read(buffer);
222: log.debug("Read: " + bytes);
223: os.write(reply.getBytes());
224: os.flush();
225: log.debug("Wrote: " + reply.length());
226: log.debug("ReplyData: " + reply);
227: os.close();
228: is.close();
229: client.close();
230: log.debug("Closed client");
231: } catch (Exception e) {
232: log.error("Failed to process request", e);
233: break;
234: }
235: }
236:
237: try {
238: serverSocket.close();
239: } catch (Exception e) {
240: log.error("Failed to close server socket", e);
241: }
242: }
243: }
244: }
|