001: /*
002: * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/contrib/org/apache/commons/httpclient/contrib/ssl/EasySSLProtocolSocketFactory.java,v 1.7 2004/06/11 19:26:27 olegk Exp $
003: * $Revision: 480424 $
004: * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
005: *
006: * ====================================================================
007: *
008: * Licensed to the Apache Software Foundation (ASF) under one or more
009: * contributor license agreements. See the NOTICE file distributed with
010: * this work for additional information regarding copyright ownership.
011: * The ASF licenses this file to You under the Apache License, Version 2.0
012: * (the "License"); you may not use this file except in compliance with
013: * the License. You may obtain a copy of the License at
014: *
015: * http://www.apache.org/licenses/LICENSE-2.0
016: *
017: * Unless required by applicable law or agreed to in writing, software
018: * distributed under the License is distributed on an "AS IS" BASIS,
019: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020: * See the License for the specific language governing permissions and
021: * limitations under the License.
022: * ====================================================================
023: *
024: * This software consists of voluntary contributions made by many
025: * individuals on behalf of the Apache Software Foundation. For more
026: * information on the Apache Software Foundation, please see
027: * <http://www.apache.org/>.
028: *
029: */
030:
031: package org.apache.commons.httpclient.contrib.ssl;
032:
033: import java.io.IOException;
034: import java.net.InetAddress;
035: import java.net.InetSocketAddress;
036: import java.net.Socket;
037: import java.net.SocketAddress;
038: import java.net.UnknownHostException;
039:
040: import org.apache.commons.httpclient.ConnectTimeoutException;
041: import org.apache.commons.httpclient.HttpClientError;
042: import org.apache.commons.httpclient.params.HttpConnectionParams;
043: import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
044: import org.apache.commons.logging.Log;
045: import org.apache.commons.logging.LogFactory;
046:
047: import javax.net.SocketFactory;
048: import javax.net.ssl.SSLContext;
049: import javax.net.ssl.TrustManager;
050:
051: /**
052: * <p>
053: * EasySSLProtocolSocketFactory can be used to creats SSL {@link Socket}s
054: * that accept self-signed certificates.
055: * </p>
056: * <p>
057: * This socket factory SHOULD NOT be used for productive systems
058: * due to security reasons, unless it is a concious decision and
059: * you are perfectly aware of security implications of accepting
060: * self-signed certificates
061: * </p>
062: *
063: * <p>
064: * Example of using custom protocol socket factory for a specific host:
065: * <pre>
066: * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
067: *
068: * HttpClient client = new HttpClient();
069: * client.getHostConfiguration().setHost("localhost", 443, easyhttps);
070: * // use relative url only
071: * GetMethod httpget = new GetMethod("/");
072: * client.executeMethod(httpget);
073: * </pre>
074: * </p>
075: * <p>
076: * Example of using custom protocol socket factory per default instead of the standard one:
077: * <pre>
078: * Protocol easyhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
079: * Protocol.registerProtocol("https", easyhttps);
080: *
081: * HttpClient client = new HttpClient();
082: * GetMethod httpget = new GetMethod("https://localhost/");
083: * client.executeMethod(httpget);
084: * </pre>
085: * </p>
086: *
087: * @author <a href="mailto:oleg -at- ural.ru">Oleg Kalnichevski</a>
088: *
089: * <p>
090: * DISCLAIMER: HttpClient developers DO NOT actively support this component.
091: * The component is provided as a reference material, which may be inappropriate
092: * for use without additional customization.
093: * </p>
094: */
095:
096: public class EasySSLProtocolSocketFactory implements
097: SecureProtocolSocketFactory {
098:
099: /** Log object for this class. */
100: private static final Log LOG = LogFactory
101: .getLog(EasySSLProtocolSocketFactory.class);
102:
103: private SSLContext sslcontext = null;
104:
105: /**
106: * Constructor for EasySSLProtocolSocketFactory.
107: */
108: public EasySSLProtocolSocketFactory() {
109: super ();
110: }
111:
112: private static SSLContext createEasySSLContext() {
113: try {
114: SSLContext context = SSLContext.getInstance("SSL");
115: context
116: .init(
117: null,
118: new TrustManager[] { new EasyX509TrustManager(
119: null) }, null);
120: return context;
121: } catch (Exception e) {
122: LOG.error(e.getMessage(), e);
123: throw new HttpClientError(e.toString());
124: }
125: }
126:
127: private SSLContext getSSLContext() {
128: if (this .sslcontext == null) {
129: this .sslcontext = createEasySSLContext();
130: }
131: return this .sslcontext;
132: }
133:
134: /**
135: * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int,java.net.InetAddress,int)
136: */
137: public Socket createSocket(String host, int port,
138: InetAddress clientHost, int clientPort) throws IOException,
139: UnknownHostException {
140:
141: return getSSLContext().getSocketFactory().createSocket(host,
142: port, clientHost, clientPort);
143: }
144:
145: /**
146: * Attempts to get a new socket connection to the given host within the given time limit.
147: * <p>
148: * To circumvent the limitations of older JREs that do not support connect timeout a
149: * controller thread is executed. The controller thread attempts to create a new socket
150: * within the given limit of time. If socket constructor does not return until the
151: * timeout expires, the controller terminates and throws an {@link ConnectTimeoutException}
152: * </p>
153: *
154: * @param host the host name/IP
155: * @param port the port on the host
156: * @param clientHost the local host name/IP to bind the socket to
157: * @param clientPort the port on the local machine
158: * @param params {@link HttpConnectionParams Http connection parameters}
159: *
160: * @return Socket a new socket
161: *
162: * @throws IOException if an I/O error occurs while creating the socket
163: * @throws UnknownHostException if the IP address of the host cannot be
164: * determined
165: */
166: public Socket createSocket(final String host, final int port,
167: final InetAddress localAddress, final int localPort,
168: final HttpConnectionParams params) throws IOException,
169: UnknownHostException, ConnectTimeoutException {
170: if (params == null) {
171: throw new IllegalArgumentException(
172: "Parameters may not be null");
173: }
174: int timeout = params.getConnectionTimeout();
175: SocketFactory socketfactory = getSSLContext()
176: .getSocketFactory();
177: if (timeout == 0) {
178: return socketfactory.createSocket(host, port, localAddress,
179: localPort);
180: } else {
181: Socket socket = socketfactory.createSocket();
182: SocketAddress localaddr = new InetSocketAddress(
183: localAddress, localPort);
184: SocketAddress remoteaddr = new InetSocketAddress(host, port);
185: socket.bind(localaddr);
186: socket.connect(remoteaddr, timeout);
187: return socket;
188: }
189: }
190:
191: /**
192: * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
193: */
194: public Socket createSocket(String host, int port)
195: throws IOException, UnknownHostException {
196: return getSSLContext().getSocketFactory().createSocket(host,
197: port);
198: }
199:
200: /**
201: * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
202: */
203: public Socket createSocket(Socket socket, String host, int port,
204: boolean autoClose) throws IOException, UnknownHostException {
205: return getSSLContext().getSocketFactory().createSocket(socket,
206: host, port, autoClose);
207: }
208:
209: public boolean equals(Object obj) {
210: return ((obj != null) && obj.getClass().equals(
211: EasySSLProtocolSocketFactory.class));
212: }
213:
214: public int hashCode() {
215: return EasySSLProtocolSocketFactory.class.hashCode();
216: }
217:
218: }
|