Search in sources :

Example 1 with NTLMLogonDetails

use of org.alfresco.jlan.server.auth.ntlm.NTLMLogonDetails in project alfresco-remote-api by Alfresco.

the class BaseNTLMAuthenticationFilter method processType1.

/**
 * Process a type 1 NTLM message
 *
 * @param type1Msg Type1NTLMMessage
 * @param req HttpServletRequest
 * @param res HttpServletResponse
 * @exception IOException
 */
protected void processType1(Type1NTLMMessage type1Msg, HttpServletRequest req, HttpServletResponse res) throws IOException {
    if (getLogger().isDebugEnabled())
        getLogger().debug("Received type1 " + type1Msg);
    // Get the existing NTLM details
    NTLMLogonDetails ntlmDetails = null;
    HttpSession session = req.getSession();
    ntlmDetails = (NTLMLogonDetails) session.getAttribute(NTLM_AUTH_DETAILS);
    // Check if cached logon details are available
    if (ntlmDetails != null && ntlmDetails.hasType2Message() && ((nltmAuthenticator.getNTLMMode() == NTLMMode.PASS_THROUGH && ntlmDetails.hasAuthenticationToken()) || !ntlmDetails.hasAuthenticationToken())) {
        // Get the authentication server type2 response
        Type2NTLMMessage cachedType2 = ntlmDetails.getType2Message();
        byte[] type2Bytes = cachedType2.getBytes();
        String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes));
        if (getLogger().isDebugEnabled())
            getLogger().debug("Sending cached NTLM type2 to client - " + cachedType2);
        // Send back a request for NTLM authentication
        res.setHeader(WWW_AUTHENTICATE, ntlmBlob);
        res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        res.flushBuffer();
    } else {
        // Clear any cached logon details
        session.removeAttribute(NTLM_AUTH_DETAILS);
        // Set the 8 byte challenge for the new logon request
        byte[] challenge = null;
        NTLMPassthruToken authToken = null;
        if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER) {
            // Generate a random 8 byte challenge
            challenge = new byte[8];
            DataPacker.putIntelLong(m_random.nextLong(), challenge, 0);
        } else {
            // Get the client domain
            String domain = type1Msg.getDomain();
            if (domain == null || domain.length() == 0) {
                domain = mapClientAddressToDomain(req.getRemoteAddr());
            }
            if (getLogger().isDebugEnabled())
                getLogger().debug("Client domain " + domain);
            // Create an authentication token for the new logon
            authToken = new NTLMPassthruToken(domain);
            // Run the first stage of the passthru authentication to get the challenge
            nltmAuthenticator.authenticate(authToken);
            // Get the challenge from the token
            if (authToken.getChallenge() != null) {
                challenge = authToken.getChallenge().getBytes();
            }
        }
        // Get the flags from the client request and mask out unsupported features
        int ntlmFlags = type1Msg.getFlags() & m_ntlmFlags;
        // Build a type2 message to send back to the client, containing the challenge
        List<TargetInfo> tList = new ArrayList<TargetInfo>();
        String srvName = getServerName();
        tList.add(new TargetInfo(NTLM.TargetServer, srvName));
        Type2NTLMMessage type2Msg = new Type2NTLMMessage();
        type2Msg.buildType2(ntlmFlags, srvName, challenge, null, tList);
        // Store the NTLM logon details, cache the type2 message, and token if using passthru
        ntlmDetails = new NTLMLogonDetails();
        ntlmDetails.setType2Message(type2Msg);
        ntlmDetails.setAuthenticationToken(authToken);
        session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
        if (getLogger().isDebugEnabled())
            getLogger().debug("Sending NTLM type2 to client - " + type2Msg);
        // Send back a request for NTLM authentication
        byte[] type2Bytes = type2Msg.getBytes();
        String ntlmBlob = "NTLM " + new String(Base64.encodeBase64(type2Bytes));
        res.setHeader(WWW_AUTHENTICATE, ntlmBlob);
        res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        res.flushBuffer();
    }
}
Also used : TargetInfo(org.alfresco.jlan.server.auth.ntlm.TargetInfo) NTLMLogonDetails(org.alfresco.jlan.server.auth.ntlm.NTLMLogonDetails) HttpSession(javax.servlet.http.HttpSession) ArrayList(java.util.ArrayList) NTLMPassthruToken(org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken) Type2NTLMMessage(org.alfresco.jlan.server.auth.ntlm.Type2NTLMMessage)

Example 2 with NTLMLogonDetails

use of org.alfresco.jlan.server.auth.ntlm.NTLMLogonDetails in project alfresco-remote-api by Alfresco.

the class BaseNTLMAuthenticationFilter method processType3.

