/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2013 The ZAP Development Team * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zaproxy.zap.extension.users; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.json.JSONException; import net.sf.json.JSONObject; import org.apache.log4j.Logger; import org.parosproxy.paros.control.Control; import org.parosproxy.paros.model.Model; import org.zaproxy.zap.authentication.AuthenticationMethodType; import org.zaproxy.zap.extension.api.API; import org.zaproxy.zap.extension.api.ApiAction; import org.zaproxy.zap.extension.api.ApiDynamicActionImplementor; import org.zaproxy.zap.extension.api.ApiException; import org.zaproxy.zap.extension.api.ApiException.Type; import org.zaproxy.zap.extension.api.ApiImplementor; import org.zaproxy.zap.extension.api.ApiResponse; import org.zaproxy.zap.extension.api.ApiResponseElement; import org.zaproxy.zap.extension.api.ApiResponseList; import org.zaproxy.zap.extension.api.ApiResponseSet; import org.zaproxy.zap.extension.api.ApiView; import org.zaproxy.zap.extension.authentication.ExtensionAuthentication; import org.zaproxy.zap.model.Context; import org.zaproxy.zap.users.User; import org.zaproxy.zap.utils.ApiUtils; /** * The API for manipulating {@link User Users}. */ public class UsersAPI extends ApiImplementor { private static final Logger log = Logger.getLogger(UsersAPI.class); private static final String PREFIX = "users"; private static final String VIEW_USERS_LIST = "usersList"; private static final String VIEW_GET_USER_BY_ID = "getUserById"; private static final String VIEW_GET_AUTH_CREDENTIALS = "getAuthenticationCredentials"; private static final String VIEW_GET_AUTH_CREDENTIALS_CONFIG_PARAMETERS = "getAuthenticationCredentialsConfigParams"; private static final String ACTION_NEW_USER = "newUser"; private static final String ACTION_REMOVE_USER = "removeUser"; private static final String ACTION_SET_ENABLED = "setUserEnabled"; private static final String ACTION_SET_NAME = "setUserName"; private static final String ACTION_SET_AUTH_CREDENTIALS = "setAuthenticationCredentials"; public static final String PARAM_CONTEXT_ID = "contextId"; public static final String PARAM_USER_ID = "userId"; private static final String PARAM_USER_NAME = "name"; private static final String PARAM_ENABLED = "enabled"; private static final String PARAM_CREDENTIALS_CONFIG_PARAMS = "authCredentialsConfigParams"; private ExtensionUserManagement extension; private Map<Integer, ApiDynamicActionImplementor> loadedAuthenticationMethodActions; public UsersAPI(ExtensionUserManagement extension) { super(); this.extension = extension; this.addApiView(new ApiView(VIEW_USERS_LIST, null, new String[] { PARAM_CONTEXT_ID })); this.addApiView(new ApiView(VIEW_GET_USER_BY_ID, null, new String[] { PARAM_CONTEXT_ID, PARAM_USER_ID })); this.addApiView(new ApiView(VIEW_GET_AUTH_CREDENTIALS_CONFIG_PARAMETERS, new String[] { PARAM_CONTEXT_ID })); this.addApiView(new ApiView(VIEW_GET_AUTH_CREDENTIALS, new String[] { PARAM_CONTEXT_ID, PARAM_USER_ID })); this.addApiAction(new ApiAction(ACTION_NEW_USER, new String[] { PARAM_CONTEXT_ID, PARAM_USER_NAME })); this.addApiAction(new ApiAction(ACTION_REMOVE_USER, new String[] { PARAM_CONTEXT_ID, PARAM_USER_ID })); this.addApiAction(new ApiAction(ACTION_SET_ENABLED, new String[] { PARAM_CONTEXT_ID, PARAM_USER_ID, PARAM_ENABLED })); this.addApiAction(new ApiAction(ACTION_SET_NAME, new String[] { PARAM_CONTEXT_ID, PARAM_USER_ID, PARAM_USER_NAME })); this.addApiAction(new ApiAction(ACTION_SET_AUTH_CREDENTIALS, new String[] { PARAM_CONTEXT_ID, PARAM_USER_ID }, new String[] { PARAM_CREDENTIALS_CONFIG_PARAMS })); // Load the authentication method actions if (Control.getSingleton() != null) { ExtensionAuthentication authenticationExtension = (ExtensionAuthentication) Control .getSingleton().getExtensionLoader().getExtension(ExtensionAuthentication.NAME); this.loadedAuthenticationMethodActions = new HashMap<>(); if (authenticationExtension != null) { for (AuthenticationMethodType t : authenticationExtension.getAuthenticationMethodTypes()) { ApiDynamicActionImplementor i = t.getSetCredentialsForUserApiAction(); if (i != null) { loadedAuthenticationMethodActions.put(t.getUniqueIdentifier(), i); } } } } } @Override public String getPrefix() { return PREFIX; } @Override public ApiResponse handleApiView(String name, JSONObject params) throws ApiException { log.debug("handleApiView " + name + " " + params.toString()); switch (name) { case VIEW_USERS_LIST: ApiResponseList usersListResponse = new ApiResponseList(name); // Get the users List<User> users; if (hasContextId(params)) users = extension.getContextUserAuthManager(getContextId(params)).getUsers(); else { users = new ArrayList<>(); for (Context c : Model.getSingleton().getSession().getContexts()) users.addAll(extension.getContextUserAuthManager(c.getIndex()).getUsers()); } // Prepare the response for (User user : users) usersListResponse.addItem(buildResponseFromUser(user)); return usersListResponse; case VIEW_GET_USER_BY_ID: return buildResponseFromUser(getUser(params)); case VIEW_GET_AUTH_CREDENTIALS: return getUser(params).getAuthenticationCredentials().getApiResponseRepresentation(); case VIEW_GET_AUTH_CREDENTIALS_CONFIG_PARAMETERS: AuthenticationMethodType type = ApiUtils.getContextByParamId(params, PARAM_CONTEXT_ID) .getAuthenticationMethod().getType(); ApiDynamicActionImplementor a = loadedAuthenticationMethodActions.get(type.getUniqueIdentifier()); return a.buildParamsDescription(); default: throw new ApiException(ApiException.Type.BAD_VIEW); } } @Override public ApiResponse handleApiAction(String name, JSONObject params) throws ApiException { log.debug("handleApiAction " + name + " " + params.toString()); User user; Context context; switch (name) { case ACTION_NEW_USER: context = ApiUtils.getContextByParamId(params, PARAM_CONTEXT_ID); String userName = ApiUtils.getNonEmptyStringParam(params, PARAM_USER_NAME); user = new User(context.getIndex(), userName); user.setAuthenticationCredentials(context.getAuthenticationMethod() .createAuthenticationCredentials()); extension.getContextUserAuthManager(context.getIndex()).addUser(user); context.save(); return new ApiResponseElement(PARAM_USER_ID, String.valueOf(user.getId())); case ACTION_REMOVE_USER: context = ApiUtils.getContextByParamId(params, PARAM_CONTEXT_ID); int userId = ApiUtils.getIntParam(params, PARAM_USER_ID); boolean deleted = extension.getContextUserAuthManager(context.getIndex()).removeUserById(userId); if (deleted) { context.save(); return ApiResponseElement.OK; } else return ApiResponseElement.FAIL; case ACTION_SET_ENABLED: boolean enabled = false; try { enabled = params.getBoolean(PARAM_ENABLED); } catch (JSONException e) { throw new ApiException(Type.ILLEGAL_PARAMETER, PARAM_ENABLED + " - should be boolean"); } user = getUser(params); user.setEnabled(enabled); user.getContext().save(); return ApiResponseElement.OK; case ACTION_SET_NAME: String nameSN = params.getString(PARAM_USER_NAME); if (nameSN == null || nameSN.isEmpty()) throw new ApiException(Type.MISSING_PARAMETER, PARAM_USER_NAME); user = getUser(params); user.setName(nameSN); user.getContext().save(); return ApiResponseElement.OK; case ACTION_SET_AUTH_CREDENTIALS: // Prepare the params JSONObject actionParams; if (params.has(PARAM_CREDENTIALS_CONFIG_PARAMS)) actionParams = API.getParams(params.getString(PARAM_CREDENTIALS_CONFIG_PARAMS)); else actionParams = new JSONObject(); context = ApiUtils.getContextByParamId(params, PARAM_CONTEXT_ID); actionParams.put(PARAM_CONTEXT_ID, context.getIndex()); actionParams.put(PARAM_USER_ID, getUserId(params)); // Run the method ApiDynamicActionImplementor a = loadedAuthenticationMethodActions.get(context .getAuthenticationMethod().getType().getUniqueIdentifier()); a.handleAction(actionParams); context.save(); return ApiResponseElement.OK; default: throw new ApiException(Type.BAD_ACTION); } } /** * Builds the response describing an User. * * @param u the user * @return the api response */ private ApiResponse buildResponseFromUser(User u) { Map<String, String> fields = new HashMap<>(); fields.put("name", u.getName()); fields.put("id", Integer.toString(u.getId())); fields.put("contextId", Integer.toString(u.getContextId())); fields.put("enabled", Boolean.toString(u.isEnabled())); fields.put("credentials", u.getAuthenticationCredentials().getApiResponseRepresentation().toJSON() .toString()); ApiResponseSet<String> response = new ApiResponseSet<String>("user", fields); return response; } /** * Gets the user id from the parameters or throws a Missing Parameter exception, if any problems * occurred. * * @param params the params * @return the user id * @throws ApiException the api exception */ private int getUserId(JSONObject params) throws ApiException { return ApiUtils.getIntParam(params, PARAM_USER_ID); } /** * Gets the user corresponding to the id provided in the parameters or throws an ApiException id * any problems occurred. * * @param params the params * @return the user * @throws ApiException the api exception */ private User getUser(JSONObject params) throws ApiException { int contextId = getContextId(params); int userId = getUserId(params); User user = extension.getContextUserAuthManager(contextId).getUserById(userId); if (user == null) throw new ApiException(Type.USER_NOT_FOUND, PARAM_USER_ID); return user; } /** * Gets the context id from the parameters or throws a Missing Parameter exception, if any * problems occured. * * @param params the params * @return the context id * @throws ApiException the api exception */ private int getContextId(JSONObject params) throws ApiException { return ApiUtils.getIntParam(params, PARAM_CONTEXT_ID); } private boolean hasContextId(JSONObject params) { try { params.getInt(PARAM_CONTEXT_ID); } catch (JSONException ex) { return false; } return true; } }