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

📄 davtransaction.java

📁 这是linux下ssl vpn的实现程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/* ========================================================================== *
 * Copyright (C) 2004-2005 Pier Fumagalli <http://www.betaversion.org/~pier/> *
 *                            All rights reserved.                            *
 * ========================================================================== *
 *                                                                            *
 * Licensed under the  Apache License, Version 2.0  (the "License").  You may *
 * not use this file except in compliance with the License.  You may obtain a *
 * copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>.       *
 *                                                                            *
 * Unless  required  by applicable  law or  agreed  to  in writing,  software *
 * distributed under the License is distributed on an  "AS IS" BASIS, WITHOUT *
 * WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied.  See the *
 * License for the  specific language  governing permissions  and limitations *
 * under the License.                                                         *
 *                                                                            *
 * ========================================================================== */
package com.sslexplorer.vfs.webdav;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.maverick.crypto.encoders.Base64;
import com.sslexplorer.boot.Util;
import com.sslexplorer.core.CoreServlet;
import com.sslexplorer.core.CoreUtil;
import com.sslexplorer.core.ServletRequestAdapter;
import com.sslexplorer.core.ServletResponseAdapter;
import com.sslexplorer.security.AccountLockedException;
import com.sslexplorer.security.AuthenticationModuleManager;
import com.sslexplorer.security.AuthenticationScheme;
import com.sslexplorer.security.AuthenticationSchemeSequence;
import com.sslexplorer.security.Constants;
import com.sslexplorer.security.Credentials;
import com.sslexplorer.security.InvalidLoginCredentialsException;
import com.sslexplorer.security.LogonController;
import com.sslexplorer.security.SessionInfo;
import com.sslexplorer.security.WebDAVAuthenticationModule;
import com.sslexplorer.security.actions.LogonAction;
import com.sslexplorer.vfs.utils.DAVCredentialsCashe;


/**
 * <p>A simple wrapper isolating the Java Servlet API from this
 * <a href="http://www.rfc-editor.org/rfc/rfc2518.txt">WebDAV</a>
 * implementation.</p> 
 *
 * @author <a href="http://www.betaversion.org/~pier/">Pier Fumagalli</a>
 */
public class DAVTransaction {

	private static Log log = LogFactory.getLog(DAVTransaction.class);
	

    public final static String ATTR_EXPECTING_REALM_AUTHENTICATION = "expectingRealmAuth";
    public final static String ATTR_DEREGISTER_SUB_AUTHS = "deregisterSubAuths";
    public final static String ATTR_AUTH_ATTEMPTS = "authAttempts";
    
    /**
     * <p>The identifyication of the <code>infinity</code> value
     * in the <code>Depth</code> header.</p>
     */
    public static final int INFINITY = Integer.MAX_VALUE;

    /** <p>The nested {@link HttpServletRequest}.</p> */
    private HttpServletRequest req = null;
    /** <p>The nested {@link HttpServletResponse}.</p> */
    private HttpServletResponse res = null;
    /** <p>The {@link URI} associated with the base of the repository.</p> */
    private URI base = null;
    /** <p>The {@link URI} session info for this transaction. contains user etc.</p> */
    private SessionInfo sessionInfo;
    /** <p>The path for this transaction. contains user etc.</p> */
    private String path;
    /** <p>A cache of resources for the life of this transaction */
    private Map resourceCache;
    /** <p>The current credentials object being used for authentication to the resources */
    private DAVCredentials currentCredentials;
    
    /* ====================================================================== */
    /* Constructors                                                           */
    /* ====================================================================== */
    
