proxy_connect.c revision 1fbf6ba0f5207e6637b49f9a9dfcc779bbe952a9
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* ====================================================================
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * The Apache Software License, Version 1.1
9a58dc6a2b26ec128b1270cf48810e705f1a90dbsf * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * reserved.
031b91a62d25106ae69d4693475c79618dd5e884fielding * Redistribution and use in source and binary forms, with or without
031b91a62d25106ae69d4693475c79618dd5e884fielding * modification, are permitted provided that the following conditions
031b91a62d25106ae69d4693475c79618dd5e884fielding * 1. Redistributions of source code must retain the above copyright
031b91a62d25106ae69d4693475c79618dd5e884fielding * notice, this list of conditions and the following disclaimer.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * 2. Redistributions in binary form must reproduce the above copyright
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * notice, this list of conditions and the following disclaimer in
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * the documentation and/or other materials provided with the
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * distribution.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * 3. The end-user documentation included with the redistribution,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * if any, must include the following acknowledgment:
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * "This product includes software developed by the
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Apache Software Foundation (http://www.apache.org/)."
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Alternately, this acknowledgment may appear in the software itself,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * if and wherever such third-party acknowledgments normally appear.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * 4. The names "Apache" and "Apache Software Foundation" must
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * not be used to endorse or promote products derived from this
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * software without prior written permission. For written
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * permission, please contact apache@apache.org.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * 5. Products derived from this software may not be called "Apache",
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * nor may "Apache" appear in their name, without prior written
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * permission of the Apache Software Foundation.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * SUCH DAMAGE.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * ====================================================================
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * This software consists of voluntary contributions made by many
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * individuals on behalf of the Apache Software Foundation. For more
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * information on the Apache Software Foundation, please see
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Portions of this software are based upon public domain software
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * originally written at the National Center for Supercomputing Applications,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * University of Illinois, Urbana-Champaign.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* CONNECT method for Apache proxy */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndint ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * This handles Netscape CONNECT method secure proxy requests.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * A connection is opened to the specified host and data is
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * passed through between the WWW site and the browser.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * This code is based on the INTERNET-DRAFT document
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * "Tunneling SSL Through a WWW Proxy" currently at
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * If proxyhost and proxyport are set, we send a CONNECT to
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * the specified proxy..
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * FIXME: this doesn't log the number of bytes sent, but
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * that may be okay, since the data is supposed to
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * be transparent. In fact, this doesn't log at all
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * yet. 8^)
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * FIXME: doesn't check any headers initally sent from the
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * FIXME: should allow authentication, but hopefully the
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * generic proxy authentication is good enough.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * FIXME: no check for r->assbackwards, whatever that is.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd for(i = 0; i < conf->allowed_connect_ports->nelts; i++) {
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* canonicalise CONNECT URLs. */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd/* CONNECT handler */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7ndint ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd apr_socket_t *client_socket = ap_get_module_config(r->connection->conn_config, &core_module);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd const char *connectname;
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* is this for us? */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Step One: Determine Who To Connect To
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Break up the URL to determine the host to connect to
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* we break the URL into host, port, uri */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd if (APR_SUCCESS != apr_uri_parse_hostinfo(p, url, &uri)) {
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd "proxy: CONNECT: connecting %s to %s:%d", url, uri.hostname, uri.port);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* do a DNS lookup for the destination host */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port, 0, p);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* are we connecting directly, or via a proxy? */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd err = apr_sockaddr_info_get(&connect_addr, proxyname, APR_UNSPEC, proxyport, 0, p);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd "proxy: CONNECT: connecting to remote proxy %s on port %d", connectname, connectport);
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* check if ProxyBlock directive on this host */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd "Connect to remote machine blocked");
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* Check if it is an allowed port */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* Default setting if not overridden by AllowCONNECT */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* XXX can we call ap_proxyerror() here to get a nice log message? */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* XXX can we call ap_proxyerror() here to get a nice log message? */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Step Two: Make the Connection
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * We have determined who to connect to. Now make the connection.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* get all the possible IP addresses for the destname and loop through them
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * until we get a successful connection
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd "DNS lookup failure for: ",
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * At this point we have a list of one or more IP addresses of
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * the machine to connect to. If configured, reorder this
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * list so that the "best candidate" is first try. "best
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * candidate" could mean the least loaded server, the fastest
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * responding server, whatever.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * For now we do nothing, ie we get DNS round robin.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * XXX FIXME
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd failed = ap_proxy_connect_to_backend(&sock, "CONNECT", connect_addr,
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* handle a permanent error from the above loop */
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Step Three: Send the Request
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * Send the HTTP/1.1 CONNECT request to the remote server
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* we are acting as a tunnel - the output filter stack should
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * be completely empty, because when we are done here we are done completely.
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * We add the NULL filter to the stack to do this...
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd /* If we are connecting through a remote proxy, we need to pass
41e3d6b4e67a52c6570c0412c3e5526278cf07d7nd * the CONNECT request on to it.
ap_rflush(r);
return HTTP_INTERNAL_SERVER_ERROR;
return HTTP_INTERNAL_SERVER_ERROR;
if (pollcnt) {
i = nbytes;
nbytes = i;
o += nbytes;
i -= nbytes;
i = nbytes;
nbytes = i;
o += nbytes;
i -= nbytes;
return OK;