Package org.tmatesoft.svn.core.internal.io.dav.http

Source Code of org.tmatesoft.svn.core.internal.io.dav.http.HTTPNegotiateAuthentication$SVNKitCallbackHandler

package org.tmatesoft.svn.core.internal.io.dav.http;

import java.io.IOException;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;

import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.internal.util.SVNBase64;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.util.SVNLogType;

class HTTPNegotiateAuthentication extends HTTPAuthentication {

    private class SVNKitCallbackHandler implements CallbackHandler {

        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            for (int i = 0; i < callbacks.length; i++) {
                if (callbacks[i] instanceof NameCallback) {
                    ((NameCallback)callbacks[i]).setName(getUserName());
                } else if (callbacks[i] instanceof PasswordCallback) {
                    ((PasswordCallback)callbacks[i]).setPassword(getPassword() == null ? null : getPassword().toCharArray());
                }
            }
        }

    }

    private static volatile Boolean ourIsNegotiateSupported;

    private GSSManager myGSSManager = GSSManager.getInstance();
    private GSSContext myGSSContext;
    private Oid mySpnegoOid;
    private Subject mySubject;
   
    public HTTPNegotiateAuthentication(HTTPNegotiateAuthentication prevAuth) {
        if (prevAuth != null) {
            mySubject = prevAuth.mySubject;
        }
    }
   
    public HTTPNegotiateAuthentication() {
        this(null);
    }

    public static synchronized boolean isSupported() {
        if (ourIsNegotiateSupported == null) {
            try {
                Oid spnegoOid = new Oid("1.3.6.1.5.5.2");
                ourIsNegotiateSupported = Boolean.valueOf(Arrays.asList(GSSManager.getInstance().getMechs()).contains(spnegoOid));
            } catch (GSSException gsse) {
                ourIsNegotiateSupported = Boolean.FALSE;
            }
        }
        return ourIsNegotiateSupported.booleanValue();
    }

    public String getAuthenticationScheme() {
        return "Negotiate";
    }

    private String getServerPrincipalName() {
        return "HTTP@" + getChallengeParameter("host");
    }

    private byte[] myToken;
    private int myTokenLength;

    public void respondTo(String challenge) {
        if (challenge == null) {
            myToken = new byte[0];
            myTokenLength = 0;
        } else {
            myToken = new byte[(challenge.length() * 3 + 3) / 4];
            myTokenLength = SVNBase64.base64ToByteArray(new StringBuffer(challenge), myToken);
        }
    }
   
    private void initializeSubject() {
        if (mySubject != null)
            return;
        try {
            LoginContext ctx = new LoginContext("com.sun.security.jgss.krb5.initiate", new SVNKitCallbackHandler());
            ctx.login();
            mySubject = ctx.getSubject();
        } catch (LoginException e) {
        }
    }

    private void initializeContext() throws GSSException {
        if (mySpnegoOid == null) {
            mySpnegoOid = new Oid("1.3.6.1.5.5.2");
        }
        GSSName serverName = myGSSManager.createName(getServerPrincipalName(), GSSName.NT_HOSTBASED_SERVICE);
        myGSSContext = myGSSManager.createContext(serverName, mySpnegoOid, null, GSSContext.DEFAULT_LIFETIME);
    }

    public String authenticate() throws SVNException {
        if (!isStarted())
            initializeSubject();

        PrivilegedExceptionAction action = new PrivilegedExceptionAction() {
            public Object run() throws SVNException {
                if (!isStarted()) {
                    try {
                        initializeContext();
                    } catch (GSSException gsse) {
                        SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, "Negotiate authentication failed: ''{0}''", gsse.getMajorString());
                        SVNErrorManager.error(err, SVNLogType.NETWORK);
                        return null;
                    }
                }
       
                byte[] outtoken;
       
                try {
                    outtoken = myGSSContext.initSecContext(myToken, 0, myTokenLength);
                } catch (GSSException gsse) {
                    SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.RA_DAV_REQUEST_FAILED, "Negotiate authentication failed: ''{0}''", gsse.getMajorString());
                    SVNErrorManager.error(err, SVNLogType.NETWORK);
                    return null;
                }
       
                if (myToken != null) {
                    return "Negotiate " + SVNBase64.byteArrayToBase64(outtoken);
                }
                return null;
            }
        };
       
        if (mySubject != null) {
            try {
                return (String) Subject.doAs(mySubject, action);
            } catch (PrivilegedActionException e) {
                Throwable cause = e.getCause();
                if (cause instanceof SVNException) {
                    throw (SVNException)cause;
                }
                throw new RuntimeException(cause);
            }
        }
       
        try {
            return (String) action.run();
        } catch (Exception cause) {
            if (cause instanceof SVNException) {
                throw (SVNException)cause;
            }
            throw new RuntimeException(cause);           
        }
    }

    public boolean isStarted() {
        return myGSSContext != null;
    }
   
    public boolean needsLogin() {
        initializeSubject();
        return mySubject == null;
    }
   
}
TOP

Related Classes of org.tmatesoft.svn.core.internal.io.dav.http.HTTPNegotiateAuthentication$SVNKitCallbackHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.