alsutton/enterprisepasswordsafe

View on GitHub
src/main/java/com/enterprisepasswordsafe/ui/web/servlets/VerifyLogin.java

Summary

Maintainability
A
1 hr
Test Coverage
F
0%
/*
 * Copyright (c) 2017 Carbon Security Ltd. <opensource@carbonsecurity.co.uk>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.enterprisepasswordsafe.ui.web.servlets;

import com.enterprisepasswordsafe.database.*;
import com.enterprisepasswordsafe.database.exceptions.DatabaseUnavailableException;
import com.enterprisepasswordsafe.engine.users.UserClassifier;
import com.enterprisepasswordsafe.ui.web.servletfilter.AuthenticationFilter;
import com.enterprisepasswordsafe.ui.web.utils.ForwardException;
import com.enterprisepasswordsafe.ui.web.utils.RedirectException;
import com.enterprisepasswordsafe.ui.web.utils.SecurityUtils;
import com.enterprisepasswordsafe.ui.web.utils.ServletUtils;

import javax.security.auth.login.LoginException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.List;

public final class VerifyLogin extends LoginAuthenticationServlet {

    private static final String NEXT_PAGE_REDIRECT = "/system/Welcome";
    private static final String PASSWORD_SYNC_PAGE = "/passwordsync.jsp";

    private final UserClassifier userClassifier = new UserClassifier();

    @Override
    protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = getClearSession(request);

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if (username == null || password == null) {
            throw new ServletException("Please enter your username and password.");
        }

        try {
            User theUser = getUser(request, username);
            authenticateUser(request, theUser, password);
            storeUserInformation(session, theUser);
            storeTimeoutInformation(session);
            String redirect = response.encodeRedirectURL(request.getContextPath() + NEXT_PAGE_REDIRECT);
            response.sendRedirect(redirect);
        } catch (RedirectException e) {
            response.sendRedirect(request.getContextPath() + e.getDestination());
        } catch (ForwardException e) {
            request.getRequestDispatcher(e.getDestination()).forward(request, response);
        } catch (DatabaseUnavailableException e) {
            response.sendRedirect(request.getContextPath()+"/VerifyJDBCConfiguration");
        } catch (SQLException | GeneralSecurityException e) {
            throw new ServletException("An error occurred trying to log you in. ", e);
        }
    }

    private HttpSession getClearSession(HttpServletRequest request) {
        HttpSession session = request.getSession();
        if( session != null ) {
            session.removeAttribute(AuthenticationFilter.USER_IS_ADMIN);
            session.removeAttribute(AuthenticationFilter.USER_IS_SUBADMIN);
            session.removeAttribute(AuthenticationFilter.ACCESS_KEY_PARAMETER);
            session.removeAttribute(AuthenticationFilter.USER_NAME_PARAMETER);
            session.removeAttribute(SecurityUtils.USER_ID_PARAMETER);
        }
        return session;
    }

    private User getUser(HttpServletRequest request, final String username)
            throws RedirectException, SQLException, UnsupportedEncodingException, GeneralSecurityException {
        User theUser = UserDAO.getInstance().getByName(username);
        if (theUser == null) {
            TamperproofEventLogDAO.getInstance().create(TamperproofEventLog.LOG_LEVEL_AUTHENTICATION,
                    null, "An attempt was made to log in as a non-existent user ("
                            + username + ") from " + request.getRemoteHost() + ". ",false);
            ServletUtils.getInstance().generateErrorMessage(request, "There was a problem authorising your details");
            throw new RedirectException("/Login");
        }

        if (!theUser.isEnabled()) {
            TamperproofEventLogDAO.getInstance().create(
                    TamperproofEventLog.LOG_LEVEL_AUTHENTICATION,
                    theUser, "An attempt was made to log in as a disabled user ("
                            + username + ") from " + request.getRemoteHost() + ". ", false);
            ServletUtils.getInstance().generateErrorMessage(request, "There was a problem authorising your details");
            throw new RedirectException("/Login");
        }
        return theUser;
    }

    private void authenticateUser(HttpServletRequest request, User user, String password)
            throws GeneralSecurityException, UnsupportedEncodingException, SQLException,
            RedirectException, ForwardException, ServletException, UnknownHostException {
        try {
            UserDAO.getInstance().authenticateUser(user, password);
        } catch (LoginException e) {
            handleAuthenticationFailure(request, user, password, e.getLocalizedMessage());
        }
        checkRemoteAndLocalPasswordsMatch(request, user, password);
        if (!user.checkPassword(password)) {
            handleFailedLogin(request, user);
        }
        checkLoginRestrictions(request, user);
        user.decryptAccessKey(password);
        UserDAO.getInstance().setFailedLogins(user, 0);
    }

    private void handleAuthenticationFailure(HttpServletRequest request, User user, String password,
                                             String failureMessage)
            throws ForwardException, RedirectException, UnsupportedEncodingException,
            GeneralSecurityException, SQLException {
        if (user.getAuthSource() != null
                && !user.getAuthSource().equals(AuthenticationSource.DEFAULT_SOURCE.getSourceId())) {
            if (user.checkPassword(password)) {
                request.setAttribute(SecurityUtils.USER_ID_PARAMETER, user.getId());
                throw new ForwardException(PASSWORD_SYNC_PAGE);
            }
        }

        TamperproofEventLogDAO.getInstance().create(TamperproofEventLog.LOG_LEVEL_AUTHENTICATION,
                user, "An attempt to log in as the user " + user.getUserName() + " from " +
                        request.getRemoteHost() + " failed (" + failureMessage + "). ", false);
        ServletUtils.getInstance().generateErrorMessage(request, "There was a problem authorising your details");
        throw new RedirectException("/Login");
    }

    private void checkRemoteAndLocalPasswordsMatch(HttpServletRequest request, User user, String password)
            throws ForwardException, NoSuchAlgorithmException {
        if (user.getAuthSource() == null
        ||  user.getAuthSource().equals(AuthenticationSource.DEFAULT_SOURCE.getSourceId())) {
            return;
        }

        if (user.checkPassword(password)) {
            return;
        }

        request.setAttribute(SecurityUtils.USER_ID_PARAMETER, user.getId());
        throw new ForwardException(PASSWORD_SYNC_PAGE);
    }

    private void handleFailedLogin(HttpServletRequest request, User user)
            throws GeneralSecurityException, UnsupportedEncodingException, SQLException, RedirectException {
        if (!userClassifier.isMasterAdmin(user)) {
            UserDAO.getInstance().increaseFailedLogins(user);
        }
        ServletUtils.getInstance().generateErrorMessage(request, "Your login details are incorrect.");
        throw new RedirectException("/Login");
    }

    private void checkLoginRestrictions(HttpServletRequest request, User user)
            throws GeneralSecurityException, SQLException, UnknownHostException, ServletException, RedirectException {
        String address = request.getRemoteAddr();
        String userId = user.getId();
        List<UserIPZoneRestriction> restrictions = UserIPZoneRestrictionDAO.getInstance().getApplicable(userId, address);
        if (restrictions.size() > 0) {
            for (UserIPZoneRestriction thisRestriction : restrictions) {
                if (thisRestriction.getRule() == UserIPZoneRestriction.DENY_INT) {
                    throw new ServletException("You can not log in from the system you are using.");
                }
            }
        } else {
            String defaultLoginAccess = ConfigurationDAO.getValue(ConfigurationOption.DEFAULT_LOGIN_ACCESS);
            if (defaultLoginAccess.equals(UserIPZoneRestriction.DENY_STRING)) {
                ServletUtils.getInstance().generateErrorMessage(request, "You can not log in from the system you are using.");
                throw new RedirectException("/Login");
            }
        }
    }

    @Override
    protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
        throws IOException {
        response.sendRedirect(request.getContextPath());
    }

    @Override
    public String getServletInfo() {
        return "Servlet to delete a group from the system";
    }
}