⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connectrequesthandler.java

📁 这是linux下ssl vpn的实现程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *  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 + -