    /**
     * <p>Create a new {@link DAVTransaction} instance.</p>
     */
    public DAVTransaction(ServletRequest request, ServletResponse response)
    throws ServletException, DAVAuthenticationRequiredException {
        if (request == null) throw new NullPointerException("Null request");
        if (response == null) throw new NullPointerException("Null response");
        this.req = (HttpServletRequest) request;
        this.res = (HttpServletResponse) response;
        this.resourceCache = new HashMap();
        
        try {

            this.sessionInfo = CoreServlet.getServlet().getLogonController().getSessionInfo((HttpServletRequest) request);
            if(this.sessionInfo == null) {  
                String ticket = request.getParameter("ticket"); 
                if(ticket != null) {
                    Map activeSessions = CoreServlet.getServlet().getLogonController().getActiveSessions();
                    for(Iterator i = activeSessions.values().iterator(); this.sessionInfo == null && i.hasNext(); ) {
                        SessionInfo session = (SessionInfo)i.next();
                        if(ticket.equals(session.getHttpSession().getAttribute(Constants.WEB_FOLDER_LAUNCH_TICKET))) {
                            this.sessionInfo = session;
                        }
                    }
                    if(this.sessionInfo != null) {
                        CoreServlet.getServlet().getLogonController().addCookies(new ServletRequestAdapter((HttpServletRequest)request), 
                            new ServletResponseAdapter((HttpServletResponse)response), sessionInfo.getLogonTicket(), sessionInfo.getUser());
                    }
                }   
            }
            
            String scheme = this.req.getScheme();
            String host = this.req.getServerName();
            String basePath = CoreUtil.doStandardReplacements(sessionInfo, DAVUtilities.concatenatePaths(this.req.getServletPath(), this.req.getPathInfo()));
            
            int port = this.req.getServerPort();
            this.base = new URI(scheme, null, host, port, basePath, null, null);
            this.base = this.base.normalize();
            path = DAVUtilities.stripTrailingSlash(DAVUtilities.stripLeadingSlash(DAVUtilities.stripFirstPath(base.getPath())));
        } catch (URISyntaxException exception) {
            throw new ServletException("Unable to create base URI", exception);
        }
        
    }
    
    public void putCachedResource(DAVResource resource) {
        String key = DAVUtilities.concatenatePaths(resource.getMount().getMountString(), resource.getRelativePath());
        resourceCache.put(key, resource);
    }
    
    public DAVResource getCachedResource(String fullPath) {
        return (DAVResource)resourceCache.get(fullPath);
    }
    
