/** * Connects to the remote machine by establishing a tunnel through a HTTP proxy with Basic * authentication. It issues a CONNECT request and authenticates with the HTTP proxy with Basic * protocol. * * @param address remote machine to connect to * @return a TCP/IP socket connected to the remote machine * @throws IOException if an I/O error occurs during handshake (a network problem) */ private Socket authenticateBasic(InetSocketAddress address, ConnectivitySettings cs) throws IOException { Socket proxy = new Socket(cs.getProxyHost(), cs.getProxyPort()); BufferedReader r = new BufferedReader( new InputStreamReader(new InterruptibleInputStream(proxy.getInputStream()))); DataOutputStream dos = new DataOutputStream(proxy.getOutputStream()); String username = cs.getProxyUsername() == null ? "" : cs.getProxyUsername(); String password = cs.getProxyPassword() == null ? "" : String.valueOf(cs.getProxyPassword()); String credentials = username + ":" + password; String basicCookie = Base64Encoder.encode(credentials.getBytes("US-ASCII")); dos.writeBytes("CONNECT "); dos.writeBytes(address.getHostName() + ":" + address.getPort()); dos.writeBytes(" HTTP/1.0\r\n"); dos.writeBytes("Connection: Keep-Alive\r\n"); dos.writeBytes("Proxy-Authorization: Basic " + basicCookie + "\r\n"); dos.writeBytes("\r\n"); dos.flush(); String line = r.readLine(); if (sConnectionEstablishedPattern.matcher(line).find()) { for (; ; ) { line = r.readLine(); if (line.length() == 0) break; } return proxy; } throw new IOException("Basic authentication failed: " + line); }
/** * Connects to the remote machine by establishing a tunnel through a HTTP proxy. It issues a * CONNECT request and eventually authenticates with the HTTP proxy. Supported authentication * methods include: Basic. * * @param address remote machine to connect to * @return a TCP/IP socket connected to the remote machine * @throws UnknownHostException if the proxy host name cannot be resolved * @throws IOException if an I/O error occurs during handshake (a network problem) */ private Socket getHttpsTunnelSocket( InetSocketAddress address, ConnectivitySettings cs, int timeout) throws IOException { Socket proxy = new Socket(); proxy.connect(new InetSocketAddress(cs.getProxyHost(), cs.getProxyPort()), timeout); BufferedReader r = new BufferedReader( new InputStreamReader(new InterruptibleInputStream(proxy.getInputStream()))); DataOutputStream dos = new DataOutputStream(proxy.getOutputStream()); dos.writeBytes("CONNECT "); dos.writeBytes(address.getHostName() + ":" + address.getPort()); dos.writeBytes(" HTTP/1.0\r\n"); dos.writeBytes("Connection: Keep-Alive\r\n\r\n"); dos.flush(); String line; line = r.readLine(); if (sConnectionEstablishedPattern.matcher(line).find()) { for (; ; ) { line = r.readLine(); if (line.length() == 0) break; } return proxy; } else if (sProxyAuthRequiredPattern.matcher(line).find()) { boolean authMethodSelected = false; String authMethod = AUTH_NONE; for (; ; ) { line = r.readLine(); if (line.length() == 0) break; if (line.startsWith("Proxy-Authenticate:") && !authMethodSelected) { authMethod = line.substring(19).trim(); if (authMethod.equals(AUTH_BASIC)) { authMethodSelected = true; } } } // TODO: need to read full response before closing connection? proxy.close(); if (authMethod.startsWith(AUTH_BASIC)) { return authenticateBasic(address, cs); } else { throw new IOException("Unsupported authentication method: " + authMethod); } } else { proxy.close(); throw new IOException("HTTP proxy does not support CONNECT command. Received reply: " + line); } }