Search in sources :

Example 1 with SessionUser

use of org.alfresco.repo.SessionUser in project alfresco-remote-api by Alfresco.

the class AuthenticationFilter method doFilter.

// Various services required by NTLM authenticator
/**
 * Run the authentication filter
 *
 * @param context ServletContext
 * @param req ServletRequest
 * @param resp ServletResponse
 * @param chain FilterChain
 * @exception ServletException
 * @exception IOException
 */
@Override
public void doFilter(ServletContext context, ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
    if (logger.isDebugEnabled())
        logger.debug("Entering AuthenticationFilter.");
    // Assume it's an HTTP request
    HttpServletRequest httpReq = (HttpServletRequest) req;
    HttpServletResponse httpResp = (HttpServletResponse) resp;
    // Get the user details object from the session
    SessionUser user = getSessionUser(context, httpReq, httpResp, false);
    if (user == null) {
        if (logger.isDebugEnabled())
            logger.debug("There is no user in the session.");
        // Get the authorization header
        String authHdr = httpReq.getHeader("Authorization");
        if (authHdr != null && authHdr.length() > 5 && authHdr.substring(0, 5).equalsIgnoreCase("BASIC")) {
            if (logger.isDebugEnabled())
                logger.debug("Basic authentication details present in the header.");
            byte[] encodedString = Base64.decodeBase64(authHdr.substring(5).getBytes());
            // ALF-13621: Due to browser inconsistencies we have to try a fallback path of encodings
            Set<String> attemptedAuths = new HashSet<String>(ENCODINGS.length * 2);
            for (String encoding : ENCODINGS) {
                CharsetDecoder decoder = Charset.forName(encoding).newDecoder().onMalformedInput(CodingErrorAction.REPORT);
                try {
                    // Attempt to decode using this charset
                    String basicAuth = decoder.decode(ByteBuffer.wrap(encodedString)).toString();
                    // It decoded OK but we may already have tried this string.
                    if (!attemptedAuths.add(basicAuth)) {
                        // Already tried - no need to try again
                        continue;
                    }
                    String username = null;
                    String password = null;
                    // Split the username and password
                    int pos = basicAuth.indexOf(":");
                    if (pos != -1) {
                        username = basicAuth.substring(0, pos);
                        password = basicAuth.substring(pos + 1);
                    } else {
                        username = basicAuth;
                        password = "";
                    }
                    // Go to the repo and authenticate
                    Authorization auth = new Authorization(username, password);
                    if (auth.isTicket()) {
                        authenticationService.validate(auth.getTicket());
                    } else {
                        authenticationService.authenticate(username, password.toCharArray());
                        if (authenticationListener != null) {
                            authenticationListener.userAuthenticated(new BasicAuthCredentials(username, password));
                        }
                    }
                    user = createUserEnvironment(httpReq.getSession(), authenticationService.getCurrentUserName(), authenticationService.getCurrentTicket(), false);
                    // Success so break out
                    break;
                } catch (CharacterCodingException e) {
                    if (logger.isDebugEnabled())
                        logger.debug("Didn't decode using " + decoder.getClass().getName(), e);
                } catch (AuthenticationException ex) {
                    if (logger.isDebugEnabled())
                        logger.debug("Authentication error ", ex);
                } catch (NoSuchPersonException e) {
                    if (logger.isDebugEnabled())
                        logger.debug("There is no such person error ", e);
                }
            }
        } else {
            // Check if the request includes an authentication ticket
            String ticket = req.getParameter(ARG_TICKET);
            if (ticket != null && ticket.length() > 0) {
                // PowerPoint bug fix
                if (ticket.endsWith(PPT_EXTN)) {
                    ticket = ticket.substring(0, ticket.length() - PPT_EXTN.length());
                }
                if (logger.isDebugEnabled())
                    logger.debug("Logon via ticket from " + req.getRemoteHost() + " (" + req.getRemoteAddr() + ":" + req.getRemotePort() + ")" + " ticket=" + ticket);
                // Validate the ticket
                authenticationService.validate(ticket);
                if (authenticationListener != null) {
                    authenticationListener.userAuthenticated(new TicketCredentials(ticket));
                }
                // Need to create the User instance if not already available
                String currentUsername = authenticationService.getCurrentUserName();
                user = createUserEnvironment(httpReq.getSession(), currentUsername, ticket, false);
            }
        }
        if (user == null) {
            if (logger.isDebugEnabled())
                logger.debug("No user/ticket, force the client to prompt for logon details.");
            httpResp.setHeader("WWW-Authenticate", "BASIC realm=\"Alfresco DAV Server\"");
            httpResp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            httpResp.flushBuffer();
            return;
        }
    } else {
        if (authenticationListener != null) {
            authenticationListener.userAuthenticated(new TicketCredentials(user.getTicket()));
        }
    }
    // Chain other filters
    chain.doFilter(req, resp);
}
Also used : TicketCredentials(org.alfresco.repo.web.auth.TicketCredentials) CharsetDecoder(java.nio.charset.CharsetDecoder) BasicAuthCredentials(org.alfresco.repo.web.auth.BasicAuthCredentials) AuthenticationException(org.alfresco.repo.security.authentication.AuthenticationException) NoSuchPersonException(org.alfresco.service.cmr.security.NoSuchPersonException) HttpServletResponse(javax.servlet.http.HttpServletResponse) CharacterCodingException(java.nio.charset.CharacterCodingException) HttpServletRequest(javax.servlet.http.HttpServletRequest) Authorization(org.alfresco.repo.security.authentication.Authorization) SessionUser(org.alfresco.repo.SessionUser) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 2 with SessionUser

use of org.alfresco.repo.SessionUser in project alfresco-remote-api by Alfresco.

the class BaseNTLMAuthenticationFilter method authenticateRequest.

public boolean authenticateRequest(ServletContext context, HttpServletRequest sreq, HttpServletResponse sresp) throws IOException, ServletException {
    // Check if there is an authorization header with an NTLM security blob
    String authHdr = sreq.getHeader(AUTHORIZATION);
    boolean reqAuth = false;
    if (authHdr != null) {
        if (authHdr.startsWith(AUTH_NTLM))
            reqAuth = true;
        else if (authHdr.startsWith("Negotiate")) {
            if (getLogger().isDebugEnabled())
                getLogger().debug("Received 'Negotiate' from client, may be SPNEGO/Kerberos logon");
            // Restart the authentication
            restartLoginChallenge(context, sreq, sresp);
            return false;
        } else if (isFallbackEnabled()) {
            return performFallbackAuthentication(context, sreq, sresp);
        }
    }
    // Check if the user is already authenticated
    SessionUser user = getSessionUser(context, sreq, sresp, true);
    // the next filter
    if (user != null && reqAuth == false) {
        // Filter validate hook
        onValidate(context, sreq, sresp, new TicketCredentials(user.getTicket()));
        if (getLogger().isDebugEnabled())
            getLogger().debug("Authentication not required (user), chaining ...");
        // Chain to the next filter
        return true;
    }
    // Check if the login page is being accessed, do not intercept the login page
    if (hasLoginPage() && sreq.getRequestURI().endsWith(getLoginPage()) == true) {
        if (getLogger().isDebugEnabled())
            getLogger().debug("Login page requested, chaining ...");
        // Chain to the next filter
        return true;
    }
    // Check if the browser is Opera, if so then display the login page as Opera does not
    // support NTLM and displays an error page if a request to use NTLM is sent to it
    String userAgent = sreq.getHeader("user-agent");
    if (userAgent != null && userAgent.indexOf("Opera ") != -1) {
        if (getLogger().isDebugEnabled())
            getLogger().debug("Opera detected, redirecting to login page");
        if (hasLoginPage())
            redirectToLoginPage(sreq, sresp);
        else
            restartLoginChallenge(context, sreq, sresp);
        return false;
    }
    // Check the authorization header
    if (authHdr == null) {
        if (allowsTicketLogons()) {
            if (checkForTicketParameter(context, sreq, sresp)) {
                // Authentication was bypassed using a ticket parameter
                return true;
            }
        }
        if (getLogger().isDebugEnabled())
            getLogger().debug("New NTLM auth request from " + sreq.getRemoteHost() + " (" + sreq.getRemoteAddr() + ":" + sreq.getRemotePort() + ") SID:" + sreq.getSession().getId());
        // Send back a request for NTLM authentication
        restartLoginChallenge(context, sreq, sresp);
        return false;
    } else {
        HttpSession session = sreq.getSession();
        Object sessionMutex = WebUtils.getSessionMutex(session);
        // Decode the received NTLM blob and validate
        final byte[] ntlmByts = Base64.decodeBase64(authHdr.substring(5).getBytes());
        int ntlmTyp = NTLMMessage.isNTLMType(ntlmByts);
        if (ntlmTyp == NTLM.Type1) {
            // Process the type 1 NTLM message
            Type1NTLMMessage type1Msg = new Type1NTLMMessage(ntlmByts);
            synchronized (sessionMutex) {
                processType1(type1Msg, sreq, sresp);
            }
            return false;
        } else if (ntlmTyp == NTLM.Type3) {
            // Process the type 3 NTLM message
            Type3NTLMMessage type3Msg = new Type3NTLMMessage(ntlmByts);
            synchronized (sessionMutex) {
                return processType3(type3Msg, context, sreq, sresp);
            }
        } else {
            if (getLogger().isDebugEnabled())
                getLogger().debug("NTLM blob not handled, redirecting to login page.");
            if (hasLoginPage())
                redirectToLoginPage(sreq, sresp);
            else
                restartLoginChallenge(context, sreq, sresp);
            return false;
        }
    }
}
Also used : TicketCredentials(org.alfresco.repo.web.auth.TicketCredentials) Type3NTLMMessage(org.alfresco.jlan.server.auth.ntlm.Type3NTLMMessage) SessionUser(org.alfresco.repo.SessionUser) HttpSession(javax.servlet.http.HttpSession) Type1NTLMMessage(org.alfresco.jlan.server.auth.ntlm.Type1NTLMMessage)

