All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.parosproxy.paros.network.HttpSender Maven / Gradle / Ivy

Go to download

The Zed Attack Proxy (ZAP) is an easy to use integrated penetration testing tool for finding vulnerabilities in web applications. It is designed to be used by people with a wide range of security experience and as such is ideal for developers and functional testers who are new to penetration testing. ZAP provides automated scanners as well as a set of tools that allow you to find security vulnerabilities manually.

The newest version!
/*
 *
 * Paros and its related class files.
 *
 * Paros is an HTTP/HTTPS proxy for assessing web application security.
 * Copyright (C) 2003-2004 Chinotec Technologies Company
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Clarified Artistic License
 * as published by the Free Software Foundation.
 *
 * 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
 * Clarified Artistic License for more details.
 *
 * You should have received a copy of the Clarified Artistic License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
// ZAP: 2011/09/19 Added debugging
// ZAP: 2012/04/23 Removed unnecessary cast.
// ZAP: 2012/05/08 Use custom http client on "Connection: Upgrade" in executeMethod().
//                 Retrieve upgraded socket and save for later use in send() method.
// ZAP: 2012/08/07 Issue 342 Support the HttpSenderListener
// ZAP: 2012/12/27 Do not read request body on Server-Sent Event streams.
// ZAP: 2013/01/03 Resolved Checkstyle issues: removed throws HttpException
//                 declaration where IOException already appears,
//                 introduced two helper methods for notifying listeners.
// ZAP: 2013/01/19 Issue 459: Active scanner locking
// ZAP: 2013/01/23 Clean up of exception handling/logging.
// ZAP: 2013/01/30 Issue 478: Allow to choose to send ZAP's managed cookies on
// a single Cookie request header and set it as the default
// ZAP: 2013/07/10 Issue 720: Cannot send non standard http methods
// ZAP: 2013/07/14 Issue 729: Update NTLM authentication code
// ZAP: 2013/07/25 Added support for sending the message from the perspective of a User
// ZAP: 2013/08/31 Reauthentication when sending a message from the perspective of a User
// ZAP: 2013/09/07 Switched to using HttpState for requesting User for cookie management
// ZAP: 2013/09/26 Issue 716: ZAP flags its own HTTP responses
// ZAP: 2013/09/26 Issue 656: Content-length: 0 in GET requests
// ZAP: 2013/09/29 Deprecating configuring HTTP Authentication through Options
// ZAP: 2013/11/16 Issue 837: Update, always, the HTTP request sent/forward by ZAP's proxy
// ZAP: 2013/12/11 Corrected log.info calls to use debug
// ZAP: 2014/03/04 Issue 1043: Custom active scan dialog
// ZAP: 2014/03/23 Issue 412: Enable unsafe SSL/TLS renegotiation option not saved
// ZAP: 2014/03/23 Issue 416: Normalise how multiple related options are managed throughout ZAP
// and enhance the usability of some options
// ZAP: 2014/03/29 Issue 1132: HttpSender ignores the "Send single cookie request header" option
// ZAP: 2014/08/14 Issue 1291: 407 Proxy Authentication Required while active scanning
// ZAP: 2014/10/25 Issue 1062: Added a getter for the HttpClient.
// ZAP: 2014/10/28 Issue 1390: Force https on cfu call
// ZAP: 2014/11/25 Issue 1411: Changed getUser() visibility
// ZAP: 2014/12/11 Added JavaDoc to constructor and removed the instance variable allowState.
// ZAP: 2015/04/09 Allow to specify the maximum number of retries on I/O error.
// ZAP: 2015/04/09 Allow to specify the maximum number of redirects.
// ZAP: 2015/04/09 Allow to specify if circular redirects are allowed.
// ZAP: 2015/06/12 Issue 1459: Add an HTTP sender listener script
// ZAP: 2016/05/24 Issue 2463: Websocket not proxied when outgoing proxy is set
// ZAP: 2016/05/27 Issue 2484: Circular Redirects
// ZAP: 2016/06/08 Set User-Agent header defined in options as default for (internal) CONNECT
// requests
// ZAP: 2016/06/10 Allow to validate the URI of the redirections before being followed
// ZAP: 2016/08/04 Added removeListener(..)
// ZAP: 2016/12/07 Add initiator constant for AJAX spider requests
// ZAP: 2016/12/12 Add initiator constant for Forced Browse requests
// ZAP: 2017/03/27 Introduce HttpRequestConfig.
// ZAP: 2017/06/12 Allow to ignore listeners.
// ZAP: 2017/06/19 Allow to send a request with custom socket timeout.
// ZAP: 2017/11/20 Add initiator constant for Token Generator requests.
// ZAP: 2017/11/27 Use custom CookieSpec (ZapCookieSpec).
// ZAP: 2017/12/20 Apply socket connect timeout (Issue 4171).
// ZAP: 2018/02/06 Make the lower case changes locale independent (Issue 4327).
// ZAP: 2018/02/19 Added WEB_SOCKET_INITIATOR.
// ZAP: 2018/02/23 Issue 1161: Allow to override the global session tracking setting
//                 Fix Session Tracking button sync
// ZAP: 2018/08/03 Added AUTHENTICATION_HELPER_INITIATOR.
// ZAP: 2018/09/17 Set the user to messages created for redirections (Issue 2531).
// ZAP: 2018/10/12 Deprecate getClient(), it exposes implementation details.
// ZAP: 2019/03/24 Removed commented and unused sendAndReceive method.
// ZAP: 2019/06/01 Normalise line endings.
// ZAP: 2019/06/05 Normalise format/style.
// ZAP: 2019/08/19 Reinstate proxy auth credentials when HTTP state is changed.
// ZAP: 2019/09/17 Use remove() instead of set(null) on IN_LISTENER.
// ZAP: 2019/09/25 Add option to disable cookies
// ZAP: 2020/04/20 Configure if the names should be resolved or not (Issue 29).
// ZAP: 2020/09/04 Added AUTHENTICATION_POLL_INITIATOR
// ZAP: 2020/11/26 Use Log4j 2 classes for logging.
// ZAP: 2020/12/09 Set content encoding to the response body.
// ZAP: 2021/05/14 Remove redundant type arguments and empty statement.
// ZAP: 2022/01/04 Add initiator constant OAST_INITIATOR for OAST requests.
// ZAP: 2022/04/08 Deprecate getSSLConnector() and executeMethod.
// ZAP: 2022/04/10 Add support for unencoded redirects
// ZAP: 2022/04/11 Deprecate set/getUserAgent() and remove userAgent/modifyUserAgent().
// ZAP: 2022/04/11 Prevent null listeners and add JavaDoc to add/removeListener.
// ZAP: 2022/04/23 Use main connection options directly.
// ZAP: 2022/04/24 Notify listeners of all redirects followed.
// ZAP: 2022/04/24 Move network initialisations from ZAP class.
// ZAP: 2022/04/24 Allow to download to file.
// ZAP: 2022/04/27 Expose global HTTP state enabled status.
// ZAP: 2022/04/27 Use latest proxy settings always.
// ZAP: 2022/04/29 Deprecate setAllowCircularRedirects.
// ZAP: 2022/05/04 Always use single cookie request header.
// ZAP: 2022/05/04 Use latest timeout/user-agent always.
// ZAP: 2022/05/20 Address deprecation warnings with ConnectionParam.
// ZAP: 2022/05/29 Remove redundant checks and create SSLConnector always.
// ZAP: 2022/05/30 Use shared connection pool.
// ZAP: 2022/06/03 Remove commented code and make listeners comparator final.
// ZAP: 2022/06/03 Move implementation to HttpSenderParos.
// ZAP: 2022/06/05 Remove usage of HttpException.
// ZAP: 2022/06/07 Address deprecation warnings with HttpSenderParos.
// ZAP: 2022/06/13 Added param digger initiator.
// ZAP: 2022/12/09 Allow to restore HttpSenderImpl state.
// ZAP: 2023/03/31 Deprecate CFU initiator and add file download with configs.
package org.parosproxy.paros.network;

import java.io.IOException;
import java.nio.file.Path;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpState;
import org.zaproxy.zap.network.HttpRedirectionValidator;
import org.zaproxy.zap.network.HttpRequestConfig;
import org.zaproxy.zap.network.HttpSenderContext;
import org.zaproxy.zap.network.HttpSenderImpl;
import org.zaproxy.zap.network.HttpSenderListener;
import org.zaproxy.zap.users.User;

public class HttpSender {
    public static final int PROXY_INITIATOR = 1;
    public static final int ACTIVE_SCANNER_INITIATOR = 2;
    public static final int SPIDER_INITIATOR = 3;
    public static final int FUZZER_INITIATOR = 4;
    public static final int AUTHENTICATION_INITIATOR = 5;
    public static final int MANUAL_REQUEST_INITIATOR = 6;

    /**
     * @deprecated (2.13.0) CFU requests are sent without notifying listeners.
     */
    @Deprecated(since = "2.13.0")
    public static final int CHECK_FOR_UPDATES_INITIATOR = 7;

    public static final int BEAN_SHELL_INITIATOR = 8;
    public static final int ACCESS_CONTROL_SCANNER_INITIATOR = 9;
    public static final int AJAX_SPIDER_INITIATOR = 10;
    public static final int FORCED_BROWSE_INITIATOR = 11;
    public static final int TOKEN_GENERATOR_INITIATOR = 12;
    public static final int WEB_SOCKET_INITIATOR = 13;
    public static final int AUTHENTICATION_HELPER_INITIATOR = 14;
    public static final int AUTHENTICATION_POLL_INITIATOR = 15;
    public static final int OAST_INITIATOR = 16;
    public static final int PARAM_DIGGER_INITIATOR = 17;

    private static final HttpRequestConfig NO_REDIRECTS = HttpRequestConfig.builder().build();
    private static final HttpRequestConfig FOLLOW_REDIRECTS =
            HttpRequestConfig.builder().setFollowRedirects(true).build();

    @SuppressWarnings("deprecation")
    private static final HttpSenderParos PAROS_IMPL = new HttpSenderParos();

    @SuppressWarnings("rawtypes")
    private static HttpSenderImpl impl = PAROS_IMPL;

    private static Object implState;

    private HttpSenderContext ctx;

    private final int initiator;

    /** Note: Not part of the public API. */
    public static  void setImpl(HttpSenderImpl impl) {
        if (HttpSender.impl != PAROS_IMPL) {
            implState = HttpSender.impl.saveState();
        }

        HttpSender.impl = impl == null ? PAROS_IMPL : impl;

        if (HttpSender.impl != PAROS_IMPL) {
            HttpSender.impl.restoreState(implState);
            implState = null;
        }
    }

    /**
     * Constructs an {@code HttpSender}.
     *
     * 

The {@code initiator} is used to indicate the component that is sending the messages when * the {@code HttpSenderListener}s are notified of messages sent and received. * * @param connectionParam the parameters used to setup the connections to target hosts * @param useGlobalState {@code true} if the messages sent/received should use the global HTTP * state, {@code false} if should use a non shared HTTP state * @param initiator the ID of the initiator of the HTTP messages sent * @see ConnectionParam#getHttpState() * @see HttpSenderListener * @see HttpMessage#getRequestingUser() * @deprecated (2.12.0) Use {@link #HttpSender(int)} instead, refer also to {@link * #setUseGlobalState(boolean)}. */ @Deprecated public HttpSender(ConnectionParam connectionParam, boolean useGlobalState, int initiator) { this(useGlobalState, initiator); } /** * Constructs an {@code HttpSender}. * *

Refer to {@link #setUseGlobalState(boolean)} to know how the HTTP state is managed. * *

The {@code initiator} is used to indicate the component that is sending the messages when * the {@code HttpSenderListener}s are notified of messages sent and received. * * @param initiator the ID of the initiator of the HTTP messages sent * @since 2.12.0 * @see HttpSenderListener */ public HttpSender(int initiator) { this(true, initiator); } private HttpSender(boolean useGlobalState, int initiator) { this.initiator = initiator; HttpSenderContext createdCtx = impl.createContext(this, initiator); if (impl.getContext(this) == null) { ctx = createdCtx; } setUseGlobalState(useGlobalState); setUseCookies(true); } private HttpSenderContext getContext() { if (ctx != null) { return ctx; } return impl.getContext(this); } /** * Gets the {@code SSLConnector} of the client. * * @return the {@code SSLConnector} used by the sender. * @deprecated (2.12.0) It will be removed in a following version. */ @Deprecated public static SSLConnector getSSLConnector() { return PAROS_IMPL.getSslConnector(); } /** * Sets whether or not the global state should be used. Defaults to {@code true}. * *

If {@code enableGlobalState} is {@code true} the {@code HttpSender} will use the HTTP * state given by the connections options iff the HTTP state is enabled there otherwise it * doesn't have any state (i.e. cookies are disabled). If {@code enableGlobalState} is {@code * false} it uses a non shared HTTP state. * *

Note: The actual state used is overridden when {@link * #getUser(HttpMessage)} returns non-{@code null}. * * @param enableGlobalState {@code true} if the global state should be used, {@code false} * otherwise. * @since 2.8.0 * @see #isGlobalStateEnabled() * @see #setUseCookies(boolean) */ public void setUseGlobalState(boolean enableGlobalState) { getContext().setUseGlobalState(enableGlobalState); } /** * Tells whether or not the global HTTP state is enabled. * * @return {@code true} if the global HTTP state is enabled, {@code false} otherwise. * @since 2.12.0 * @see #setUseGlobalState(boolean) */ public boolean isGlobalStateEnabled() { return impl.isGlobalStateEnabled(); } /** * Sets whether or not the requests sent should keep track of cookies. * * @param shouldUseCookies {@code true} if cookies should be used, {@code false} otherwise. * @since 2.9.0 * @see #setUseGlobalState(boolean) */ public void setUseCookies(boolean shouldUseCookies) { getContext().setUseCookies(shouldUseCookies); } /** * Executes the given method. * * @param method the method. * @param state the state, might be {@code null}. * @return the status code. * @throws IOException if an error occurred while executing the method. * @deprecated (2.12.0) Use one of the {@code sendAndReceive} methods. It will be removed in a * following version. */ @Deprecated public int executeMethod(HttpMethod method, HttpState state) throws IOException { HttpSenderContext ctxTemp = getContext(); if (!(ctxTemp instanceof HttpSenderContextParos)) { ctxTemp = PAROS_IMPL.createContext(this, initiator); } return PAROS_IMPL.executeMethodImpl((HttpSenderContextParos) ctxTemp, method, state); } /** * @deprecated (2.12.0) No longer needed. */ @Deprecated public void shutdown() {} /** * Downloads the response (body) to the given file. * *

The body in the given {@code message} will be empty. * * @param message the message containing the request to send. * @param file the file where to save the response body. * @throws IOException if an error occurred while sending the request or while downloading. * @since 2.12.0 * @see #setFollowRedirect(boolean) */ public void sendAndReceive(HttpMessage message, Path file) throws IOException { sendAndReceive(message, null, file); } /** * Downloads the response (body) to the given file, using the given request configurations. * *

The body in the given {@code message} will be empty. * * @param message the message containing the request to send. * @param requestConfig the request configurations. * @param file the file where to save the response body. * @throws IOException if an error occurred while sending the request or while downloading. * @since 2.13.0 */ public void sendAndReceive(HttpMessage message, HttpRequestConfig requestConfig, Path file) throws IOException { sendImpl(requestConfig, message, file); } public void sendAndReceive(HttpMessage msg) throws IOException { sendImpl(null, msg, null); } /** * Send and receive a HttpMessage. * * @param msg * @param isFollowRedirect * @throws IOException * @see #sendAndReceive(HttpMessage, HttpRequestConfig) */ public void sendAndReceive(HttpMessage msg, boolean isFollowRedirect) throws IOException { sendImpl(isFollowRedirect ? FOLLOW_REDIRECTS : NO_REDIRECTS, msg, null); } /** * Gets the user set in this {@code HttpSender} if any, otherwise the one in the given {@code * HttpMessage}. * * @param msg usually the message being sent, that might have a user. * @return the user set in the {@code HttpSender} or in the given {@code HttpMessage}. Might be * {@code null} if no user set. * @throws NullPointerException if the given message is {@code null}. * @since 2.4.1 * @see #setUser(User) * @see HttpMessage#getRequestingUser() */ public User getUser(HttpMessage msg) { return getContext().getUser(msg); } public void setFollowRedirect(boolean followRedirect) { getContext().setFollowRedirects(followRedirect); } /** * @return Returns the userAgent. * @deprecated (2.12.0) No longer supported, it returns an empty string. * @see #setUserAgent(String) */ @Deprecated public static String getUserAgent() { return ""; } /** * @param userAgent The userAgent to set. * @deprecated (2.12.0) No longer supported, use a {@link HttpSenderListener} to actually set * the user agent. */ @Deprecated public static void setUserAgent(String userAgent) {} /** * Adds the given listener to be notified of each message sent/received by each {@code * HttpSender}. * *

The listener might be notified concurrently. * * @param listener the listener to add. * @since 2.0.0 * @throws NullPointerException if the given listener is {@code null}. */ public static void addListener(HttpSenderListener listener) { impl.addListener(listener); } /** * Removes the given listener. * * @param listener the listener to remove. * @since 2.0.0 * @throws NullPointerException if the given listener is {@code null}. */ public static void removeListener(HttpSenderListener listener) { impl.removeListener(listener); } /** * Set the user to scan as. If null then the current session will be used. * * @param user */ public void setUser(User user) { getContext().setUser(user); } /** * @return the HTTP client implementation. * @deprecated (2.8.0) Do not use, this exposes implementation details which might change * without warning. It will be removed in a following version. */ @Deprecated public HttpClient getClient() { return PAROS_IMPL.getClient(); } /** * Sets whether or not the authentication headers ("Authorization" and "Proxy-Authorization") * already present in the request should be removed if received an authentication challenge * (status codes 401 and 407). * *

If {@code true} new authentication headers will be generated and the old ones removed * otherwise the authentication headers already present in the request will be used to * authenticate. * *

Default is {@code false}, i.e. use the headers already present in the request header. * *

Processes that reuse messages previously sent should consider setting this to {@code * true}, otherwise new authentication challenges might fail. * * @param removeHeaders {@code true} if the authentication headers already present should be * removed when challenged, {@code false} otherwise */ public void setRemoveUserDefinedAuthHeaders(boolean removeHeaders) { getContext().setRemoveUserDefinedAuthHeaders(removeHeaders); } /** * Sets the maximum number of retries of an unsuccessful request caused by I/O errors. * *

The default number of retries is 3. * * @param retries the number of retries * @throws IllegalArgumentException if {@code retries} is negative. * @since 2.4.0 */ public void setMaxRetriesOnIOError(int retries) { getContext().setMaxRetriesOnIoError(retries); } /** * Sets the maximum number of redirects that will be followed before failing with an exception. * *

The default maximum number of redirects is 100. * * @param maxRedirects the maximum number of redirects * @throws IllegalArgumentException if {@code maxRedirects} is negative. * @since 2.4.0 */ public void setMaxRedirects(int maxRedirects) { getContext().setMaxRedirects(maxRedirects); } /** * Sets whether or not circular redirects are allowed. * *

Circular redirects happen when a request redirects to itself, or when a same request was * already accessed in a chain of redirects. * *

Since 2.5.0, the default is to allow circular redirects. * * @param allow {@code true} if circular redirects should be allowed, {@code false} otherwise * @since 2.4.0 * @deprecated (2.12.0) No longer supported, the circular redirects are allowed always. If * needed they can be prevented with a custom {@link HttpRedirectionValidator}. */ @Deprecated public void setAllowCircularRedirects(boolean allow) {} /** * Sends the request of given HTTP {@code message} with the given configurations. * * @param message the message that will be sent * @param requestConfig the request configurations. * @throws IllegalArgumentException if any of the parameters is {@code null} * @throws IOException if an error occurred while sending the message or following the * redirections * @since 2.6.0 * @see #sendAndReceive(HttpMessage, boolean) */ public void sendAndReceive(HttpMessage message, HttpRequestConfig requestConfig) throws IOException { sendImpl(requestConfig, message, null); } @SuppressWarnings("unchecked") private void sendImpl(HttpRequestConfig requestConfig, HttpMessage message, Path file) throws IOException { if (ctx == null) { impl.sendAndReceive(this, requestConfig, message, file); } else { impl.sendAndReceive(ctx, requestConfig, message, file); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy