001 /*
002 * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.net.ssl;
027
028 import java.net.*;
029 import javax.net.SocketFactory;
030 import java.io.IOException;
031 import java.security.*;
032
033 import sun.security.action.GetPropertyAction;
034
035 /**
036 * <code>SSLSocketFactory</code>s create <code>SSLSocket</code>s.
037 *
038 * @since 1.4
039 * @see SSLSocket
040 * @version 1.32
041 * @author David Brownell
042 */
043 public abstract class SSLSocketFactory extends SocketFactory {
044 private static SSLSocketFactory theFactory;
045
046 private static boolean propertyChecked;
047
048 static final boolean DEBUG;
049
050 static {
051 String s = java.security.AccessController.doPrivileged(
052 new GetPropertyAction("javax.net.debug", ""))
053 .toLowerCase();
054 DEBUG = s.contains("all") || s.contains("ssl");
055 }
056
057 private static void log(String msg) {
058 if (DEBUG) {
059 System.out.println(msg);
060 }
061 }
062
063 /**
064 * Constructor is used only by subclasses.
065 */
066 public SSLSocketFactory() {
067 }
068
069 /**
070 * Returns the default SSL socket factory.
071 *
072 * <p>The first time this method is called, the security property
073 * "ssl.SocketFactory.provider" is examined. If it is non-null, a class by
074 * that name is loaded and instantiated. If that is successful and the
075 * object is an instance of SSLSocketFactory, it is made the default SSL
076 * socket factory.
077 *
078 * <p>Otherwise, this method returns
079 * <code>SSLContext.getDefault().getSocketFactory()</code>. If that
080 * call fails, an inoperative factory is returned.
081 *
082 * @return the default <code>SocketFactory</code>
083 * @see SSLContext#getDefault
084 */
085 public static synchronized SocketFactory getDefault() {
086 if (theFactory != null) {
087 return theFactory;
088 }
089
090 if (propertyChecked == false) {
091 propertyChecked = true;
092 String clsName = getSecurityProperty("ssl.SocketFactory.provider");
093 if (clsName != null) {
094 log("setting up default SSLSocketFactory");
095 try {
096 Class cls = null;
097 try {
098 cls = Class.forName(clsName);
099 } catch (ClassNotFoundException e) {
100 ClassLoader cl = ClassLoader
101 .getSystemClassLoader();
102 if (cl != null) {
103 cls = cl.loadClass(clsName);
104 }
105 }
106 log("class " + clsName + " is loaded");
107 SSLSocketFactory fac = (SSLSocketFactory) cls
108 .newInstance();
109 log("instantiated an instance of class " + clsName);
110 theFactory = fac;
111 return fac;
112 } catch (Exception e) {
113 log("SSLSocketFactory instantiation failed: "
114 + e.toString());
115 theFactory = new DefaultSSLSocketFactory(e);
116 return theFactory;
117 }
118 }
119 }
120
121 try {
122 return SSLContext.getDefault().getSocketFactory();
123 } catch (NoSuchAlgorithmException e) {
124 return new DefaultSSLSocketFactory(e);
125 }
126 }
127
128 static String getSecurityProperty(final String name) {
129 return AccessController
130 .doPrivileged(new PrivilegedAction<String>() {
131 public String run() {
132 String s = java.security.Security
133 .getProperty(name);
134 if (s != null) {
135 s = s.trim();
136 if (s.length() == 0) {
137 s = null;
138 }
139 }
140 return s;
141 }
142 });
143 }
144
145 /**
146 * Returns the list of cipher suites which are enabled by default.
147 * Unless a different list is enabled, handshaking on an SSL connection
148 * will use one of these cipher suites. The minimum quality of service
149 * for these defaults requires confidentiality protection and server
150 * authentication (that is, no anonymous cipher suites).
151 *
152 * @see #getSupportedCipherSuites()
153 * @return array of the cipher suites enabled by default
154 */
155 public abstract String[] getDefaultCipherSuites();
156
157 /**
158 * Returns the names of the cipher suites which could be enabled for use
159 * on an SSL connection. Normally, only a subset of these will actually
160 * be enabled by default, since this list may include cipher suites which
161 * do not meet quality of service requirements for those defaults. Such
162 * cipher suites are useful in specialized applications.
163 *
164 * @see #getDefaultCipherSuites()
165 * @return an array of cipher suite names
166 */
167 public abstract String[] getSupportedCipherSuites();
168
169 /**
170 * Returns a socket layered over an existing socket connected to the named
171 * host, at the given port. This constructor can be used when tunneling SSL
172 * through a proxy or when negotiating the use of SSL over an existing
173 * socket. The host and port refer to the logical peer destination.
174 * This socket is configured using the socket options established for
175 * this factory.
176 *
177 * @param s the existing socket
178 * @param host the server host
179 * @param port the server port
180 * @param autoClose close the underlying socket when this socket is closed
181 * @return a socket connected to the specified host and port
182 * @throws IOException if an I/O error occurs when creating the socket
183 * @throws NullPointerException if the parameter s is null
184 */
185 public abstract Socket createSocket(Socket s, String host,
186 int port, boolean autoClose) throws IOException;
187 }
188
189 // file private
190 class DefaultSSLSocketFactory extends SSLSocketFactory {
191 private Exception reason;
192
193 DefaultSSLSocketFactory(Exception reason) {
194 this .reason = reason;
195 }
196
197 private Socket throwException() throws SocketException {
198 throw (SocketException) new SocketException(reason.toString())
199 .initCause(reason);
200 }
201
202 public Socket createSocket() throws IOException {
203 return throwException();
204 }
205
206 public Socket createSocket(String host, int port)
207 throws IOException {
208 return throwException();
209 }
210
211 public Socket createSocket(Socket s, String host, int port,
212 boolean autoClose) throws IOException {
213 return throwException();
214 }
215
216 public Socket createSocket(InetAddress address, int port)
217 throws IOException {
218 return throwException();
219 }
220
221 public Socket createSocket(String host, int port,
222 InetAddress clientAddress, int clientPort)
223 throws IOException {
224 return throwException();
225 }
226
227 public Socket createSocket(InetAddress address, int port,
228 InetAddress clientAddress, int clientPort)
229 throws IOException {
230 return throwException();
231 }
232
233 public String[] getDefaultCipherSuites() {
234 return new String[0];
235 }
236
237 public String[] getSupportedCipherSuites() {
238 return new String[0];
239 }
240 }
|