1 | /******************************************************************************
|
---|
2 | *
|
---|
3 | * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
|
---|
4 | * www.mindbright.se, [email protected]
|
---|
5 | *
|
---|
6 | * This program is free software; you can redistribute it and/or modify
|
---|
7 | * it under the terms of the GNU General Public License as published by
|
---|
8 | * the Free Software Foundation; either version 2 of the License, or
|
---|
9 | * (at your option) any later version.
|
---|
10 | *
|
---|
11 | * This program is distributed in the hope that it will be useful,
|
---|
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
14 | * GNU General Public License for more details.
|
---|
15 | *
|
---|
16 | *****************************************************************************
|
---|
17 | * $Author: mats $
|
---|
18 | * $Date: 2000/03/27 07:53:53 $
|
---|
19 | * $Name: rel1-2-1 $
|
---|
20 | *****************************************************************************/
|
---|
21 | package mindbright.net;
|
---|
22 |
|
---|
23 | import java.io.InputStream;
|
---|
24 | import java.io.OutputStream;
|
---|
25 | import java.io.IOException;
|
---|
26 | import java.net.Socket;
|
---|
27 | import java.net.UnknownHostException;
|
---|
28 | import java.net.SocketException;
|
---|
29 |
|
---|
30 | import mindbright.util.Base64;
|
---|
31 |
|
---|
32 | /**
|
---|
33 | * Socket that implements web proxy tunnelling (using CONNECT)
|
---|
34 | *
|
---|
35 | * (described in an Internet Draft (expired Feb. 1999) titled
|
---|
36 | * 'Tunneling TCP based protocols through Web proxy servers'
|
---|
37 | * by: Ari Luotonen)
|
---|
38 | *
|
---|
39 | * proxy-authentication is described in RFC2616 and RFC2617
|
---|
40 | *
|
---|
41 | * @author Mats Andersson (originally by John Pallister)
|
---|
42 | */
|
---|
43 | public class WebProxyTunnelSocket extends Socket {
|
---|
44 |
|
---|
45 | private String proxyHost;
|
---|
46 | private int proxyPort;
|
---|
47 | private String targetHost;
|
---|
48 | private int targetPort;
|
---|
49 |
|
---|
50 | HttpHeader responseHeader;
|
---|
51 | String serverDesc;
|
---|
52 |
|
---|
53 | public HttpHeader getResponseHeader() {
|
---|
54 | return responseHeader;
|
---|
55 | }
|
---|
56 |
|
---|
57 | public String getServerDesc() {
|
---|
58 | return serverDesc;
|
---|
59 | }
|
---|
60 |
|
---|
61 | private WebProxyTunnelSocket(String host, int port, String proxyHost, int proxyPort)
|
---|
62 | throws IOException, UnknownHostException
|
---|
63 | {
|
---|
64 | super(proxyHost, proxyPort);
|
---|
65 |
|
---|
66 | this.proxyHost = proxyHost;
|
---|
67 | this.proxyPort = proxyPort;
|
---|
68 | this.targetHost = targetHost;
|
---|
69 | this.targetPort = targetPort;
|
---|
70 | }
|
---|
71 |
|
---|
72 | public static WebProxyTunnelSocket getProxy(String host, int port, String proxyHost, int proxyPort, String protoStr,
|
---|
73 | ProxyAuthenticator authenticator, String userAgent)
|
---|
74 | throws IOException, UnknownHostException
|
---|
75 | {
|
---|
76 | WebProxyTunnelSocket proxySocket = new WebProxyTunnelSocket(host, port, proxyHost, proxyPort);
|
---|
77 | int status = -1;
|
---|
78 | String serverDesc;
|
---|
79 |
|
---|
80 | try {
|
---|
81 | InputStream proxyIn = proxySocket.getInputStream();
|
---|
82 | OutputStream proxyOut = proxySocket.getOutputStream();
|
---|
83 | HttpHeader requestHeader = new HttpHeader();
|
---|
84 |
|
---|
85 | if(protoStr == null)
|
---|
86 | protoStr = "";
|
---|
87 |
|
---|
88 | requestHeader.setStartLine("CONNECT " + protoStr + host + ":" + port + " HTTP/1.0");
|
---|
89 | requestHeader.setHeaderField("User-Agent", userAgent);
|
---|
90 | requestHeader.setHeaderField("Pragma", "No-Cache");
|
---|
91 | requestHeader.setHeaderField("Proxy-Connection", "Keep-Alive");
|
---|
92 |
|
---|
93 | requestHeader.writeTo(proxyOut);
|
---|
94 | proxySocket.responseHeader = new HttpHeader(proxyIn);
|
---|
95 |
|
---|
96 | serverDesc = proxySocket.responseHeader.getHeaderField("server");
|
---|
97 |
|
---|
98 | // If proxy requires authentication
|
---|
99 | //
|
---|
100 | if(proxySocket.responseHeader.getStatus() == 407 && authenticator != null) {
|
---|
101 | String method = proxySocket.responseHeader.getProxyAuthMethod();
|
---|
102 | String realm = proxySocket.responseHeader.getProxyAuthRealm();
|
---|
103 |
|
---|
104 | if(realm == null)
|
---|
105 | realm = "";
|
---|
106 |
|
---|
107 | if("basic".equalsIgnoreCase(method)) {
|
---|
108 | // OK
|
---|
109 | } else if("digest".equalsIgnoreCase(method)) {
|
---|
110 | throw new IOException("We don't support 'Digest' HTTP Authentication");
|
---|
111 | } else {
|
---|
112 | throw new IOException("Unknown HTTP Authentication method '" + method + "'");
|
---|
113 | }
|
---|
114 |
|
---|
115 | proxySocket.close();
|
---|
116 | proxySocket = new WebProxyTunnelSocket(host, port, proxyHost, proxyPort);
|
---|
117 | proxyIn = proxySocket.getInputStream();
|
---|
118 | proxyOut = proxySocket.getOutputStream();
|
---|
119 |
|
---|
120 | String username = authenticator.getProxyUsername("HTTP Proxy", realm);
|
---|
121 | String password = authenticator.getProxyPassword("HTTP Proxy", realm);
|
---|
122 |
|
---|
123 | requestHeader.setBasicProxyAuth(username, password);
|
---|
124 | requestHeader.writeTo(proxyOut);
|
---|
125 | proxySocket.responseHeader = new HttpHeader(proxyIn);
|
---|
126 | }
|
---|
127 |
|
---|
128 | status = proxySocket.responseHeader.getStatus();
|
---|
129 |
|
---|
130 | } catch (SocketException e) {
|
---|
131 | throw new SocketException("Error communicating with proxy server " +
|
---|
132 | proxyHost + ":" + proxyPort + " (" + e.getMessage() + ")");
|
---|
133 | }
|
---|
134 |
|
---|
135 | if((status < 200) || (status > 299))
|
---|
136 | throw new WebProxyException("Proxy tunnel setup failed: " +
|
---|
137 | proxySocket.responseHeader.getStartLine());
|
---|
138 |
|
---|
139 | proxySocket.serverDesc = serverDesc;
|
---|
140 |
|
---|
141 | return proxySocket;
|
---|
142 | }
|
---|
143 |
|
---|
144 | public String toString() {
|
---|
145 | return "WebProxyTunnelSocket[addr=" + getInetAddress() +
|
---|
146 | ",port=" + getPort() +
|
---|
147 | ",localport=" + getLocalPort() + "]";
|
---|
148 | }
|
---|
149 | }
|
---|