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.service;
023:
024: import java.io.File;
025: import java.io.FileOutputStream;
026: import java.io.InputStream;
027: import java.io.IOException;
028: import java.net.JarURLConnection;
029: import java.net.Socket;
030: import java.net.URL;
031: import java.net.HttpURLConnection;
032: import java.net.MalformedURLException;
033: import java.security.Provider;
034: import java.security.Security;
035: import java.util.StringTokenizer;
036: import java.util.jar.JarEntry;
037: import java.util.jar.JarFile;
038: import javax.net.ssl.SSLSocketFactory;
039:
040: //import com.sun.net.ssl.internal.ssl.Provider;
041:
042: import org.jboss.logging.Logger;
043: import org.jboss.system.ServiceMBeanSupport;
044: import org.jboss.test.util.SecurityProviderUtil;
045: import org.jboss.invocation.http.interfaces.Util;
046:
047: /** A test mbean service that reads input from an https url passed in
048: to its readURL method.
049:
050: @author Scott.Stark@jboss.org
051: @version $Revision: 57211 $
052: */
053: public class HttpsClient extends ServiceMBeanSupport implements
054: HttpsClientMBean {
055: // Constants -----------------------------------------------------
056:
057: // Attributes ----------------------------------------------------
058: private boolean addedHttpsHandler;
059:
060: private boolean addedJSSEProvider;
061:
062: // Static --------------------------------------------------------
063:
064: // Constructors --------------------------------------------------
065: public HttpsClient() {
066: }
067:
068: public String getName() {
069: return "HttpsClient";
070: }
071:
072: /** Read the contents of the given URL and return it. */
073: public String readURL(String urlString) throws IOException {
074: try {
075: String reply = internalReadURL(urlString);
076: log.debug("readURL -> " + reply);
077: return reply;
078: } catch (Throwable e) {
079: log.error("Failed to readURL", e);
080: throw new IOException("Failed to readURL, ex="
081: + e.getMessage());
082: }
083: }
084:
085: private String internalReadURL(String urlString) throws Exception {
086: log.debug("Creating URL from string: " + urlString);
087: URL url = new URL(urlString);
088: log.debug("Created URL object from string, protocol="
089: + url.getProtocol());
090: HttpURLConnection conn = (HttpURLConnection) url
091: .openConnection();
092: /* Override the host verifier so we can use a test server cert with
093: a hostname that may not match the https url hostname.
094: */
095: System
096: .setProperty("org.jboss.security.ignoreHttpsHost",
097: "true");
098: Util.configureHttpsHostVerifier(conn);
099:
100: log.debug("Connecting to URL: " + url);
101: byte[] buffer = new byte[1024];
102: int length = conn.getContentLength();
103: log.debug("ContentLength: " + length);
104: InputStream is = conn.getInputStream();
105: StringBuffer reply = new StringBuffer();
106: while ((length = is.read(buffer)) > 0)
107: reply.append(new String(buffer, 0, length));
108: log.debug("Done, closing streams");
109: is.close();
110: return reply.toString();
111: }
112:
113: // Public --------------------------------------------------------
114: protected void startService() throws Exception {
115: addedJSSEProvider = false;
116: try {
117: new URL("https://www.https.test");
118: } catch (MalformedURLException e) {
119: // Install the default JSSE security provider
120: Provider provider = SecurityProviderUtil.getJSSEProvider();
121: log.debug("Adding " + provider.getName());
122:
123: //addedJSSEProvider = Security.addProvider(new Provider()) != -1;
124: addedJSSEProvider = Security.addProvider(provider) != -1;
125: if (addedJSSEProvider) {
126: log.debug("Added " + provider.getName());
127: }
128:
129: addedHttpsHandler = false;
130:
131: // Install the JSSE https handler if it has not already been added
132: String protocolHandler = SecurityProviderUtil
133: .getProtocolHandlerName();
134: String handlers = System
135: .getProperty("java.protocol.handler.pkgs");
136: if (handlers == null
137: || handlers.indexOf(protocolHandler) < 0) {
138: handlers += "|" + protocolHandler;
139: log
140: .debug("Adding https handler to java.protocol.handler.pkgs");
141: System.setProperty("java.protocol.handler.pkgs",
142: handlers);
143: addedHttpsHandler = true;
144: }
145: }
146:
147: // Install the trust store
148: ClassLoader loader = Thread.currentThread()
149: .getContextClassLoader();
150: URL keyStoreURL = loader.getResource("META-INF/tst.keystore");
151: if (keyStoreURL == null)
152: throw new IOException(
153: "Failed to find resource tst.keystore");
154: if (keyStoreURL.getProtocol().equals("jar")) {
155: JarURLConnection conn = (JarURLConnection) keyStoreURL
156: .openConnection();
157: JarFile jar = conn.getJarFile();
158: JarEntry entry = jar.getJarEntry("META-INF/tst.keystore");
159: InputStream is = jar.getInputStream(entry);
160: File tmp = File.createTempFile("tst-", ".keystore");
161: tmp.deleteOnExit();
162: FileOutputStream fos = new FileOutputStream(tmp);
163: byte[] buffer = new byte[1024];
164: int bytes;
165: while ((bytes = is.read(buffer)) > 0)
166: fos.write(buffer, 0, bytes);
167: fos.close();
168: is.close();
169: keyStoreURL = tmp.toURL();
170: }
171: log.debug("Setting javax.net.ssl.trustStore to: "
172: + keyStoreURL.getPath());
173: System.setProperty("javax.net.ssl.trustStore", keyStoreURL
174: .getPath());
175: }
176:
177: protected void stopService() throws Exception {
178: if (addedJSSEProvider) {
179: //String name = (new Provider()).getName();
180: Provider provider = SecurityProviderUtil.getJSSEProvider();
181: String name = provider.getName();
182: log.debug("Removing " + name);
183: Security.removeProvider(name);
184: }
185: if (addedHttpsHandler == true) {
186: log
187: .debug("Removing https handler from java.protocol.handler.pkgs");
188: String protocolHandler = SecurityProviderUtil
189: .getProtocolHandlerName();
190: String handlers = System
191: .getProperty("java.protocol.handler.pkgs");
192: StringTokenizer tokenizer = new StringTokenizer(handlers,
193: "|");
194: StringBuffer buffer = new StringBuffer();
195: while (tokenizer.hasMoreTokens()) {
196: String handler = tokenizer.nextToken();
197: if (handler.equals(protocolHandler) == false) {
198: buffer.append('|');
199: buffer.append(handler);
200: }
201: }
202: System.setProperty("java.protocol.handler.pkgs", buffer
203: .toString());
204: }
205: }
206:
207: /** A SSLSocketFactory that logs the createSocket calls.
208: */
209: class DebugSSLSocketFactory extends SSLSocketFactory {
210: SSLSocketFactory factoryDelegate;
211: Logger theLog;
212:
213: DebugSSLSocketFactory(SSLSocketFactory factoryDelegate,
214: Logger theLog) {
215: this .factoryDelegate = factoryDelegate;
216: this .theLog = theLog;
217: }
218:
219: public Socket createSocket(java.net.InetAddress host, int port)
220: throws java.io.IOException {
221: theLog.debug("createSocket, host=" + host + ", port="
222: + port);
223: Socket s = factoryDelegate.createSocket(host, port);
224: theLog.debug("created socket=" + s);
225: return s;
226: }
227:
228: public Socket createSocket(String host, int port)
229: throws java.io.IOException,
230: java.net.UnknownHostException {
231: theLog.debug("createSocket, host=" + host + ", port="
232: + port);
233: Socket s = factoryDelegate.createSocket(host, port);
234: theLog.debug("created socket=" + s);
235: return s;
236: }
237:
238: public Socket createSocket(Socket socket, String host,
239: int port, boolean autoClose) throws java.io.IOException {
240: theLog.debug("createSocket, socket=" + socket + ", host="
241: + host + ", port=" + port);
242: Socket s = factoryDelegate.createSocket(socket, host, port,
243: autoClose);
244: theLog.debug("created socket=" + s);
245: return s;
246: }
247:
248: public Socket createSocket(java.net.InetAddress host, int port,
249: java.net.InetAddress clientAddress, int clientPort)
250: throws java.io.IOException {
251: theLog.debug("createSocket, host=" + host + ", port="
252: + port + ", clientAddress=" + clientAddress
253: + ", clientPort=" + clientPort);
254: Socket s = factoryDelegate.createSocket(host, port,
255: clientAddress, clientPort);
256: theLog.debug("created socket=" + s);
257: return s;
258: }
259:
260: public Socket createSocket(String host, int port,
261: java.net.InetAddress clientAddress, int clientPort)
262: throws java.io.IOException,
263: java.net.UnknownHostException {
264: theLog.debug("createSocket, host=" + host + ", port="
265: + port + ", addr=" + clientAddress);
266: Socket s = factoryDelegate.createSocket(host, port,
267: clientAddress, clientPort);
268: theLog.debug("created socket=" + s);
269: return s;
270: }
271:
272: public String[] getDefaultCipherSuites() {
273: return factoryDelegate.getDefaultCipherSuites();
274: }
275:
276: public String[] getSupportedCipherSuites() {
277: return factoryDelegate.getSupportedCipherSuites();
278: }
279: }
280: }
|