/*
* 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.authentication;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;
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.ApiView;
import org.zaproxy.zap.model.Context;
import org.zaproxy.zap.utils.ApiUtils;
/**
* The API for manipulating the {@link org.zaproxy.zap.authentication.AuthenticationMethod AuthenticationMethod} for
* {@link Context Contexts}.
*/
public class AuthenticationAPI extends ApiImplementor {
private static final Logger log = Logger.getLogger(AuthenticationAPI.class);
private static final String PREFIX = "authentication";
private static final String VIEW_GET_AUTHENTICATION = "getAuthenticationMethod";
private static final String VIEW_GET_LOGGED_IN_INDICATOR = "getLoggedInIndicator";
private static final String VIEW_GET_LOGGED_OUT_INDICATOR = "getLoggedOutIndicator";
private static final String VIEW_GET_METHOD_CONFIG_PARAMETERS = "getAuthenticationMethodConfigParams";
private static final String VIEW_GET_SUPPORTED_METHODS = "getSupportedAuthenticationMethods";
private static final String ACTION_SET_LOGGED_IN_INDICATOR = "setLoggedInIndicator";
private static final String ACTION_SET_LOGGED_OUT_INDICATOR = "setLoggedOutIndicator";
private static final String ACTION_SET_METHOD = "setAuthenticationMethod";
public static final String PARAM_CONTEXT_ID = "contextId";
private static final String PARAM_LOGGED_IN_INDICATOR = "loggedInIndicatorRegex";
private static final String PARAM_LOGGED_OUT_INDICATOR = "loggedOutIndicatorRegex";
private static final String PARAM_METHOD_NAME = "authMethodName";
private static final String PARAM_METHOD_CONFIG_PARAMS = "authMethodConfigParams";
private Map<String, ApiDynamicActionImplementor> loadedAuthenticationMethodActions;
public AuthenticationAPI(ExtensionAuthentication extension) {
super();
this.addApiView(new ApiView(VIEW_GET_SUPPORTED_METHODS));
this.addApiView(new ApiView(VIEW_GET_METHOD_CONFIG_PARAMETERS, new String[] { PARAM_METHOD_NAME }));
this.addApiView(new ApiView(VIEW_GET_AUTHENTICATION, new String[] { PARAM_CONTEXT_ID }));
this.addApiView(new ApiView(VIEW_GET_LOGGED_IN_INDICATOR, new String[] { PARAM_CONTEXT_ID }));
this.addApiView(new ApiView(VIEW_GET_LOGGED_OUT_INDICATOR, new String[] { PARAM_CONTEXT_ID }));
this.loadedAuthenticationMethodActions = new HashMap<>();
// Load the authentication method actions
if (extension != null) {
for (AuthenticationMethodType t : extension.getAuthenticationMethodTypes()) {
ApiDynamicActionImplementor i = t.getSetMethodForContextApiAction();
if (i != null) {
loadedAuthenticationMethodActions.put(i.getName(), i);
}
}
}
this.addApiAction(new ApiAction(ACTION_SET_METHOD,
new String[] { PARAM_CONTEXT_ID, PARAM_METHOD_NAME },
new String[] { PARAM_METHOD_CONFIG_PARAMS }));
this.addApiAction(new ApiAction(ACTION_SET_LOGGED_IN_INDICATOR, new String[] { PARAM_CONTEXT_ID,
PARAM_LOGGED_IN_INDICATOR }));
this.addApiAction(new ApiAction(ACTION_SET_LOGGED_OUT_INDICATOR, new String[] { PARAM_CONTEXT_ID,
PARAM_LOGGED_OUT_INDICATOR }));
}
@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_GET_AUTHENTICATION:
return getContext(params).getAuthenticationMethod().getApiResponseRepresentation();
case VIEW_GET_LOGGED_IN_INDICATOR:
Pattern loggedInPattern = getContext(params).getAuthenticationMethod()
.getLoggedInIndicatorPattern();
if (loggedInPattern != null)
return new ApiResponseElement("logged_in_regex", loggedInPattern.toString());
else
return new ApiResponseElement("logged_in_regex", "");
case VIEW_GET_LOGGED_OUT_INDICATOR:
Pattern loggedOutPattern = getContext(params).getAuthenticationMethod()
.getLoggedOutIndicatorPattern();
if (loggedOutPattern != null)
return new ApiResponseElement("logged_out_regex", loggedOutPattern.toString());
else
return new ApiResponseElement("logged_out_regex", "");
case VIEW_GET_SUPPORTED_METHODS:
ApiResponseList supportedMethods = new ApiResponseList("supportedMethods");
for (ApiDynamicActionImplementor a : loadedAuthenticationMethodActions.values())
supportedMethods.addItem(new ApiResponseElement("methodName", a.getName()));
return supportedMethods;
case VIEW_GET_METHOD_CONFIG_PARAMETERS:
ApiDynamicActionImplementor a = getSetMethodActionImplementor(params);
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());
Context context;
switch (name) {
case ACTION_SET_LOGGED_IN_INDICATOR:
String loggedInIndicator = params.getString(PARAM_LOGGED_IN_INDICATOR);
if (loggedInIndicator == null || loggedInIndicator.isEmpty())
throw new ApiException(Type.MISSING_PARAMETER, PARAM_LOGGED_IN_INDICATOR);
context = getContext(params);
context.getAuthenticationMethod().setLoggedInIndicatorPattern(loggedInIndicator);
context.save();
return ApiResponseElement.OK;
case ACTION_SET_LOGGED_OUT_INDICATOR:
String loggedOutIndicator = params.getString(PARAM_LOGGED_OUT_INDICATOR);
if (loggedOutIndicator == null || loggedOutIndicator.isEmpty())
throw new ApiException(Type.MISSING_PARAMETER, PARAM_LOGGED_OUT_INDICATOR);
context = getContext(params);
context.getAuthenticationMethod().setLoggedOutIndicatorPattern(loggedOutIndicator);
context.save();
return ApiResponseElement.OK;
case ACTION_SET_METHOD:
// Prepare the params
JSONObject actionParams;
if (params.has(PARAM_METHOD_CONFIG_PARAMS))
actionParams = API.getParams(params.getString(PARAM_METHOD_CONFIG_PARAMS));
else
actionParams = new JSONObject();
context = getContext(params);
actionParams.put(PARAM_CONTEXT_ID, context.getIndex());
// Run the method
getSetMethodActionImplementor(params).handleAction(actionParams);
context.save();
return ApiResponseElement.OK;
default:
throw new ApiException(Type.BAD_ACTION);
}
}
/**
* Gets the sets the method action implementor or throws a Missing Parameter exception, if any
* problems occured.
*
* @param params the params
* @return the sets the method action implementor
* @throws ApiException the api exception
*/
private ApiDynamicActionImplementor getSetMethodActionImplementor(JSONObject params) throws ApiException {
ApiDynamicActionImplementor a = loadedAuthenticationMethodActions.get(ApiUtils
.getNonEmptyStringParam(params, PARAM_METHOD_NAME));
if (a == null)
throw new ApiException(Type.DOES_NOT_EXIST,
"No authentication method type matches the provided value.");
return a;
}
/**
* Gets the context from the parameters or throws a Missing Parameter exception, if any problems
* occured.
*
* @param params the params
* @return the context
* @throws ApiException the api exception
*/
private Context getContext(JSONObject params) throws ApiException {
// NOTE: Still use this method as maybe we'll switch to using context names instead of id
int contextId = getContextId(params);
Context context = Model.getSingleton().getSession().getContext(contextId);
if (context == null)
throw new ApiException(Type.CONTEXT_NOT_FOUND, PARAM_CONTEXT_ID);
return context;
}
/**
* 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 {
try {
return params.getInt(PARAM_CONTEXT_ID);
} catch (JSONException ex) {
throw new ApiException(ApiException.Type.MISSING_PARAMETER, PARAM_CONTEXT_ID);
}
}
@SuppressWarnings("unused")
private boolean hasContextId(JSONObject params) {
try {
params.getInt(PARAM_CONTEXT_ID);
} catch (JSONException ex) {
return false;
}
return true;
}
}