KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > soap > util > net > SSLUtils


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2000 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "SOAP" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 2000, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.apache.soap.util.net;
59
60 import java.net.*;
61 import java.io.*;
62 import java.util.*;
63 import javax.net.ssl.*;
64 import java.security.*;
65
66 /**
67  * A bunch of utility stuff for doing SSL things.
68  *
69  * @author Chris Nelson (cnelson@synchrony.net)
70  */

71 public class SSLUtils {
72         static String JavaDoc tunnelHost;
73         static int tunnelPort;
74     
75     /** This method builds an SSL socket, after auto-starting SSL */
76     public static Socket buildSSLSocket(String JavaDoc host, int port, String JavaDoc httpProxyHost,
77                                             int httpProxyPort)
78         throws IOException, UnknownHostException
79     {
80            SSLSocket sslSocket = null;
81            SSLSocketFactory factory =
82               (SSLSocketFactory)SSLSocketFactory.getDefault();
83
84            // Determine if a proxy should be used. Use system properties if set
85
// Otherwise use http proxy. If neither is set, dont use a proxy
86
tunnelHost = System.getProperty("https.proxyHost");
87            tunnelPort = Integer.getInteger("https.proxyPort", 80).intValue();
88
89            if (tunnelHost==null) {
90               // Try to use http proxy instead
91
tunnelHost = httpProxyHost;
92               tunnelPort = httpProxyPort;
93            }
94
95            /*
96            System.out.println("https proxyHost=" + tunnelHost +
97                               " proxyPort=" + tunnelPort +
98                               " host=" + host +
99                               " port=" + port);
100            */

101
102            /*
103             * If a proxy has been set...
104             * Set up a socket to do tunneling through the proxy.
105             * Start it off as a regular socket, then layer SSL
106             * over the top of it.
107             */

108            if (tunnelHost==null) {
109               sslSocket = (SSLSocket)factory.createSocket(host, port);
110            } else {
111               Socket tunnel = new Socket(tunnelHost, tunnelPort);
112               doTunnelHandshake(tunnel, host, port);
113
114               // Overlay tunnel socket with SSL
115
sslSocket = (SSLSocket)factory.createSocket(tunnel, host, port, true);
116            }
117
118            /*
119             * Handshaking is started manually in this example because
120             * PrintWriter catches all IOExceptions (including
121             * SSLExceptions), sets an internal error flag, and then
122             * returns without rethrowing the exception.
123             *
124             * Unfortunately, this means any error messages are lost,
125             * which caused lots of confusion for others using this
126             * code. The only way to tell there was an error is to call
127             * PrintWriter.checkError().
128             */

129            sslSocket.startHandshake();
130
131            return sslSocket;
132         
133     }
134
135         static private void doTunnelHandshake(Socket tunnel, String JavaDoc host, int port)
136          throws IOException
137         {
138              OutputStream out = tunnel.getOutputStream();
139              String JavaDoc msg = "CONNECT " + host + ":" + port + " HTTP/1.0\n"
140                           + "User-Agent: "
141                           + sun.net.www.protocol.http.HttpURLConnection.userAgent
142                           + "\r\n\r\n";
143              byte b[];
144              try {
145                  /*
146                   * We really do want ASCII7 -- the http protocol doesn't change
147                   * with locale.
148                   */

149                  b = msg.getBytes("ASCII7");
150              } catch (UnsupportedEncodingException ignored) {
151                  /*
152                   * If ASCII7 isn't there, something serious is wrong, but
153                   * Paranoia Is Good (tm)
154                   */

155                  b = msg.getBytes();
156              }
157              out.write(b);
158              out.flush();
159
160              /*
161               * We need to store the reply so we can create a detailed
162               * error message to the user.
163               */

164              byte reply[] = new byte[200];
165              int replyLen = 0;
166              int newlinesSeen = 0;
167              boolean headerDone = false; /* Done on first newline */
168
169              InputStream in = tunnel.getInputStream();
170              boolean error = false;
171
172              while (newlinesSeen < 2) {
173                  int i = in.read();
174                  if (i < 0) {
175                      throw new IOException("Unexpected EOF from proxy");
176                  }
177                  if (i == '\n') {
178                      headerDone = true;
179                      ++newlinesSeen;
180                  } else if (i != '\r') {
181                      newlinesSeen = 0;
182                      if (!headerDone && replyLen < reply.length) {
183                          reply[replyLen++] = (byte) i;
184                      }
185                  }
186              }
187
188              /*
189               * Converting the byte array to a string is slightly wasteful
190               * in the case where the connection was successful, but it's
191               * insignificant compared to the network overhead.
192               */

193              String JavaDoc replyStr;
194              try {
195                  replyStr = new String JavaDoc(reply, 0, replyLen, "ASCII7");
196              } catch (UnsupportedEncodingException ignored) {
197                  replyStr = new String JavaDoc(reply, 0, replyLen);
198              }
199
200              // Parse response, check for status code
201
StringTokenizer st = new StringTokenizer(replyStr);
202              st.nextToken(); // ignore version part
203
if (!st.nextToken().startsWith("200")) {
204                 throw new IOException("Unable to tunnel through "
205                         + tunnelHost + ":" + tunnelPort
206                         + ". Proxy returns \"" + replyStr + "\"");
207              }
208
209              /* tunneling Handshake was successful! */
210          }
211 }
212
Popular Tags