/* * Password Management Servlets (PWM) * http://www.pwm-project.org * * Copyright (c) 2006-2009 Novell, Inc. * Copyright (c) 2009-2017 The PWM Project * * This program 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. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package password.pwm.http.servlet.forgottenpw; import password.pwm.PwmApplication; import password.pwm.PwmConstants; import password.pwm.VerificationMethodSystem; import password.pwm.bean.RemoteVerificationRequestBean; import password.pwm.bean.RemoteVerificationResponseBean; import password.pwm.bean.SessionLabel; import password.pwm.bean.UserInfoBean; import password.pwm.bean.pub.PublicUserInfoBean; import password.pwm.config.PwmSetting; import password.pwm.error.ErrorInformation; import password.pwm.error.PwmError; import password.pwm.error.PwmException; import password.pwm.error.PwmUnrecoverableException; import password.pwm.http.HttpHeader; import password.pwm.http.HttpMethod; import password.pwm.http.client.PwmHttpClient; import password.pwm.http.client.PwmHttpClientRequest; import password.pwm.http.client.PwmHttpClientResponse; import password.pwm.util.java.JsonUtil; import password.pwm.util.logging.PwmLogger; import password.pwm.util.macro.MacroMachine; import password.pwm.util.secure.PwmRandom; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; public class RemoteVerificationMethod implements VerificationMethodSystem { private static final PwmLogger LOGGER = PwmLogger.forClass(RemoteVerificationMethod.class); private String remoteSessionID = PwmRandom.getInstance().randomUUID().toString(); private RemoteVerificationResponseBean lastResponse; private PwmHttpClient pwmHttpClient; private PwmApplication pwmApplication; private UserInfoBean userInfoBean; private SessionLabel sessionLabel; private Locale locale; private String url; @Override public List<UserPrompt> getCurrentPrompts() throws PwmUnrecoverableException { if (lastResponse == null || lastResponse.getUserPrompts() == null) { return null; } final List<UserPrompt> returnObj = new ArrayList<>(); for (final UserPromptBean userPromptBean : lastResponse.getUserPrompts()) { returnObj.add(userPromptBean); } return returnObj; } @Override public String getCurrentDisplayInstructions() { return lastResponse == null ? "" : lastResponse.getDisplayInstructions(); } @Override public ErrorInformation respondToPrompts(final Map<String, String> answers) throws PwmUnrecoverableException { sendRemoteRequest(answers); if (lastResponse != null) { final String errorMsg = lastResponse.getErrorMessage(); if (errorMsg != null && !errorMsg.isEmpty()) { return new ErrorInformation(PwmError.ERROR_REMOTE_ERROR_VALUE, errorMsg); } } return null; } @Override public VerificationState getVerificationState() { return lastResponse == null ? VerificationState.INPROGRESS : lastResponse.getVerificationState(); } @Override public void init(final PwmApplication pwmApplication, final UserInfoBean userInfoBean, final SessionLabel sessionLabel, final Locale locale) throws PwmUnrecoverableException { pwmHttpClient = new PwmHttpClient(pwmApplication, sessionLabel); this.userInfoBean = userInfoBean; this.sessionLabel = sessionLabel; this.locale = locale; this.pwmApplication = pwmApplication; this.url = pwmApplication.getConfig().readSettingAsString(PwmSetting.EXTERNAL_MACROS_REMOTE_RESPONSES_URL); if (url == null || url.isEmpty()) { final String errorMsg = PwmSetting.EXTERNAL_MACROS_REMOTE_RESPONSES_URL.toMenuLocationDebug(null, PwmConstants.DEFAULT_LOCALE) + " must be configured for remote responses"; final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_INVALID_CONFIG, errorMsg); LOGGER.error(sessionLabel, errorInformation); throw new PwmUnrecoverableException(errorInformation); } sendRemoteRequest(null); } private void sendRemoteRequest(final Map<String, String> userResponses) throws PwmUnrecoverableException { lastResponse = null; final Map<String, String> headers = new LinkedHashMap<>(); headers.put(HttpHeader.Content_Type.getHttpName(), PwmConstants.ContentTypeValue.json.getHeaderValue()); headers.put(HttpHeader.Accept_Language.getHttpName(), locale.toLanguageTag()); final RemoteVerificationRequestBean remoteVerificationRequestBean = new RemoteVerificationRequestBean(); remoteVerificationRequestBean.setResponseSessionID(this.remoteSessionID); final MacroMachine macroMachine = MacroMachine.forUser(pwmApplication, PwmConstants.DEFAULT_LOCALE, SessionLabel.SYSTEM_LABEL, userInfoBean.getUserIdentity()); remoteVerificationRequestBean.setUserInfo(PublicUserInfoBean.fromUserInfoBean(userInfoBean, pwmApplication.getConfig(), locale, macroMachine)); remoteVerificationRequestBean.setUserResponses(userResponses); final PwmHttpClientRequest pwmHttpClientRequest = new PwmHttpClientRequest( HttpMethod.POST, url, JsonUtil.serialize(remoteVerificationRequestBean), headers ); try { final PwmHttpClientResponse response = pwmHttpClient.makeRequest(pwmHttpClientRequest); final String responseBodyStr = response.getBody(); this.lastResponse = JsonUtil.deserialize(responseBodyStr, RemoteVerificationResponseBean.class); } catch (PwmException e) { LOGGER.error(sessionLabel, e.getErrorInformation()); throw new PwmUnrecoverableException(e.getErrorInformation()); } catch (Exception e) { final String errorMsg = "error reading remote responses web service response: " + e.getMessage(); final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_SERVICE_NOT_AVAILABLE, errorMsg); LOGGER.error(sessionLabel, errorInformation); throw new PwmUnrecoverableException(errorInformation); } } }