/**
 * Process a type 3 NTLM message
 *
 * @param type3Msg Type3NTLMMessage
 * @param req HttpServletRequest
 * @param res HttpServletResponse
 *
 * @exception IOException
 * @exception ServletException
 */
protected boolean processType3(Type3NTLMMessage type3Msg, ServletContext context, HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
    Log logger = getLogger();
    if (logger.isDebugEnabled())
        logger.debug("Received type3 " + type3Msg);
    // Get the existing NTLM details
    NTLMLogonDetails ntlmDetails = null;
    SessionUser user = null;
    user = getSessionUser(context, req, res, true);
    HttpSession session = req.getSession();
    ntlmDetails = (NTLMLogonDetails) session.getAttribute(NTLM_AUTH_DETAILS);
    // Get the NTLM logon details
    String userName = type3Msg.getUserName();
    String workstation = type3Msg.getWorkstation();
    String domain = type3Msg.getDomain();
    // ALF-10997 fix, normalize the userName
    // the system runAs is acceptable because we are resolving a username i.e. it's a system-wide operation that does not need permission checks
    final String userName_f = userName;
    String normalized = transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<String>() {

        public String execute() throws Throwable {
            return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String>() {

                public String doWork() throws Exception {
                    String normalized = personService.getUserIdentifier(userName_f);
                    return normalized;
                }
            }, AuthenticationUtil.SYSTEM_USER_NAME);
        }
    }, true);
    if (normalized != null) {
        userName = normalized;
    }
    boolean authenticated = false;
    // Check if we are using cached details for the authentication
    if (user != null && ntlmDetails != null && ntlmDetails.hasNTLMHashedPassword()) {
        // Check if the received NTLM hashed password matches the cached password
        byte[] ntlmPwd = type3Msg.getNTLMHash();
        byte[] cachedPwd = ntlmDetails.getNTLMHashedPassword();
        if (ntlmPwd != null) {
            authenticated = Arrays.equals(cachedPwd, ntlmPwd);
        }
        if (logger.isDebugEnabled())
            logger.debug("Using cached NTLM hash, authenticated = " + authenticated);
        onValidate(context, req, res, new NTLMCredentials(userName, ntlmPwd));
        // Allow the user to access the requested page
        return true;
    } else {
        WebCredentials credentials;
        // Check if we are using local MD4 password hashes or passthru authentication
        if (nltmAuthenticator.getNTLMMode() == NTLMMode.MD4_PROVIDER) {
            // Check if guest logons are allowed and this is a guest logon
            if (m_allowGuest && userName.equalsIgnoreCase(authenticationComponent.getGuestUserName())) {
                credentials = new GuestCredentials();
                // Indicate that the user has been authenticated
                authenticated = true;
                if (getLogger().isDebugEnabled())
                    getLogger().debug("Guest logon");
            } else {
                // Get the stored MD4 hashed password for the user, or null if the user does not exist
                String md4hash = getMD4Hash(userName);
                if (md4hash != null) {
                    authenticated = validateLocalHashedPassword(type3Msg, ntlmDetails, authenticated, md4hash);
                    credentials = new NTLMCredentials(ntlmDetails.getUserName(), ntlmDetails.getNTLMHashedPassword());
                } else {
                    // Check if unknown users should be logged on as guest
                    if (m_mapUnknownUserToGuest) {
                        // Reset the user name to be the guest user
                        userName = authenticationComponent.getGuestUserName();
                        authenticated = true;
                        credentials = new GuestCredentials();
                        if (logger.isDebugEnabled())
                            logger.debug("User " + userName + " logged on as guest, no Alfresco account");
                    } else {
                        if (logger.isDebugEnabled())
                            logger.debug("User " + userName + " does not have Alfresco account");
                        // Bypass NTLM authentication and display the logon screen,
                        // as user account does not exist in Alfresco
                        credentials = new UnknownCredentials();
                        authenticated = false;
                    }
                }
            }
        } else {
            credentials = new NTLMCredentials(type3Msg.getUserName(), type3Msg.getNTLMHash());
            // Determine if the client sent us NTLMv1 or NTLMv2
            if (type3Msg.hasFlag(NTLM.Flag128Bit) && type3Msg.hasFlag(NTLM.FlagNTLM2Key) || (type3Msg.getNTLMHash() != null && type3Msg.getNTLMHash().length > 24)) {
                // Cannot accept NTLMv2 if we are using passthru auth
                if (logger.isErrorEnabled())
                    logger.error("Client " + workstation + " using NTLMv2 logon, not valid with passthru authentication");
            } else {
                if (ntlmDetails == null) {
                    if (logger.isWarnEnabled())
                        logger.warn("Authentication failed: NTLM details can not be retrieved from session. Client must support cookies.");
                    restartLoginChallenge(context, req, res);
                    return false;
                }
                // Passthru mode, send the hashed password details to the passthru authentication server
                NTLMPassthruToken authToken = (NTLMPassthruToken) ntlmDetails.getAuthenticationToken();
                authToken.setUserAndPassword(type3Msg.getUserName(), type3Msg.getNTLMHash(), PasswordEncryptor.NTLM1);
                try {
                    // Run the second stage of the passthru authentication
                    nltmAuthenticator.authenticate(authToken);
                    authenticated = true;
                    // Check if the user has been logged on as guest
                    if (authToken.isGuestLogon()) {
                        userName = authenticationComponent.getGuestUserName();
                    }
                    // Set the authentication context
                    authenticationComponent.setCurrentUser(userName);
                } catch (BadCredentialsException ex) {
                    if (logger.isDebugEnabled())
                        logger.debug("Authentication failed, " + ex.getMessage());
                } catch (AuthenticationException ex) {
                    if (logger.isDebugEnabled())
                        logger.debug("Authentication failed, " + ex.getMessage());
                } finally {
                    // Clear the authentication token from the NTLM details
                    ntlmDetails.setAuthenticationToken(null);
                }
            }
        }
        // Check if the user has been authenticated, if so then setup the user environment
        if (authenticated == true) {
            boolean userInit = false;
            if (user == null) {
                try {
                    user = createUserEnvironment(session, userName);
                    userInit = true;
                } catch (AuthenticationException ex) {
                    if (logger.isDebugEnabled())
                        logger.debug("Failed to validate user " + userName, ex);
                    onValidateFailed(context, req, res, session, credentials);
                    return false;
                }
            }
            onValidate(context, req, res, credentials);
            // Update the NTLM logon details in the session
            String srvName = getServerName();
            if (ntlmDetails == null) {
                // No cached NTLM details
                ntlmDetails = new NTLMLogonDetails(userName, workstation, domain, false, srvName);
                ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
                session.setAttribute(NTLM_AUTH_DETAILS, ntlmDetails);
                if (logger.isDebugEnabled())
                    logger.debug("No cached NTLM details, created");
            } else {
                // Update the cached NTLM details
                ntlmDetails.setDetails(userName, workstation, domain, false, srvName);
                ntlmDetails.setNTLMHashedPassword(type3Msg.getNTLMHash());
                if (logger.isDebugEnabled())
                    logger.debug("Updated cached NTLM details");
            }
            if (logger.isDebugEnabled())
                logger.debug("User logged on via NTLM, " + ntlmDetails);
            if (onLoginComplete(context, req, res, userInit)) {
                // Allow the user to access the requested page
                return true;
            }
        } else {
            restartLoginChallenge(context, req, res);
        }
    }
    return false;
}
Also used : NTLMCredentials(org.alfresco.repo.web.auth.NTLMCredentials) Log(org.apache.commons.logging.Log) NTLMLogonDetails(org.alfresco.jlan.server.auth.ntlm.NTLMLogonDetails) RetryingTransactionHelper(org.alfresco.repo.transaction.RetryingTransactionHelper) UnknownCredentials(org.alfresco.repo.web.auth.UnknownCredentials) AuthenticationException(org.alfresco.repo.security.authentication.AuthenticationException) HttpSession(javax.servlet.http.HttpSession) BadCredentialsException(net.sf.acegisecurity.BadCredentialsException) SessionUser(org.alfresco.repo.SessionUser) NTLMPassthruToken(org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken) WebCredentials(org.alfresco.repo.web.auth.WebCredentials) GuestCredentials(org.alfresco.repo.web.auth.GuestCredentials)

Aggregations

HttpSession (javax.servlet.http.HttpSession)2 NTLMLogonDetails (org.alfresco.jlan.server.auth.ntlm.NTLMLogonDetails)2 NTLMPassthruToken (org.alfresco.repo.security.authentication.ntlm.NTLMPassthruToken)2 ArrayList (java.util.ArrayList)1 BadCredentialsException (net.sf.acegisecurity.BadCredentialsException)1 TargetInfo (org.alfresco.jlan.server.auth.ntlm.TargetInfo)1 Type2NTLMMessage (org.alfresco.jlan.server.auth.ntlm.Type2NTLMMessage)1 SessionUser (org.alfresco.repo.SessionUser)1 AuthenticationException (org.alfresco.repo.security.authentication.AuthenticationException)1 RetryingTransactionHelper (org.alfresco.repo.transaction.RetryingTransactionHelper)1 GuestCredentials (org.alfresco.repo.web.auth.GuestCredentials)1 NTLMCredentials (org.alfresco.repo.web.auth.NTLMCredentials)1 UnknownCredentials (org.alfresco.repo.web.auth.UnknownCredentials)1 WebCredentials (org.alfresco.repo.web.auth.WebCredentials)1 Log (org.apache.commons.logging.Log)1