📄 connectrequesthandler.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.requesthandler.connect;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.util.LabelValueBean;
import com.maverick.crypto.encoders.Base64;
import com.sslexplorer.boot.HostService;
import com.sslexplorer.boot.HttpConstants;
import com.sslexplorer.boot.RequestHandler;
import com.sslexplorer.boot.RequestHandlerException;
import com.sslexplorer.boot.RequestHandlerRequest;
import com.sslexplorer.boot.RequestHandlerResponse;
import com.sslexplorer.core.CoreAttributeConstants;
import com.sslexplorer.core.CoreEvent;
import com.sslexplorer.core.CoreEventConstants;
import com.sslexplorer.core.CoreServlet;
import com.sslexplorer.forwarding.ForwardingTunnel;
import com.sslexplorer.forwarding.LocalRequestHandlerTunnel;
import com.sslexplorer.forwarding.RemoteRequestHandlerTunnel;
import com.sslexplorer.forwarding.VPNListeningSocket;
import com.sslexplorer.policyframework.ResourceChangeEvent;
import com.sslexplorer.tunnels.TransportType;
public class ConnectRequestHandler implements RequestHandler {
static Log log = LogFactory.getLog(ConnectRequestHandler.class);
private HashMap listeningPorts = new HashMap();
private List listeners;
public boolean handle(String pathInContext, String pathParams, RequestHandlerRequest request, RequestHandlerResponse response)
throws RequestHandlerException, IOException {
if (HttpConstants.METHOD_CONNECT.equalsIgnoreCase(request.getMethod())) {
//HostService addrPort2 = new HostService(request.getPath());
try {
if (log.isInfoEnabled())
log.info("CONNECT: " + request.getPath());
String authorization = request.getField("Proxy-Authorization");
// Check for proxy authentication information
if (authorization == null) {
if (log.isInfoEnabled())
log.info("Requesting that user supply proxy authentication credentials");
requestAuthentication(response);
} else {
if (log.isInfoEnabled())
log.info("Got proxy authentication credentials");
// This used to be in handle method, but we dont want the
// connection to close if no auth is supplied.
response.setField(HttpConstants.HDR_CONNECTION, "close");
// Process the authenticated proxy request
int idx = authorization.indexOf(' ');
if (idx == -1 || idx == authorization.length() - 1) {
sendAuthorizationError(response);
return true;
}
String method = authorization.substring(0, idx);
if (!method.equalsIgnoreCase("basic")) {
if (log.isInfoEnabled())
log.info("Invalid authentication method " + method);
throw new IOException("Basic proxy authentication required");
}
// Extract the credentials - should be ticket:tunnel
String encoded = authorization.substring(idx + 1);
String credentials = new String(Base64.decode(encoded));
idx = credentials.indexOf(':');
if (idx == 0 || idx == -1 || idx == credentials.length() - 1) {
sendAuthorizationError(response);
return true;
}
// The client authenticates with the VPN session ticket and
// tunnel ticket
String ticket = credentials.substring(0, idx);
String tunnel = credentials.substring(idx + 1);
// Get the tunnel details from the security manager
VPNListeningSocket vpnSocket = verifyTunnelCredentials(ticket, tunnel);
if(vpnSocket.getTunnel().getType()==TransportType.LOCAL_TUNNEL_ID) {
/**
* Handle a local tunnel
*/
HostService addrPort2 = new HostService(request.getPath());
HostService addrPort1 = vpnSocket.getTunnel().getDestination();
InetAddress addr1 = addrPort1.getAddress();
// Get the tunnel details that the client requested
InetAddress addr2 = addrPort2.getAddress();
// Check the tunnel request is the same as the authorized
// details
if (!addr1.equals(addr2) || addrPort1.getPort() != addrPort2.getPort()) {
log.error(
"Tunnel requested does not match the previoulsy authenticated tunnel settings");
throw new IOException("The tunnel was requested for a different host than was previously authenticated. The original " +
" request used " + addrPort1 +
" while the new request uses " + addrPort2);
}
if (log.isInfoEnabled())
log.info("Connecting to " + addr1 + ":" + addrPort1.getPort());
if (TransportType.UDP_TUNNEL.equals(vpnSocket.getTunnel().getTransport())) {
UDPHttpTunnel udpTunnel = new UDPHttpTunnel(vpnSocket,
addr1,
addrPort1.getPort());
request.setTunnel(udpTunnel);
} else {
// The user has a valid VPN session and the tunnel is
// valid so create
// a socket
Socket socket = new Socket(addr1, addrPort1.getPort());
// Force no timeout on these connections
socket.setSoTimeout(0);
LocalRequestHandlerTunnel localTunnel = new LocalRequestHandlerTunnel(vpnSocket, socket, 0);
request.setTunnel(localTunnel);
// TODO should this timeout be ZERO? LDP - HttpTunnel will always close if
// timeout is set. If it is set we would have to make it configurable
}
// Set the response status
response.setStatus(HttpConstants.RESP_200_OK);
CoreServlet.getServlet().fireCoreEvent(new ResourceChangeEvent(this,
CoreEventConstants.TUNNEL_OPENED, vpnSocket.getTunnel(), null, ResourceChangeEvent.STATE_SUCCESSFUL)
.addAttribute(CoreAttributeConstants.EVENT_ATTR_TUNNEL_TRANSPORT, vpnSocket.getTunnel().getTransport())
.addAttribute(CoreAttributeConstants.EVENT_ATTR_TUNNEL_DESTINATION, vpnSocket.getTunnel().getDestination().toString())
.addAttribute(CoreAttributeConstants.EVENT_ATTR_TUNNEL_SOURCE_PORT, String.valueOf(vpnSocket.getTunnel().getSourcePort()))
//.addAttribute(CoreAttributeConstants.EVENT_ATTR_TUNNEL_TYPE, String.valueOf(vpnSocket.getTunnel().getType())));
.addAttribute(CoreAttributeConstants.EVENT_ATTR_TUNNEL_TYPE, ((LabelValueBean)TransportType.TYPES.get(vpnSocket.getTunnel().getType())).getLabel()));
if (log.isInfoEnabled())
log.info("Tunnel established");
} else {
synchronized (listeningPorts) {
/**
* Handle a remote tunnel
*/
String path = request.getPath();
idx = path.indexOf("#");
if (idx == -1) {
response.sendError(400, "Bad LISTEN request");
return true;
}
HostService destination = new HostService(path.
substring(idx + 1));
path = path.substring(0, idx);
// Get the tunnel details that the client requested
HostService bindAddr = new HostService(path);
if (listeningPorts.containsKey(new Integer(
bindAddr.getPort()))) {
response.sendError(500,
path + " already in use");
return true;
}
if (log.isInfoEnabled())
log.info("Listening on " + bindAddr.getHost() + ":" +
bindAddr.getPort());
// Create a listener
RemoteRequestHandlerTunnel listener = new
RemoteRequestHandlerTunnel(bindAddr.getHost(),
bindAddr.getPort(), destination.getHost(),
destination.getPort(),
vpnSocket);
request.setTunnel(listener);
listeningPorts.put(new Integer(bindAddr.getPort()),
listener);
// Set the response status
response.setStatus(HttpConstants.RESP_200_OK);
response.setContentLength(0);
if (log.isInfoEnabled())
log.info("Socket listener established");
}
}
}
} catch (Exception e) {
log.error("Ignored exception.", e);
response.sendError(HttpConstants.RESP_500_INTERNAL_SERVER_ERROR, e.getMessage());
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -