123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- /*
- * 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.ws.server.rest;
- import com.novell.ldapchai.ChaiUser;
- import com.novell.ldapchai.cr.ChaiChallenge;
- import com.novell.ldapchai.cr.Challenge;
- import com.novell.ldapchai.cr.ChallengeSet;
- import com.novell.ldapchai.cr.ResponseSet;
- import com.novell.ldapchai.cr.bean.ChallengeBean;
- import password.pwm.Permission;
- import password.pwm.bean.ResponseInfoBean;
- import password.pwm.bean.UserIdentity;
- import password.pwm.config.PwmSetting;
- import password.pwm.config.profile.ChallengeProfile;
- import password.pwm.config.profile.HelpdeskProfile;
- import password.pwm.config.profile.PwmPasswordPolicy;
- import password.pwm.error.ErrorInformation;
- import password.pwm.error.PwmError;
- import password.pwm.error.PwmException;
- import password.pwm.error.PwmOperationalException;
- import password.pwm.error.PwmUnrecoverableException;
- import password.pwm.i18n.Message;
- import password.pwm.ldap.LdapOperationsHelper;
- import password.pwm.svc.event.AuditEvent;
- import password.pwm.svc.event.AuditRecordFactory;
- import password.pwm.svc.event.HelpdeskAuditRecord;
- import password.pwm.svc.event.UserAuditRecord;
- import password.pwm.svc.stats.Statistic;
- import password.pwm.svc.stats.StatisticsManager;
- import password.pwm.util.operations.CrService;
- import password.pwm.util.operations.PasswordUtility;
- import password.pwm.ws.server.RestRequestBean;
- import password.pwm.ws.server.RestResultBean;
- import password.pwm.ws.server.RestServerHelper;
- import password.pwm.ws.server.ServicePermissions;
- import javax.servlet.http.HttpServletRequest;
- import javax.ws.rs.Consumes;
- import javax.ws.rs.DELETE;
- import javax.ws.rs.GET;
- import javax.ws.rs.POST;
- import javax.ws.rs.Path;
- import javax.ws.rs.Produces;
- import javax.ws.rs.QueryParam;
- import javax.ws.rs.core.Context;
- import javax.ws.rs.core.MediaType;
- import javax.ws.rs.core.Response;
- import java.io.Serializable;
- import java.net.URISyntaxException;
- import java.time.Instant;
- import java.util.ArrayList;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Locale;
- import java.util.Map;
- @Path("/challenges")
- public class RestChallengesServer extends AbstractRestServer {
- private static final ServicePermissions SERVICE_PERMISSIONS = ServicePermissions.builder()
- .adminOnly(false)
- .authRequired(true)
- .blockExternal(true)
- .build();
- public static class Policy {
- public List<ChallengeBean> challenges;
- public List<ChallengeBean> helpdeskChallenges;
- public int minimumRandoms;
- }
- public static class JsonChallengesData implements Serializable {
- public String username;
- public List<ChallengeBean> challenges;
- public List<ChallengeBean> helpdeskChallenges;
- public int minimumRandoms;
- public Policy policy;
- public ResponseInfoBean toResponseInfoBean(final Locale locale, final String csIdentifier)
- throws PwmOperationalException
- {
- final Map<Challenge,String> crMap = new LinkedHashMap<>();
- if (challenges != null) {
- for (final ChallengeBean challengeBean : challenges) {
- final Challenge challenge = ChaiChallenge.fromChallengeBean(challengeBean);
- final String answerText = challengeBean.getAnswer().getAnswerText();
- if (answerText == null || answerText.length() < 1) {
- throw new IllegalArgumentException("missing answerText for challenge '" + challenge.getChallengeText() + "'");
- }
- crMap.put(challenge,answerText);
- }
- }
- final Map<Challenge,String> helpdeskCrMap = new LinkedHashMap<>();
- if (helpdeskChallenges != null) {
- for (final ChallengeBean challengeBean : helpdeskChallenges) {
- final Challenge challenge = ChaiChallenge.fromChallengeBean(challengeBean);
- final String answerText = challengeBean.getAnswer().getAnswerText();
- if (answerText == null || answerText.length() < 1) {
- throw new IllegalArgumentException("missing answerText for helpdesk challenge '" + challenge.getChallengeText() + "'");
- }
- helpdeskCrMap.put(challenge,answerText);
- }
- }
- final ResponseInfoBean responseInfoBean = new ResponseInfoBean(
- crMap,
- helpdeskCrMap,
- locale,
- minimumRandoms,
- csIdentifier,
- null,
- null
- );
- responseInfoBean.setTimestamp(Instant.now());
- return responseInfoBean;
- }
- }
- @Context
- HttpServletRequest request;
- @GET
- @Produces(MediaType.TEXT_HTML)
- public javax.ws.rs.core.Response doHtmlRedirect() throws URISyntaxException {
- return RestServerHelper.handleHtmlRequest();
- }
- @GET
- @Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
- public Response doFormGetChallengeData(
- @QueryParam("answers") final boolean answers,
- @QueryParam("helpdesk") final boolean helpdesk,
- @QueryParam("username") final String username
- )
- throws PwmUnrecoverableException
- {
- final RestRequestBean restRequestBean;
- try {
- restRequestBean = RestServerHelper.initializeRestRequest(request, response, SERVICE_PERMISSIONS, username);
- } catch (PwmUnrecoverableException e) {
- return RestResultBean.fromError(e.getErrorInformation()).asJsonResponse();
- }
- try {
- if (answers && !restRequestBean.getPwmApplication().getConfig().readSettingAsBoolean(PwmSetting.ENABLE_WEBSERVICES_READANSWERS)) {
- throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_SERVICE_NOT_AVAILABLE,"retrieval of answers is not permitted"));
- }
- // gather data
- final ResponseSet responseSet;
- final ChallengeSet challengeSet;
- final ChallengeSet helpdeskChallengeSet;
- final String outputUsername;
- if (restRequestBean.getUserIdentity() == null) {
- final ChaiUser chaiUser = restRequestBean.getPwmSession().getSessionManager().getActor(restRequestBean.getPwmApplication());
- final CrService crService = restRequestBean.getPwmApplication().getCrService();
- responseSet = crService.readUserResponseSet(restRequestBean.getPwmSession().getLabel(), restRequestBean.getPwmSession().getUserInfo().getUserIdentity(), chaiUser);
- challengeSet = restRequestBean.getPwmSession().getUserInfo().getChallengeProfile().getChallengeSet();
- helpdeskChallengeSet = restRequestBean.getPwmSession().getUserInfo().getChallengeProfile().getHelpdeskChallengeSet();
- outputUsername = restRequestBean.getPwmSession().getUserInfo().getUserIdentity().getLdapProfileID();
- } else {
- final ChaiUser chaiUser = restRequestBean.getPwmSession().getSessionManager().getActor(restRequestBean.getPwmApplication(),restRequestBean.getUserIdentity());
- final Locale userLocale = restRequestBean.getPwmSession().getSessionStateBean().getLocale();
- final CrService crService = restRequestBean.getPwmApplication().getCrService();
- responseSet = crService.readUserResponseSet(restRequestBean.getPwmSession().getLabel(),restRequestBean.getUserIdentity(), chaiUser);
- final PwmPasswordPolicy passwordPolicy = PasswordUtility.readPasswordPolicyForUser(
- restRequestBean.getPwmApplication(),
- restRequestBean.getPwmSession().getLabel(),
- restRequestBean.getUserIdentity(),
- chaiUser,userLocale
- );
- final ChallengeProfile challengeProfile = crService.readUserChallengeProfile(
- restRequestBean.getPwmSession().getLabel(),
- restRequestBean.getUserIdentity(),
- chaiUser,
- passwordPolicy,
- userLocale
- );
- challengeSet = challengeProfile.getChallengeSet();
- helpdeskChallengeSet = challengeProfile.getHelpdeskChallengeSet();
- outputUsername = restRequestBean.getUserIdentity().toDelimitedKey();
- }
- // build output
- final JsonChallengesData jsonData = new JsonChallengesData();
- {
- jsonData.username = outputUsername;
- if (responseSet != null) {
- jsonData.challenges = responseSet.asChallengeBeans(answers);
- if (helpdesk) {
- jsonData.helpdeskChallenges = responseSet.asHelpdeskChallengeBeans(answers);
- }
- jsonData.minimumRandoms = responseSet.getChallengeSet().getMinRandomRequired();
- }
- final Policy policy = new Policy();
- if (challengeSet != null) {
- policy.challenges = challengesToBeans(challengeSet.getChallenges());
- policy.minimumRandoms = challengeSet.getMinRandomRequired();
- }
- if (helpdeskChallengeSet != null && helpdesk) {
- policy.helpdeskChallenges = challengesToBeans(helpdeskChallengeSet.getChallenges());
- }
- if (policy.challenges != null || policy.helpdeskChallenges != null) {
- jsonData.policy = policy;
- }
- }
- // update statistics
- if (!restRequestBean.isExternal()) {
- StatisticsManager.incrementStat(restRequestBean.getPwmApplication(), Statistic.REST_CHALLENGES);
- }
- final RestResultBean resultBean = new RestResultBean();
- resultBean.setData(jsonData);
- return resultBean.asJsonResponse();
- } catch (PwmException e) {
- return RestResultBean.fromError(e.getErrorInformation(), restRequestBean).asJsonResponse();
- } catch (Exception e) {
- final String errorMsg = "unexpected error building json response: " + e.getMessage();
- final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg);
- return RestResultBean.fromError(errorInformation, restRequestBean).asJsonResponse();
- }
- }
- @POST
- @Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
- @Consumes(MediaType.APPLICATION_JSON)
- public Response doSetChallengeDataJson(
- final JsonChallengesData jsonInput
- )
- {
- final RestRequestBean restRequestBean;
- try {
- restRequestBean = RestServerHelper.initializeRestRequest(request, response, SERVICE_PERMISSIONS, jsonInput.username);
- } catch (PwmUnrecoverableException e) {
- return RestResultBean.fromError(e.getErrorInformation()).asJsonResponse();
- }
- try {
- if (!restRequestBean.getPwmSession().getSessionManager().checkPermission(restRequestBean.getPwmApplication(), Permission.SETUP_RESPONSE)) {
- throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNAUTHORIZED,"actor does not have required permission"));
- }
- final ChaiUser chaiUser;
- final String userGUID;
- final String csIdentifer;
- final UserIdentity userIdentity;
- final CrService crService = restRequestBean.getPwmApplication().getCrService();
- if (restRequestBean.getUserIdentity() == null) {
- chaiUser = restRequestBean.getPwmSession().getSessionManager().getActor(restRequestBean.getPwmApplication());
- userIdentity = restRequestBean.getPwmSession().getUserInfo().getUserIdentity();
- userGUID = restRequestBean.getPwmSession().getUserInfo().getUserGuid();
- csIdentifer = restRequestBean.getPwmSession().getUserInfo().getChallengeProfile().getChallengeSet().getIdentifier();
- } else {
- userIdentity = restRequestBean.getUserIdentity();
- chaiUser = restRequestBean.getPwmSession().getSessionManager().getActor(restRequestBean.getPwmApplication(),userIdentity);
- userGUID = LdapOperationsHelper.readLdapGuidValue(
- restRequestBean.getPwmApplication(),
- restRequestBean.getPwmSession().getLabel(),
- userIdentity,
- false);
- final ChallengeProfile challengeProfile = crService.readUserChallengeProfile(
- restRequestBean.getPwmSession().getLabel(),
- userIdentity,
- chaiUser,
- PwmPasswordPolicy.defaultPolicy(),
- request.getLocale());
- csIdentifer = challengeProfile.getChallengeSet().getIdentifier();
- }
- final ResponseInfoBean responseInfoBean = jsonInput.toResponseInfoBean(request.getLocale(), csIdentifer);
- crService.writeResponses(userIdentity, chaiUser,userGUID,responseInfoBean);
- // update statistics
- if (!restRequestBean.isExternal()) {
- StatisticsManager.incrementStat(restRequestBean.getPwmApplication(), Statistic.REST_CHALLENGES);
- }
- final String successMsg = Message.Success_SetupResponse.getLocalizedMessage(request.getLocale(),restRequestBean.getPwmApplication().getConfig());
- final RestResultBean resultBean = new RestResultBean();
- resultBean.setError(false);
- resultBean.setSuccessMessage(successMsg);
- return resultBean.asJsonResponse();
- } catch (PwmException e) {
- return RestResultBean.fromError(e.getErrorInformation(), restRequestBean).asJsonResponse();
- } catch (Exception e) {
- final String errorMsg = "unexpected error reading json input: " + e.getMessage();
- final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg);
- return RestResultBean.fromError(errorInformation, restRequestBean).asJsonResponse();
- }
- }
- @DELETE
- @Produces(MediaType.APPLICATION_JSON + ";charset=UTF-8")
- public Response doDeleteChallengeData(
- @QueryParam("username") final String username
- )
- {
- final RestRequestBean restRequestBean;
- try {
- final ServicePermissions servicePermissions = SERVICE_PERMISSIONS.toBuilder()
- .helpdeskPermitted(true)
- .build();
- restRequestBean = RestServerHelper.initializeRestRequest(request, response, servicePermissions, username);
- } catch (PwmUnrecoverableException e) {
- return RestResultBean.fromError(e.getErrorInformation()).asJsonResponse();
- }
- try {
- final HelpdeskProfile helpdeskProfile = restRequestBean.getPwmSession().getSessionManager().getHelpdeskProfile(restRequestBean.getPwmApplication());
- if (restRequestBean.getUserIdentity() == null) {
- if (!restRequestBean.getPwmSession().getSessionManager().checkPermission(restRequestBean.getPwmApplication(), Permission.SETUP_RESPONSE)) {
- throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNAUTHORIZED,"actor does not have required permission"));
- }
- } else {
- if (helpdeskProfile == null) {
- throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNAUTHORIZED,"actor does not have required permission"));
- }
- }
- final ChaiUser chaiUser;
- final String userGUID;
- if (restRequestBean.getUserIdentity() == null) {
- /* clear self */
- chaiUser = restRequestBean.getPwmSession().getSessionManager().getActor(restRequestBean.getPwmApplication());
- userGUID = restRequestBean.getPwmSession().getUserInfo().getUserGuid();
- // mark the event log
- final UserAuditRecord auditRecord = new AuditRecordFactory(restRequestBean.getPwmApplication(), restRequestBean.getPwmSession()).createUserAuditRecord(
- AuditEvent.CLEAR_RESPONSES,
- restRequestBean.getPwmSession().getUserInfo(),
- restRequestBean.getPwmSession()
- );
- restRequestBean.getPwmApplication().getAuditManager().submit(auditRecord);
- } else {
- /* clear 3rd party (helpdesk) */
- final boolean useProxy = helpdeskProfile.readSettingAsBoolean(PwmSetting.HELPDESK_USE_PROXY);
- chaiUser = useProxy
- ? restRequestBean.getPwmApplication().getProxiedChaiUser(restRequestBean.getUserIdentity())
- : restRequestBean.getPwmSession().getSessionManager().getActor(restRequestBean.getPwmApplication(),restRequestBean.getUserIdentity());
- userGUID = LdapOperationsHelper.readLdapGuidValue(
- restRequestBean.getPwmApplication(),
- restRequestBean.getPwmSession().getLabel(),
- restRequestBean.getUserIdentity(),
- false);
- // mark the event log
- final HelpdeskAuditRecord auditRecord = new AuditRecordFactory(restRequestBean.getPwmApplication(), restRequestBean.getPwmSession()).createHelpdeskAuditRecord(
- AuditEvent.HELPDESK_CLEAR_RESPONSES,
- restRequestBean.getPwmSession().getUserInfo().getUserIdentity(),
- null,
- restRequestBean.getUserIdentity(),
- restRequestBean.getPwmSession().getSessionStateBean().getSrcAddress(),
- restRequestBean.getPwmSession().getSessionStateBean().getSrcHostname()
- );
- restRequestBean.getPwmApplication().getAuditManager().submit(auditRecord);
- }
- final CrService crService = restRequestBean.getPwmApplication().getCrService();
- crService.clearResponses(
- restRequestBean.getPwmSession().getLabel(),
- restRequestBean.getUserIdentity(),
- chaiUser,
- userGUID
- );
- // update statistics
- if (!restRequestBean.isExternal()) {
- StatisticsManager.incrementStat(restRequestBean.getPwmApplication(), Statistic.REST_CHALLENGES);
- }
- final String successMsg = Message.Success_Unknown.getLocalizedMessage(request.getLocale(),restRequestBean.getPwmApplication().getConfig());
- final RestResultBean resultBean = new RestResultBean();
- resultBean.setError(false);
- resultBean.setSuccessMessage(successMsg);
- return resultBean.asJsonResponse();
- } catch (PwmException e) {
- return RestResultBean.fromError(e.getErrorInformation(), restRequestBean).asJsonResponse();
- } catch (Exception e) {
- final String errorMsg = "unexpected error delete responses: " + e.getMessage();
- final ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_UNKNOWN, errorMsg);
- return RestResultBean.fromError(errorInformation, restRequestBean).asJsonResponse();
- }
- }
- private static List<ChallengeBean> challengesToBeans(final List<Challenge> challenges) {
- final List<ChallengeBean> returnList = new ArrayList<>();
- for (final Challenge challenge : challenges) {
- returnList.add(challenge.asChallengeBean());
- }
- return returnList;
- }
- }
|