Example 3 with SessionUser

use of org.alfresco.repo.SessionUser 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)

Example 4 with SessionUser

use of org.alfresco.repo.SessionUser in project acs-community-packaging by Alfresco.

the class BasicAuthenticationHandler method isUserAuthenticated.

/**
 * Returns <code>true</code> if the user is authenticated and their details are cached in the session
 *
 * @param context
 *            the servlet context
 * @param request
 *            the servlet request
 * @return <code>true</code>, if the user is authenticated
 * @throws IOException
 *             Signals that an I/O exception has occurred.
 * @throws ServletException
 *             On other errors.
 */
public boolean isUserAuthenticated(ServletContext context, HttpServletRequest request) throws IOException, ServletException {
    String authHdr = request.getHeader(HEADER_AUTHORIZATION);
    HttpSession session = request.getSession(false);
    SessionUser sessionUser = session == null ? null : (SessionUser) session.getAttribute(USER_SESSION_ATTRIBUTE);
    if (sessionUser == null) {
        if (remoteUserMapper != null && (!(remoteUserMapper instanceof ActivateableBean) || ((ActivateableBean) remoteUserMapper).isActive())) {
            String userId = remoteUserMapper.getRemoteUser(request);
            if (userId != null) {
                // authenticated by other
                authenticationComponent.setCurrentUser(userId);
                request.getSession().setAttribute(USER_SESSION_ATTRIBUTE, new User(userId, authenticationService.getCurrentTicket(), personService.getPerson(userId)));
                return true;
            }
        }
        if (authHdr != null && authHdr.length() > 5 && authHdr.substring(0, 5).equalsIgnoreCase(BASIC_START)) {
            String basicAuth = new String(Base64.decodeBase64(authHdr.substring(5).getBytes()));
            String username = null;
            String password = null;
            int pos = basicAuth.indexOf(":");
            if (pos != -1) {
                username = basicAuth.substring(0, pos);
                password = basicAuth.substring(pos + 1);
            } else {
                username = basicAuth;
                password = "";
            }
            try {
                if (logger.isDebugEnabled())
                    logger.debug("Authenticating user '" + username + "'");
                authenticationService.authenticate(username, password.toCharArray());
                // Normalize the user ID taking into account case sensitivity settings
                username = authenticationService.getCurrentUserName();
                if (logger.isDebugEnabled())
                    logger.debug("Authenticated user '" + username + "'");
                authenticationListener.userAuthenticated(new BasicAuthCredentials(username, password));
                request.getSession().setAttribute(USER_SESSION_ATTRIBUTE, new User(username, authenticationService.getCurrentTicket(), personService.getPerson(username)));
                return true;
            } catch (AuthenticationException ex) {
                authenticationListener.authenticationFailed(new BasicAuthCredentials(username, password), ex);
            }
        }
    } else {
        try {
            authenticationService.validate(sessionUser.getTicket());
            authenticationListener.userAuthenticated(new TicketCredentials(sessionUser.getTicket()));
            return true;
        } catch (AuthenticationException ex) {
            authenticationListener.authenticationFailed(new TicketCredentials(sessionUser.getTicket()), ex);
            session.invalidate();
        }
    }
    return false;
}
Also used : TicketCredentials(org.alfresco.repo.web.auth.TicketCredentials) SessionUser(org.alfresco.repo.SessionUser) SessionUser(org.alfresco.repo.SessionUser) User(org.alfresco.web.bean.repository.User) BasicAuthCredentials(org.alfresco.repo.web.auth.BasicAuthCredentials) AuthenticationException(org.alfresco.repo.security.authentication.AuthenticationException) HttpSession(javax.servlet.http.HttpSession) ActivateableBean(org.alfresco.repo.management.subsystems.ActivateableBean)

