proxy_connect.c revision a2f9f38db0931e6edf7b71378dd680c3c5fa5841
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* ====================================================================
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * The Apache Software License, Version 1.1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Copyright (c) 2000 The Apache Software Foundation. All rights
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * reserved.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Redistribution and use in source and binary forms, with or without
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * modification, are permitted provided that the following conditions
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * are met:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 1. Redistributions of source code must retain the above copyright
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * notice, this list of conditions and the following disclaimer.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 2. Redistributions in binary form must reproduce the above copyright
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * notice, this list of conditions and the following disclaimer in
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * the documentation and/or other materials provided with the
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * distribution.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 3. The end-user documentation included with the redistribution,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * if any, must include the following acknowledgment:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * "This product includes software developed by the
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Apache Software Foundation (http://www.apache.org/)."
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Alternately, this acknowledgment may appear in the software itself,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * if and wherever such third-party acknowledgments normally appear.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 4. The names "Apache" and "Apache Software Foundation" must
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * not be used to endorse or promote products derived from this
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * software without prior written permission. For written
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * permission, please contact apache@apache.org.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 5. Products derived from this software may not be called "Apache",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * nor may "Apache" appear in their name, without prior written
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * permission of the Apache Software Foundation.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * SUCH DAMAGE.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ====================================================================
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This software consists of voluntary contributions made by many
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * individuals on behalf of the Apache Software Foundation. For more
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * information on the Apache Software Foundation, please see
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Portions of this software are based upon public domain software
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * originally written at the National Center for Supercomputing Applications,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * University of Illinois, Urbana-Champaign.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* CONNECT method for Apache proxy */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb#include <bstring.h> /* for IRIX, FD_SET calls bzero() */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This handles Netscape CONNECT method secure proxy requests.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * A connection is opened to the specified host and data is
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * passed through between the WWW site and the browser.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This code is based on the INTERNET-DRAFT document
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * "Tunneling SSL Through a WWW Proxy" currently at
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * If proxyhost and proxyport are set, we send a CONNECT to
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * the specified proxy..
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * FIXME: this is bad, because it does its own socket I/O
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * instead of using the I/O in buff.c. However,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * the I/O in buff.c blocks on reads, and because
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * this function doesn't know how much data will
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * be sent either way (or when) it can't use blocking
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * I/O. This may be very implementation-specific
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * (to Linux). Any suggestions?
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * FIXME: this doesn't log the number of bytes sent, but
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * that may be okay, since the data is supposed to
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * be transparent. In fact, this doesn't log at all
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * yet. 8^)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * FIXME: doesn't check any headers initally sent from the
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * FIXME: should allow authentication, but hopefully the
a2a0abd88b19e042a3eb2a9fa1702c25ad51303dwrowe * generic proxy authentication is good enough.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * FIXME: no check for r->assbackwards, whatever that is.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb for(i = 0; i < conf->allowed_connect_ports->nelts; i++) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbint ap_proxy_connect_handler(request_rec *r, ap_cache_el *c, char *url,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb const char *host;
731344ed8f3677d1661c261ca5fcdd2ee3dbc74ccoar (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe /* Break the URL into host:port pairs */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe/* check if ProxyBlock directive on this host */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe if ((npent[i].name != NULL && ap_strstr_c(host, npent[i].name) != NULL)
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe || destaddr.s_addr == npent[i].addr.s_addr || npent[i].name[0] == '*')
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe "Connect to remote machine blocked");
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe /* Check if it is an allowed port */
3e392a5afd51526de3cb15d57ee46d8cb160ae65gregames /* Default setting if not overridden by AllowCONNECT */
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe "CONNECT to remote proxy %s on port %d", proxyhost, proxyport);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
4775dfc34c90fada8c7c4d6a57ed8a3114d55c2dtrawick if ((apr_create_tcp_socket(&sock, r->pool)) != APR_SUCCESS) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe "proxy: error creating socket");
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe if (ap_proxy_doconnect(sock, (char *)(proxyhost ? proxyhost : host), proxyport ? proxyport : port, r) == -1) {
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe apr_pstrcat(r->pool, "Could not connect to remote machine:<br>",
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe /* If we are connecting through a remote proxy, we need to pass
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * the CONNECT request on to it.
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe /* FIXME: We should not be calling write() directly, but we currently
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * have no alternative. Error checking ignored. Also, we force
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe * a HTTP/1.0 request to keep things simple.
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe "Sending the CONNECT request to the remote proxy");
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe nbytes = apr_snprintf(buffer, sizeof(buffer), "CONNECT %s HTTP/1.0" CRLF, r->uri);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe nbytes = apr_snprintf(buffer, sizeof(buffer),"Proxy-agent: %s" CRLF CRLF, ap_get_server_version());
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe "Returning 200 OK Status");
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe ap_rvputs(r, "HTTP/1.0 200 Connection established" CRLF, NULL);
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe ap_rvputs(r, "Proxy-agent: ", ap_get_server_version(), CRLF CRLF, NULL);
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe if(apr_setup_poll(&pollfd, 2, r->pool) != APR_SUCCESS)
c2cf53a40a9814eb91db2cdf820f97d943f21628coar ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error apr_setup_poll()");
c2cf53a40a9814eb91db2cdf820f97d943f21628coar /* Add client side to the poll */
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe/* FIXME !!!! SDM !!! If someone can figure out how to turn a conn_rec into a ap_sock_t or something
c2cf53a40a9814eb91db2cdf820f97d943f21628coar this code might work. However if we must we can change r->connection->client to non-blocking and
c2cf53a40a9814eb91db2cdf820f97d943f21628coar just see if a recv gives us anything and do the same to sock (server) side, I'll leave this as TBD so
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe one can decide the best path to take
c2cf53a40a9814eb91db2cdf820f97d943f21628coar if(apr_put_os_sock(&client_sock, (apr_os_sock_t *)get_socket(r->connection->client),
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error creating client apr_socket_t");
c2cf53a40a9814eb91db2cdf820f97d943f21628coar /* Add the server side to the poll */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar while (1) { /* Infinite loop until error (one side closes the connection) */
c2cf53a40a9814eb91db2cdf820f97d943f21628coar ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL, "Going to sleep (poll)");
c2cf53a40a9814eb91db2cdf820f97d943f21628coar ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "proxy: error apr_poll()");
c2cf53a40a9814eb91db2cdf820f97d943f21628coar ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe "sock was set");
fa06de8a28a737e8fbaad76d7f3ff67aaa5e4a09wrowe if(ap_bread(sock_buff, buffer, HUGE_STRING_LEN, &nbytes) == APR_SUCCESS) {
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ap_bwrite(r->connection->client, buffer + o, nbytes, &i);
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, NULL,
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe "client was set");
83a8dc5a596a8a1b9d14f063268287d123b9ed7ewrowe if(ap_bread(r->connection->client, buffer, HUGE_STRING_LEN, &nbytes) == APR_SUCCESS) {