dug 01/08/21 12:22:35
Modified: java/src/org/apache/soap/util/net HTTPUtils.java
SSLUtils.java
Log:
Add HTTPS proxy support (by David Melgar - [EMAIL PROTECTED])
Revision Changes Path
1.23 +13 -11 xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java
Index: HTTPUtils.java
===================================================================
RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/util/net/HTTPUtils.java,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- HTTPUtils.java 2001/08/02 00:20:14 1.22
+++ HTTPUtils.java 2001/08/21 19:22:35 1.23
@@ -99,26 +99,24 @@
throws Exception {
Socket s = null;
String host = null;
- int port;
-
- if (httpProxyHost == null) {
- host = url.getHost();
- port = targetPort;
- } else {
- host = httpProxyHost;
- port = httpProxyPort;
- }
+ int port = targetPort;
+ host = url.getHost();
if (url.getProtocol().equalsIgnoreCase("HTTPS")) {
// Using reflection to avoid compile time dependencies
Class SSLUtilsClass =
Class.forName("org.apache.soap.util.net.SSLUtils");
- Class[] paramTypes = new Class[] {String.class, int.class};
+ Class[] paramTypes = new Class[] {String.class, int.class, String.class,
int.class};
Method buildSSLSocket = SSLUtilsClass.getMethod(
"buildSSLSocket", paramTypes);
- Object[] params = new Object[] {host, new Integer(port)};
+ Object[] params = new Object[] {host, new Integer(port),
+ httpProxyHost, new Integer(httpProxyPort)};
s = (Socket)buildSSLSocket.invoke(null, params);
} else {
+ if (httpProxyHost != null) {
+ host = httpProxyHost;
+ port = httpProxyPort;
+ }
s = new Socket(host, port);
}
@@ -193,6 +191,10 @@
port = getPort(url);
s = buildSocket(url, port, httpProxyHost, httpProxyPort);
+ if (url.getProtocol().equalsIgnoreCase("HTTPS")) {
+ // Ignore proxy from now on. Buildsocket takes handles it
+ httpProxyHost = null;
+ }
if (timeout > 0) // Should be redundant but not every JVM likes this
s.setSoTimeout(timeout);
1.4 +134 -21 xml-soap/java/src/org/apache/soap/util/net/SSLUtils.java
Index: SSLUtils.java
===================================================================
RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/util/net/SSLUtils.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SSLUtils.java 2001/02/12 07:02:26 1.3
+++ SSLUtils.java 2001/08/21 19:22:35 1.4
@@ -69,30 +69,143 @@
* @author Chris Nelson ([EMAIL PROTECTED])
*/
public class SSLUtils {
+ static String tunnelHost;
+ static int tunnelPort;
/** This method builds an SSL socket, after auto-starting SSL */
- public static Socket buildSSLSocket(String host, int port)
+ public static Socket buildSSLSocket(String host, int port, String
httpProxyHost,
+ int httpProxyPort)
throws IOException, UnknownHostException
{
- SSLSocketFactory factory =
- (SSLSocketFactory)SSLSocketFactory.getDefault();
- SSLSocket sslSocket =
- (SSLSocket)factory.createSocket(host, port);
-
- /*
- * Handshaking is started manually in this example because
- * PrintWriter catches all IOExceptions (including
- * SSLExceptions), sets an internal error flag, and then
- * returns without rethrowing the exception.
- *
- * Unfortunately, this means any error messages are lost,
- * which caused lots of confusion for others using this
- * code. The only way to tell there was an error is to call
- * PrintWriter.checkError().
- */
- sslSocket.startHandshake();
-
- return sslSocket;
+ SSLSocket sslSocket = null;
+ SSLSocketFactory factory =
+ (SSLSocketFactory)SSLSocketFactory.getDefault();
+
+ // Determine if a proxy should be used. Use system properties if set
+ // Otherwise use http proxy. If neither is set, dont use a proxy
+ tunnelHost = System.getProperty("https.proxyHost");
+ tunnelPort = Integer.getInteger("https.proxyPort", 80).intValue();
+
+ if (tunnelHost==null) {
+ // Try to use http proxy instead
+ tunnelHost = httpProxyHost;
+ tunnelPort = httpProxyPort;
+ }
+
+ /*
+ System.out.println("https proxyHost=" + tunnelHost +
+ " proxyPort=" + tunnelPort +
+ " host=" + host +
+ " port=" + port);
+ */
+
+ /*
+ * If a proxy has been set...
+ * Set up a socket to do tunneling through the proxy.
+ * Start it off as a regular socket, then layer SSL
+ * over the top of it.
+ */
+ if (tunnelHost==null) {
+ sslSocket = (SSLSocket)factory.createSocket(host, port);
+ } else {
+ Socket tunnel = new Socket(tunnelHost, tunnelPort);
+ doTunnelHandshake(tunnel, host, port);
+
+ // Overlay tunnel socket with SSL
+ sslSocket = (SSLSocket)factory.createSocket(tunnel, host, port, true);
+ }
+
+ /*
+ * Handshaking is started manually in this example because
+ * PrintWriter catches all IOExceptions (including
+ * SSLExceptions), sets an internal error flag, and then
+ * returns without rethrowing the exception.
+ *
+ * Unfortunately, this means any error messages are lost,
+ * which caused lots of confusion for others using this
+ * code. The only way to tell there was an error is to call
+ * PrintWriter.checkError().
+ */
+ sslSocket.startHandshake();
+
+ return sslSocket;
- }
+ }
+
+ static private void doTunnelHandshake(Socket tunnel, String host, int port)
+ throws IOException
+ {
+ OutputStream out = tunnel.getOutputStream();
+ String msg = "CONNECT " + host + ":" + port + " HTTP/1.0\n"
+ + "User-Agent: "
+ + sun.net.www.protocol.http.HttpURLConnection.userAgent
+ + "\r\n\r\n";
+ byte b[];
+ try {
+ /*
+ * We really do want ASCII7 -- the http protocol doesn't change
+ * with locale.
+ */
+ b = msg.getBytes("ASCII7");
+ } catch (UnsupportedEncodingException ignored) {
+ /*
+ * If ASCII7 isn't there, something serious is wrong, but
+ * Paranoia Is Good (tm)
+ */
+ b = msg.getBytes();
+ }
+ out.write(b);
+ out.flush();
+
+ /*
+ * We need to store the reply so we can create a detailed
+ * error message to the user.
+ */
+ byte reply[] = new byte[200];
+ int replyLen = 0;
+ int newlinesSeen = 0;
+ boolean headerDone = false; /* Done on first newline */
+
+ InputStream in = tunnel.getInputStream();
+ boolean error = false;
+
+ while (newlinesSeen < 2) {
+ int i = in.read();
+ if (i < 0) {
+ throw new IOException("Unexpected EOF from proxy");
+ }
+ if (i == '\n') {
+ headerDone = true;
+ ++newlinesSeen;
+ } else if (i != '\r') {
+ newlinesSeen = 0;
+ if (!headerDone && replyLen < reply.length) {
+ reply[replyLen++] = (byte) i;
+ }
+ }
+ }
+
+ /*
+ * Converting the byte array to a string is slightly wasteful
+ * in the case where the connection was successful, but it's
+ * insignificant compared to the network overhead.
+ */
+ String replyStr;
+ try {
+ replyStr = new String(reply, 0, replyLen, "ASCII7");
+ } catch (UnsupportedEncodingException ignored) {
+ replyStr = new String(reply, 0, replyLen);
+ }
+
+ // Parse response, check for status code
+ StringTokenizer st = new StringTokenizer(replyStr);
+ st.nextToken(); // ignore version part
+ if (!st.nextToken().startsWith("200")) {
+ throw new IOException("Unable to tunnel through "
+ + tunnelHost + ":" + tunnelPort
+ + ". Proxy returns \"" + replyStr + "\"");
+ }
+
+ /* tunneling Handshake was successful! */
+ }
}