Example 5 with SessionUser

use of org.alfresco.repo.SessionUser in project acs-community-packaging by Alfresco.

the class NtlmAuthenticationHandler method createUserObject.

/* (non-Javadoc)
     * @see org.alfresco.repo.webdav.auth.BaseAuthenticationFilter#createUserObject(java.lang.String, java.lang.String, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef)
     */
@Override
protected SessionUser createUserObject(String userName, String ticket, NodeRef personNode, NodeRef homeSpaceRef) {
    // Create a web client user object
    User user = new User(userName, ticket, personNode);
    user.setHomeSpaceId(homeSpaceRef.getId());
    return user;
}
Also used : SessionUser(org.alfresco.repo.SessionUser) User(org.alfresco.web.bean.repository.User)

Aggregations

SessionUser (org.alfresco.repo.SessionUser)25 AuthenticationException (org.alfresco.repo.security.authentication.AuthenticationException)14 HttpSession (javax.servlet.http.HttpSession)9 User (org.alfresco.web.bean.repository.User)9 IOException (java.io.IOException)5 TicketCredentials (org.alfresco.repo.web.auth.TicketCredentials)5 AuthenticationService (org.alfresco.service.cmr.security.AuthenticationService)5 WebApplicationContext (org.springframework.web.context.WebApplicationContext)5 HttpServletRequest (javax.servlet.http.HttpServletRequest)4 PortletSession (javax.portlet.PortletSession)3 HttpServletResponse (javax.servlet.http.HttpServletResponse)3 Authorization (org.alfresco.repo.security.authentication.Authorization)3 BasicAuthCredentials (org.alfresco.repo.web.auth.BasicAuthCredentials)3 Serializable (java.io.Serializable)2 UnknownHostException (java.net.UnknownHostException)2 CharacterCodingException (java.nio.charset.CharacterCodingException)2 CharsetDecoder (java.nio.charset.CharsetDecoder)2 Date (java.util.Date)2 HashSet (java.util.HashSet)2 LinkedHashSet (java.util.LinkedHashSet)2