package at.gv.egovernment.moa.id.entrypoints; import java.io.IOException; import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.swing.ListModel; import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger; import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer; import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; import at.gv.egovernment.moa.id.auth.servlet.AuthServlet; import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; import at.gv.egovernment.moa.id.moduls.AuthenticationManager; import at.gv.egovernment.moa.id.moduls.IAction; import at.gv.egovernment.moa.id.moduls.IModulInfo; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.moduls.ModulStorage; import at.gv.egovernment.moa.id.moduls.NoPassivAuthenticationException; import at.gv.egovernment.moa.id.moduls.RequestStorage; import at.gv.egovernment.moa.id.moduls.SSOManager; import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; import at.gv.egovernment.moa.id.storage.ExceptionStoreImpl; import at.gv.egovernment.moa.id.util.HTTPSessionUtils; import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; import at.gv.egovernment.moa.id.util.Random; import at.gv.egovernment.moa.id.util.legacy.LegacyHelper; import at.gv.egovernment.moa.logging.Logger; import at.gv.egovernment.moa.util.MiscUtil; public class DispatcherServlet extends AuthServlet{ /** * */ private static final long serialVersionUID = 1L; public static final String PARAM_TARGET_MODULE = "mod"; public static final String PARAM_TARGET_ACTION = "action"; public static final String PARAM_TARGET_PENDINGREQUESTID = "pendingid"; @Override public void init(ServletConfig config) throws ServletException { try { super.init(config); MOAIDAuthInitializer.initialize(); Logger.info(MOAIDMessageProvider.getInstance().getMessage( "init.00", null)); } catch (Exception ex) { Logger.fatal( MOAIDMessageProvider.getInstance().getMessage("init.02", null), ex); throw new ServletException(ex); } Logger.info("Dispatcher Servlet initialization"); } protected void processRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { boolean isValidSSOSession = false; boolean useSSOOA = false; String protocolRequestID = null; try { Logger.info("REQUEST: " + req.getRequestURI()); Logger.info("QUERY : " + req.getQueryString()); String errorid = req.getParameter(ERROR_CODE_PARAM); if (errorid != null) { Throwable throwable = ExceptionStoreImpl.getStore() .fetchException(errorid); ExceptionStoreImpl.getStore().removeException(errorid); Object idObject = req.getParameter(PARAM_TARGET_PENDINGREQUESTID); Map errorRequests = RequestStorage.getPendingRequest(req.getSession()); String pendingRequestID = null; if (idObject != null && (idObject instanceof String)) { if (errorRequests.containsKey((String)idObject)) pendingRequestID = (String) idObject; } if (throwable != null) { if (errorRequests != null) { synchronized (errorRequests) { IRequest errorRequest = null; if (pendingRequestID != null) { errorRequest = errorRequests.get(pendingRequestID); //remove the RequestStorage.removePendingRequest(errorRequests, pendingRequestID); } else { if (errorRequests.size() > 1) { handleErrorNoRedirect(throwable.getMessage(), throwable, req, resp); } else { Set keys = errorRequests.keySet(); errorRequest = errorRequests.get(keys.toArray()[0]); RequestStorage.removeAllPendingRequests(req.getSession()); } } if (errorRequest != null) { try { IModulInfo handlingModule = ModulStorage .getModuleByPath(errorRequest .requestedModule()); if (handlingModule != null) { if (handlingModule.generateErrorMessage( throwable, req, resp, errorRequest)) { //log Error Message StatisticLogger logger = StatisticLogger.getInstance(); logger.logErrorOperation(throwable, errorRequest); return; } } } catch (Throwable e) { Logger.error(e); handleErrorNoRedirect(throwable.getMessage(), throwable, req, resp); } } else { handleErrorNoRedirect(throwable.getMessage(), throwable, req, resp); } } handleErrorNoRedirect(throwable.getMessage(), throwable, req, resp); } else { // TODO: use better string handleErrorNoRedirect("UNKOWN ERROR DETECTED!", null, req, resp); } return; } } Object moduleObject = req.getParameter(PARAM_TARGET_MODULE); String module = null; if (moduleObject != null && (moduleObject instanceof String)) { module = (String) moduleObject; } if (module == null) { module = (String) req.getAttribute(PARAM_TARGET_MODULE); } Object actionObject = req.getParameter(PARAM_TARGET_ACTION); String action = null; if (actionObject != null && (actionObject instanceof String)) { action = (String) actionObject; } if (action == null) { action = req.getParameter(PARAM_TARGET_ACTION); } Logger.debug("dispatching to " + module + " protocol " + action); IModulInfo info = ModulStorage.getModuleByPath(module); IAction moduleAction = null; if (info == null) { Iterator modules = ModulStorage.getAllModules() .iterator(); while (modules.hasNext()) { info = modules.next(); moduleAction = info.canHandleRequest(req, resp); if (moduleAction != null) { action = moduleAction.getDefaultActionName(); module = info.getPath(); break; } info = null; } if (moduleAction == null) { resp.sendError(HttpServletResponse.SC_NOT_FOUND); Logger.error("Protocol " + module + " has no module registered"); return; } } if (moduleAction == null) { moduleAction = info.getAction(action); if (moduleAction == null) { resp.sendError(HttpServletResponse.SC_NOT_FOUND); Logger.error("Action " + action + " is not available!"); return; } } HttpSession httpSession = req.getSession(); Map protocolRequests = null; IRequest protocolRequest = null; try { protocolRequests = RequestStorage.getPendingRequest(httpSession); Object idObject = req.getParameter(PARAM_TARGET_PENDINGREQUESTID); if (protocolRequests != null && idObject != null && (idObject instanceof String)) { // synchronized (protocolRequests) { protocolRequestID = (String) idObject; //get IRequest if it exits if (protocolRequests.containsKey(protocolRequestID)) { protocolRequest = protocolRequests.get(protocolRequestID); Logger.debug(DispatcherServlet.class.getName()+": Found PendingRequest with ID " + protocolRequestID); //RequestStorage.setPendingRequest(httpSession, protocolRequests); } else { Logger.error("No PendingRequest with ID " + protocolRequestID + " found.!"); Set mapkeys = protocolRequests.keySet(); for (String el : mapkeys) Logger.debug("PendingRequest| ID=" + el + " OAIdentifier=" + protocolRequests.get(el)); handleErrorNoRedirect("Während des Anmeldevorgangs ist ein Fehler aufgetreten. Bitte versuchen Sie es noch einmal.", null, req, resp); //resp.sendError(HttpServletResponse.SC_CONFLICT); return; } // } } else { try { protocolRequest = info.preProcess(req, resp, action); if (protocolRequest != null) { if(protocolRequests != null) { // synchronized (protocolRequests) { // synchronized (protocolRequest) { Set mapkeys = protocolRequests.keySet(); for (String el : mapkeys) { IRequest value = protocolRequests.get(el); if (value.getOAURL().equals(protocolRequest.getOAURL())) { if(!AuthenticationSessionStoreage.deleteSessionWithPendingRequestID(el)) { Logger.warn(DispatcherServlet.class.getName()+": NO MOASession with PendingRequestID " + el + " found. Delete all user sessions!"); RequestStorage.removeAllPendingRequests(req.getSession()); } else { RequestStorage.removePendingRequest(protocolRequests, el); } } } // } // } } else { protocolRequests = new ConcurrentHashMap(); } synchronized (protocolRequest) { synchronized (protocolRequests) { //Start new Authentication protocolRequest.setAction(action); protocolRequest.setModule(module); protocolRequestID = Random.nextRandom(); protocolRequest.setRequestID(protocolRequestID); protocolRequests.put(protocolRequestID, protocolRequest); Logger.debug(DispatcherServlet.class.getName()+": Create PendingRequest with ID " + protocolRequestID + "."); } } } } catch (MOAIDException e) { resp.sendError(HttpServletResponse.SC_BAD_REQUEST); Logger.error("Failed to generate a valid protocol request!"); return; } if (protocolRequest == null) { resp.sendError(HttpServletResponse.SC_BAD_REQUEST); Logger.error("Failed to generate a valid protocol request!"); return; } } RequestStorage.setPendingRequest(httpSession, protocolRequests); AuthenticationManager authmanager = AuthenticationManager.getInstance(); SSOManager ssomanager = SSOManager.getInstance(); String moasessionID = null; String newSSOSessionId = null; AuthenticationSession moasession = null; //get SSO Cookie for Request String ssoId = ssomanager.getSSOSessionID(req); boolean needAuthentication = moduleAction.needAuthentication(protocolRequest, req, resp); if (needAuthentication) { //check SSO session if (ssoId != null) { String correspondingMOASession = ssomanager.existsOldSSOSession(ssoId); if (correspondingMOASession != null) { Logger.warn("Request sends an old SSO Session ID("+ssoId+")! " + "Invalidate the corresponding MOASession with ID="+ correspondingMOASession); AuthenticationSessionStoreage.destroySession(correspondingMOASession); ssomanager.deleteSSOSessionID(req, resp); } } //load Parameters from OnlineApplicationConfiguration OAAuthParameter oaParam = AuthConfigurationProvider.getInstance() .getOnlineApplicationParameter(protocolRequest.getOAURL()); if (oaParam == null) { throw new AuthenticationException("auth.00", new Object[] { protocolRequest.getOAURL() }); } isValidSSOSession = ssomanager.isValidSSOSession(ssoId, req); useSSOOA = oaParam.useSSO(); //if a legacy request is used SSO should not be allowed, actually boolean isUseMandateRequested = LegacyHelper.isUseMandateRequested(req); if (protocolRequest.isPassiv() && protocolRequest.forceAuth()) { // conflict! throw new NoPassivAuthenticationException(); } boolean tryperform = authmanager.tryPerformAuthentication( req, resp); if (protocolRequest.forceAuth()) { if (!tryperform) { authmanager.doAuthentication(req, resp, protocolRequest); return; } } else if (protocolRequest.isPassiv()) { if (tryperform || (isValidSSOSession && useSSOOA && !isUseMandateRequested) ) { // Passive authentication ok! } else { throw new NoPassivAuthenticationException(); } } else { if (tryperform || (isValidSSOSession && useSSOOA && !isUseMandateRequested) ) { // Is authenticated .. proceed } else { // Start authentication! authmanager.doAuthentication(req, resp, protocolRequest); return; } } if ((useSSOOA || isValidSSOSession)) //TODO: SSO with mandates requires an OVS extension { //TODO SSO Question!!!! if (useSSOOA && isValidSSOSession) { moasessionID = ssomanager.getMOASession(ssoId); moasession = AuthenticationSessionStoreage.getSession(moasessionID); //use new OAParameter if (oaParam.useSSOQuestion() && !AuthenticationSessionStoreage.isAuthenticated(moasessionID)) { authmanager.sendTransmitAssertionQuestion(req, resp, protocolRequest, oaParam); return; } } else { moasessionID = (String) req.getParameter(PARAM_SESSIONID); moasession = AuthenticationSessionStoreage.getSession(moasessionID); } //save SSO session usage in Database newSSOSessionId = ssomanager.createSSOSessionInformations(moasessionID, protocolRequest.getOAURL()); if (newSSOSessionId != null) { ssomanager.setSSOSessionID(req, resp, newSSOSessionId); } else { ssomanager.deleteSSOSessionID(req, resp); } } else { // moasessionID = HTTPSessionUtils.getHTTPSessionString(req.getSession(), // AuthenticationManager.MOA_SESSION, null); moasessionID = (String) req.getParameter(PARAM_SESSIONID); moasession = AuthenticationSessionStoreage.getSession(moasessionID); moasessionID = AuthenticationSessionStoreage.changeSessionID(moasession); } } String assertionID = moduleAction.processRequest(protocolRequest, req, resp, moasession); RequestStorage.removePendingRequest(protocolRequests, protocolRequestID); if (needAuthentication) { //boolean isSSOSession = AuthenticationSessionStoreage.isSSOSession(moasessionID); boolean isSSOSession = MiscUtil.isNotEmpty(newSSOSessionId); if ((useSSOOA || isSSOSession) //TODO: SSO with mandates requires an OVS extension && !moasession.getUseMandate()) { try { //Store OA specific SSO session information AuthenticationSessionStoreage.addSSOInformation(moasessionID, newSSOSessionId, assertionID, protocolRequest.getOAURL()); } catch (AuthenticationException e) { Logger.warn("SSO Session information can not be stored -> SSO is not enabled!"); authmanager.logout(req, resp, moasessionID); isSSOSession = false; } } else { authmanager.logout(req, resp, moasessionID); } //Advanced statistic logging StatisticLogger logger = StatisticLogger.getInstance(); logger.logSuccessOperation(protocolRequest, moasession, isSSOSession); } } catch (Throwable e) { e.printStackTrace(); // Try handle module specific, if not possible rethrow if (!info.generateErrorMessage(e, req, resp, protocolRequest)) { throw e; } } } catch (WrongParametersException ex) { handleWrongParameters(ex, req, resp); } catch (MOAIDException ex) { handleError(null, ex, req, resp, protocolRequestID); } catch (Throwable e) { handleErrorNoRedirect(e.getMessage(), e, req, resp); } finally { ConfigurationDBUtils.closeSession(); } } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { processRequest(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { processRequest(req, resp); } }