    public boolean verifyAuthorization() throws IOException, DAVAuthenticationRequiredException {
    	
      	/**
         * SSL-Explorer authentication should be performed here.
         */        
        String expectingRealm = (String) req.getSession().getAttribute(ATTR_EXPECTING_REALM_AUTHENTICATION);
        
        try {
            if (!CoreServlet.getServlet().getSystemDatabase().verifyIPAddress(req.getRemoteAddr())) {
              	if(log.isDebugEnabled())
              		log.debug(req.getRemoteHost() + " is not authorized");
              	res.setStatus(HttpServletResponse.SC_FORBIDDEN);
                return false;
            } 
            else {
                
                /**
                 * We may already have the session info
                 */
                if(sessionInfo!=null)
                    return true;
                
                /**
                 * No so lets get it from the request
                 */
                if (CoreServlet.getServlet().getLogonController().hasClientLoggedOn(req, res)  == LogonController.LOGGED_ON) {
                    sessionInfo = CoreServlet.getServlet().getLogonController().getSessionInfo(req);
                    return true;            	     
                }
            }

	        if(log.isDebugEnabled())
	        		log.debug("Requesting HTTP authentication for SSL-Explorer logon.");
	        
	        expectingRealm = WebDAVAuthenticationModule.DEFAULT_REALM;
	
	        req.getSession().setAttribute(Constants.ORIGINAL_REQUEST, Util.getOriginalRequest(req));        
	        
	        if(log.isDebugEnabled())
	        		log.debug("Expecting authentication " + expectingRealm);
	
	        // Now test for the authorization
	        boolean hasAuthorization = req.getHeader("Authorization") != null && Boolean.TRUE.equals(req.getSession().getAttribute(Constants.AUTH_SENT));

	        if (expectingRealm.equals(WebDAVAuthenticationModule.DEFAULT_REALM) && !hasAuthorization) {
	
	        		if(log.isDebugEnabled())
	        			log.debug("Creating new HTTP authentication authentication session");
	        			            
	            /* 
	             * TODO make this more secure. This makes it possible to logon using a WebDAV url with HTTP basic authentication
	             * then continue to use other areas of SSL-Explorer - bypassing any stricter authentication schemes
	             */
                AuthenticationSchemeSequence seq = AuthenticationModuleManager.getInstance().getSchemeForAuthenticationModuleInUse(WebDAVAuthenticationModule.MODULE_NAME);
                if(seq == null || !seq.getEnabled()) {
                    log.error("User cannot authenticate via WebDAV using only HTTP BASIC authentication as the current policy does not allow this.");
                    res.sendError(DAVStatus.SC_FORBIDDEN, "You cannot authenticate via WebDAV using only HTTP BASIC authentication as the current policy does not allow this.");
                    return false;                    
                }
                seq.addModule(WebDAVAuthenticationModule.MODULE_NAME);
                seq.init(req.getSession());
                seq.nextAuthenticationModule();
                req.getSession().setAttribute(Constants.AUTH_SENT, Boolean.TRUE);
                req.getSession().setAttribute(Constants.AUTH_SESSION, seq);
                WebDAVAuthenticationModule.sendAuthorizationError(req, res, WebDAVAuthenticationModule.DEFAULT_REALM);
                return false;
	        }        
        
	        if (!hasAuthorization) {
                WebDAVAuthenticationModule.sendAuthorizationError(req, res, expectingRealm);
	            return false;
	        } 
	        else {
	            String authorization = req.getHeader("Authorization");
	            int idx = authorization.indexOf(' ');
	            if (idx == -1 || idx == authorization.length() - 1) {
                    WebDAVAuthenticationModule.sendAuthorizationError(req, res, expectingRealm);
	                return false;
	            }
	            // Authenticate the user
	            String method = authorization.substring(0, idx);
	            if (!method.equalsIgnoreCase("basic")) {
                    WebDAVAuthenticationModule.sendAuthorizationError(req, res, expectingRealm);
	                return false;
	            }
	
	            // 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) {
                    WebDAVAuthenticationModule.sendAuthorizationError(req, res, expectingRealm);
	                return false;
	            }
	
	            // Get the user credentials
	            String username = credentials.substring(0, idx);

                    
	                if (expectingRealm.equals(WebDAVAuthenticationModule.DEFAULT_REALM)) {
	                    AuthenticationSchemeSequence authScheme = (AuthenticationSchemeSequence) req.getSession().getAttribute(Constants.AUTH_SESSION);
	                    if(authScheme == null) {
	                        throw new Exception("No authentication scheme initialised.");
	                    }
	                    LogonAction.authenticate(authScheme, req);
	                    LogonAction.finishAuthentication(authScheme, req, res);
	                } 
	                else {
	                	
	                	    if(log.isDebugEnabled())
	                	    		log.debug("Logging " + username + " [" + req.getRemoteHost() + "] onto realm " + expectingRealm
	                                    + " using Basic authentication for session " + req.getSession().getId());
	                    //subAuths.put(expectingRealm, new AuthPair(username, password.toCharArray()));
	                    req.getSession().removeAttribute(ATTR_EXPECTING_REALM_AUTHENTICATION);
	                }
	                req.getSession().removeAttribute(Constants.AUTH_SENT);
	                
	                /* Logging method */
	                if(log.isDebugEnabled())
	                	   log.debug(req.getMethod() + ' ' + req.getRequestURI() + ' ' + req.getProtocol());
	                
	                // We now can get the sessionInfo object for this session
	                sessionInfo = CoreServlet.getServlet().getLogonController().getSessionInfo(req);
	                
	                	return true;
	             

	        }            	
        }  catch (InvalidLoginCredentialsException ex) {
            log.error(ex);
            WebDAVAuthenticationModule.sendAuthorizationError(req, res, expectingRealm);
            return false;
        } 
        catch (AccountLockedException ex) {
            log.error(ex);
            res.sendError(DAVStatus.SC_FORBIDDEN, ex.getMessage());
            return false;
        } catch(Exception ex) {
	    	    log.error("Unexpected error", ex);
	    	    res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
	        return false;
	    }    	
    }
    public HttpServletResponse getResponse() {
    	   return (HttpServletResponse) res;
    }
    
    /* ====================================================================== */
    /* Request methods                                                        */
    /* ====================================================================== */


    /**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -