/* Copyright 2008-2015 Josh Drummond This file is part of WebPasswordSafe. WebPasswordSafe is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. WebPasswordSafe is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with WebPasswordSafe; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package net.webpasswordsafe.server.service; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.Resource; import net.webpasswordsafe.client.remote.LoginService; import net.webpasswordsafe.client.remote.UserService; import net.webpasswordsafe.common.dto.SystemSettings; import net.webpasswordsafe.common.model.User; import net.webpasswordsafe.common.util.Constants; import net.webpasswordsafe.common.util.Constants.AuthenticationStatus; import net.webpasswordsafe.common.util.Constants.Function; import net.webpasswordsafe.common.util.Utils; import net.webpasswordsafe.server.ServerSessionUtil; import net.webpasswordsafe.server.dao.UserDAO; import net.webpasswordsafe.server.plugin.audit.AuditLogger; import net.webpasswordsafe.server.plugin.authentication.Authenticator; import net.webpasswordsafe.server.plugin.authentication.RoleRetriever; import net.webpasswordsafe.server.plugin.authentication.sso.SsoAuthenticator; import net.webpasswordsafe.server.plugin.authorization.Authorizer; import net.webpasswordsafe.server.report.ReportConfig; import net.webpasswordsafe.server.service.helper.WPSXsrfProtectedServiceServlet; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** * Implementation of Login Service * * @author Josh Drummond * */ @Service("loginService") public class LoginServiceImpl extends WPSXsrfProtectedServiceServlet implements LoginService { private static final long serialVersionUID = 185624826328067937L; private static Logger LOG = Logger.getLogger(LoginServiceImpl.class); @Resource private Authenticator authenticator; @Resource private SsoAuthenticator ssoAuthenticator; @Autowired private UserDAO userDAO; @Autowired private ReportConfig reportConfig; @Resource private AuditLogger auditLogger; @Resource private RoleRetriever roleRetriever; @Resource private Authorizer authorizer; @Autowired private UserService userService; @Override @Transactional(propagation=Propagation.REQUIRED) public SystemSettings getSystemSettings() { userService.verifyInitialization(); SystemSettings systemSettings = new SystemSettings(); systemSettings.setEveryoneGroup(userService.getEveryoneGroup()); systemSettings.setSsoEnabled(ssoAuthenticator.isSsoEnabled()); systemSettings.setLogoutUrl(Utils.safeString(ssoAuthenticator.getLogoutUrl())); return systemSettings; } @Override @Transactional(propagation=Propagation.REQUIRED, readOnly=true) public User getLogin() { String username = ServerSessionUtil.getUsername(); User user = userDAO.findActiveUserByUsername(username); if (null != user) { user.setRoles(ServerSessionUtil.getRoles()); } LOG.debug("logged in user="+((null==user) ? "null":user.getUsername())); return user; } @Override @Transactional(propagation=Propagation.REQUIRED) public AuthenticationStatus login(String principal, String[] credentials) { Date now = new Date(); AuthenticationStatus authStatus = AuthenticationStatus.SUCCESS; String message = ""; principal = trimUsername(principal); //don't let them get around SSO if enabled if (ssoAuthenticator.isSsoEnabled() && !ssoAuthenticator.isBypassAllowed(principal)) { authStatus = AuthenticationStatus.FAILURE; message = "bypass SSO not allowed"; } //otherwise authenticate given credentials if (authStatus == AuthenticationStatus.SUCCESS) { authStatus = authenticator.authenticate(principal, credentials); if (AuthenticationStatus.SUCCESS == authStatus) { message = loginDB(principal); authStatus = ("".equals(message)) ? AuthenticationStatus.SUCCESS : AuthenticationStatus.FAILURE; } else if (AuthenticationStatus.TWO_STEP_REQ == authStatus) { message = "two-step authentication required"; } else { message = "authentication failed"; } } auditLogger.log(now, principal, ServerSessionUtil.getIP(), "login", "", AuthenticationStatus.SUCCESS == authStatus, message); return authStatus; } @Override @Transactional(propagation=Propagation.REQUIRED) public AuthenticationStatus checkSsoLogin() { AuthenticationStatus authStatus = AuthenticationStatus.SUCCESS; if (ssoAuthenticator.isSsoEnabled()) { String principal = ssoAuthenticator.getPrincipal(); String message = loginDB(principal); authStatus = ("".equals(message)) ? AuthenticationStatus.SUCCESS : AuthenticationStatus.FAILURE; auditLogger.log(new Date(), principal, ServerSessionUtil.getIP(), "login", "", AuthenticationStatus.SUCCESS == authStatus, message); } return authStatus; } @Transactional(propagation=Propagation.REQUIRED) protected String loginDB(String principal) { String message = ""; User user = userDAO.findActiveUserByUsername(principal); if (null != user) { user.setLastLogin(new Date()); userDAO.makePersistent(user); ServerSessionUtil.setUsername(principal); ServerSessionUtil.setRoles(roleRetriever.retrieveRoles(user)); } else { message = "user not found"; } return message; } private String trimUsername(String username) { if ((null != username) && (username.length() > User.LENGTH_USERNAME)) { return username.substring(0, User.LENGTH_USERNAME); } else { return username; } } @Override public boolean logout() { auditLogger.log(new Date(), ServerSessionUtil.getUsername(), ServerSessionUtil.getIP(), "logout", "", true, ""); ServerSessionUtil.setUsername(null); ServerSessionUtil.setRoles(null); ServerSessionUtil.invalidateSession(); return true; } @Override @Transactional(propagation=Propagation.REQUIRED, readOnly=true) public Map<Function, Boolean> getLoginAuthorizations(Set<Function> functions) { LOG.debug("inside getLoginAuthorizations"); User loggedInUser = getLogin(); // if passed null, load everything if (null==functions) { LOG.debug("functions was passed null"); functions = new HashSet<Function>(Arrays.asList(Function.values())); } LOG.debug("functions="+functions.toString()); Map<Function, Boolean> authzMap = new HashMap<Function, Boolean>(functions.size()); for (Function function : functions) { authzMap.put(function, authorizer.isAuthorized(loggedInUser, function.name())); } LOG.debug("authzMap="+authzMap.toString()); return authzMap; } @Override public boolean ping() { ServerSessionUtil.initCsrfSession(); return true; } @Override @Transactional(propagation=Propagation.REQUIRED, readOnly=true) public List<Map<String, Object>> getLoginReports() { LOG.debug("inside getLoginReports"); User loggedInUser = getLogin(); List<Map<String, Object>> reportList = new ArrayList<Map<String,Object>>(); for (Map<String, Object> report : reportConfig.getReports()) { if (authorizer.isAuthorized(loggedInUser, Constants.VIEW_REPORT_PREFIX+(String)report.get(Constants.NAME))) { reportList.add(report); } } return reportList; } }