/** * 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); }
private void setupProxy( ConnectivitySettings cs, int connectionType, InetSocketAddress inetSocketAddress) { cs.setConnectionType(connectionType); InetAddress address = inetSocketAddress.getAddress(); cs.setProxyHost((address != null) ? address.getHostAddress() : inetSocketAddress.getHostName()); cs.setProxyPort(inetSocketAddress.getPort()); }
/** * 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); } }
private Socket createSocket(ConnectivitySettings cs, InetSocketAddress address, int timeout) throws IOException { switch (cs.getConnectionType()) { case ConnectivitySettings.CONNECTION_VIA_SOCKS: case ConnectivitySettings.CONNECTION_DIRECT: Socket s = new Socket(); s.connect(address, timeout); return s; case ConnectivitySettings.CONNECTION_VIA_HTTPS: return getHttpsTunnelSocket(address, cs, timeout); default: throw new IllegalArgumentException("Illegal connection type: " + cs.getConnectionType()); } }
private ConnectivitySettings proxyToCs(Proxy proxy, URI uri) { ConnectivitySettings cs = new ConnectivitySettings(); InetSocketAddress isa = (InetSocketAddress) proxy.address(); switch (proxy.type()) { case HTTP: setupProxy(cs, ConnectivitySettings.CONNECTION_VIA_HTTPS, isa); break; case SOCKS: setupProxy(cs, ConnectivitySettings.CONNECTION_VIA_SOCKS, isa); break; default: } String prosyUser = NetworkSettings.getAuthenticationUsername(uri); if (prosyUser != null && !prosyUser.isEmpty()) { cs.setProxyUsername(prosyUser); cs.setProxyPassword(Keyring.read(NetworkSettings.getKeyForAuthenticationPassword(uri))); } return cs; }