📄 abstractvpnclient.java
字号:
/*
* SSL-Explorer
*
* Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package com.sslexplorer.vpn.base;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
import java.util.Vector;
import com.maverick.crypto.security.SecureRandom;
import com.maverick.http.AuthenticationCancelledException;
import com.maverick.http.AuthenticationPrompt;
import com.maverick.http.ConnectMethod;
import com.maverick.http.GetMethod;
import com.maverick.http.HttpClient;
import com.maverick.http.HttpException;
import com.maverick.http.HttpMethod;
import com.maverick.http.HttpResponse;
import com.maverick.http.PasswordCredentials;
import com.maverick.http.URLDecoder;
import com.maverick.http.UnsupportedAuthenticationException;
import com.maverick.multiplex.Channel;
import com.maverick.multiplex.ChannelFactory;
import com.maverick.multiplex.ChannelListener;
import com.maverick.multiplex.MultiplexedConnection;
import com.maverick.multiplex.SocketChannel;
import com.maverick.ssl.SSLException;
import com.sslexplorer.vpn.util.IOStreamConnectorListener;
import com.sslexplorer.vpn.util.Tunnel;
import com.sslexplorer.vpn.util.URI;
import com.sslexplorer.vpn.util.XMLElement;
/**
* An abstract class to provide the common features of the SSL-Explorer VPN
* Client. When a user wants to tunnel through the gateway they must first
* register a tunnel using
* {@link registerApplicationTunnel(String, String, int)}. The client returns
* an {@link ApplicationTunnel} which can be used to obtain a Socket with
* {@link createTunnel(ApplicationTunnel)}.
*
* @author Lee David Painter
* @version $Revision: 1.52 $
*/
public abstract class AbstractVPNClient implements ChannelListener /*
* THIS
* BREAKS
* THE
* EMBEDDED
* VPN
* CLIENT
* ,AuthenticationPrompt
*/{
/** The lowest possible random port to select * */
public final int LOWEST_RANDOM_PORT = 49152;
/** The highest possible random port to select * */
public final int HIGHEST_RANDOM_PORT = 65535;
/** The collection of active socket listeners * */
protected Hashtable activeListeners = new Hashtable();
/** The hostname of the SSL-Explorer proxy * */
protected String sslexplorerHostname;
/** The port of the SSL-Explorer proxy * */
protected int sslexplorerPort;
/** The username for this session * */
protected String username;
/** The VPN client ticket for an authenticated session * */
protected String ticket;
/** The hostname of the local HTTPS proxy server * */
protected URI localProxyURL;
/** The active application tunnels * */
protected Vector activeApplicationTunnels = new Vector();
/** All local forwarding tunnels * */
protected Vector forwardingTunnels = new Vector();
/** The remote listeners * */
protected Hashtable remoteListeners = new Hashtable();
/** All registered tunnels by ticket * */
protected Hashtable registeredListeningSockets = new Hashtable();
/** All remote forwarding tunnels * */
protected Vector remoteTunnels = new Vector();
/** The active forwarding tunnels * */
protected Vector activeForwardingTunnels = new Vector();
/** The active direct tunnels (i.e. no listening sockets)* */
protected Hashtable activeDirectTunnels = new Hashtable();
/** We store all the available proxy information here * */
protected static Hashtable proxiesIE = new Hashtable();
/** We store all the local bypass addresses here * */
protected static Vector proxyBypassIE = new Vector();
protected static Hashtable proxiesFF = new Hashtable();
protected static Vector proxyBypassFF = new Vector();
/** HttpClient instances are cached * */
protected HttpClient client;
protected String defaultProxyHost;
protected int defaultProxyPort = 80;
protected PasswordCredentials defaultProxyCredentials;
protected String defaultProxyPreferredAuthentication;
protected boolean autoDetectProxies = true;
protected AuthenticationPrompt defaultProxyAuthenticationPrompt;
protected int defaultProxyType = HttpClient.PROXY_HTTP;
// #ifdef DEBUG
org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(AbstractVPNClient.class);
// #endif
static {
HttpClient.setUserAgent("SSL-Explorer/Agent");
}
public AbstractVPNClient() {
}
/**
* Initializes the abstract client with the SSL-Explorer servers host
* details, the user's name and the authenticated ticket for this session.
*
* @param sslexplorerHostname String
* @param proxyPort int
* @param username String
* @param ticket String
*/
public void init(String sslexplorerHostname, int sslexplorerPort, String username, String ticket) {
this.sslexplorerHostname = sslexplorerHostname;
this.sslexplorerPort = sslexplorerPort;
this.username = username;
this.ticket = ticket;
}
/**
* Set the URL of the HTTPS proxy server to use for all outgoing connections
*
* @param localProxyURL local proxy URL
*/
public void setLocalProxyURL(String localProxyURL) throws URI.MalformedURIException {
this.localProxyURL = new URI(localProxyURL);
// FIXME What about HttpsURLConnection?
}
/**
* Get the hostname of the SSL-Explorer proxy
*
* @return
*/
public String getSSLExplorerHost() {
return sslexplorerHostname;
}
/**
* Get the port of the SSL-Explorer proxy
*
* @return
*/
public int getSSLExplorerPort() {
return sslexplorerPort;
}
/**
* Get the username for this session
*
* @return
*/
public String getUsername() {
return username;
}
/**
* Get the authenticated VPN client ticket for this session
*
* @return
*/
public String getTicket() {
return ticket;
}
public void configureProxy() {
// Configure local proxy support
if (localProxyURL != null && !localProxyURL.equals("")) {
// #ifdef DEBUG
log.info("Configuring HTTP proxy to " + obfuscateURL(localProxyURL.toString()));
// #endif
String userInfo = localProxyURL.getUserinfo();
String user = "";
String password = "";
if (userInfo != null && !userInfo.equals("")) {
int idx = userInfo.indexOf(':');
user = URLDecoder.decode(userInfo);
if (idx != -1) {
password = URLDecoder.decode(userInfo.substring(idx + 1));
user = URLDecoder.decode(userInfo.substring(0, idx));
}
}
int port = localProxyURL.getPort();
setDefaultProxyType(localProxyURL.getScheme().equals("https") ? HttpClient.PROXY_HTTPS : HttpClient.PROXY_HTTP);
setDefaultProxyHost(localProxyURL.getHost());
setDefaultProxyPort(port == -1 ? 80 : port);
if (!user.equals("")) {
setDefaultProxyCredentials(new PasswordCredentials(user, password));
}
if (localProxyURL.getQueryString() != null) {
setDefaultProxyPreferredAuthentication(localProxyURL.getQueryString());
}
}
}
public synchronized HttpClient getHttpClient() {
if (client == null) {
// #ifdef DEBUG
log.info("Creating HttpClient instance");
// #endif
client = new HttpClient(sslexplorerHostname, sslexplorerPort, true);
if (defaultProxyHost != null && !defaultProxyHost.equals("")) {
// #ifdef DEBUG
log.info("Configuring proxies for HttpClient instance");
// #endif
client.setProxyAuthenticationPrompt(defaultProxyAuthenticationPrompt);
client.setProxyHost(defaultProxyHost);
client.setProxyPort(defaultProxyPort);
client.setProxyType(defaultProxyType);
if (defaultProxyCredentials != null && defaultProxyCredentials.getUsername() != null
&& !defaultProxyCredentials.getUsername().equals("")) {
/**
* LDP - This used to set preemptive authentication but its causing problems with
* NTLM
*/
client.setProxyCredentials(defaultProxyCredentials);
}
client.setProxyPreferedAuthentication("AUTO".equalsIgnoreCase(defaultProxyPreferredAuthentication) ? null
: defaultProxyPreferredAuthentication);
}
}
return client;
}
/**
* Register an application tunnel; this is typically used where an
* application can utilize the Input/OutputStreams of a tunnel. This removes
* the need for opening a seperate listening socket.
*
* @param name
* @param hostToConnect
* @param portToConnect
* @return
* @throws IOException
* @throws UnsupportedAuthenticationException
* @throws HttpException
*/
public Tunnel registerApplicationTunnel(String name, String hostToConnect, int portToConnect) throws IOException,
HttpException, UnsupportedAuthenticationException, AuthenticationCancelledException {
// #ifdef DEBUG
log.info("Registering application tunnel " + name + " host=" + hostToConnect + ":" + portToConnect);
// #endif
HttpClient client = getHttpClient();
GetMethod get = new GetMethod("/registerListeningSocket.do");
get.setParameter("sourcePort", String.valueOf(portToConnect));
get.setParameter("destinationHost", hostToConnect);
get.setParameter("destinationPort", String.valueOf(portToConnect));
get.setParameter("allowExternalHosts", "false");
get.setParameter("ticket", ticket);
HttpResponse response = null;
try {
response = client.execute(get);
XMLElement xml = new XMLElement();
xml.parseFromReader(new InputStreamReader(response.getInputStream()));
if (xml.getName().equalsIgnoreCase("success")) {
// This is the ticket we will use for proxy authentication
DefaultTunnel tunnel = new DefaultTunnel(-1, Tunnel.LOCAL_TUNNEL, false, Tunnel.TCP_TUNNEL, username,
portToConnect, portToConnect, hostToConnect, false, false, true, name, false);
tunnel.setTicket(xml.getContent());
// ApplicationTunnel tunnel = new ApplicationTunnel(-1, name,
// hostToConnect, portToConnect);
// tunnel.setTicket(xml.getContent());
// #ifdef DEBUG
log.info("Registered tunnel " + tunnel.getDestinationHost() + ":" + tunnel.getDestinationPort());
// #endif
activeDirectTunnels.put(tunnel.getDestinationHost() + ":" + tunnel.getDestinationPort(), tunnel);
return tunnel;
} else
throw new IOException("The server failed to register the application tunnel named " + name + " " + xml.getContent());
} finally {
if (response != null)
response.close();
}
}
/**
* Retrieve the list of persistant forwarding tunnels from the server
*
* @return ok
* @throws IOException
*/
protected boolean startForwardingTunnels() throws IOException {
for (Enumeration e = forwardingTunnels.elements(); e.hasMoreElements();) {
Tunnel t = (Tunnel) e.nextElement();
if (t.isAutoStart()) {
switch (t.getType()) {
case Tunnel.REMOTE_TUNNEL:
startRemoteForwarding(t);
break;
default:
createPermanentListeningSocket(t);
break;
}
}
}
return true;
}
/**
* Get a persistant forwarding tunnel given its id. <code>null</code> will
* be returned if no such tunnel exists
*
* @param id id
* @return forwarding tunnel
*/
protected Tunnel getPersistantForwardingTunnel(int id) {
Tunnel t;
for (Enumeration e = forwardingTunnels.elements(); e.hasMoreElements();) {
t = (Tunnel) e.nextElement();
if (t.getId() == id) {
return t;
}
}
for (Enumeration e = remoteTunnels.elements(); e.hasMoreElements();) {
t = (Tunnel) e.nextElement();
if (t.getId() == id) {
return t;
}
}
return null;
}
/**
* Retrieve the list of persistant forwarding tunnels from the server
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -