Commit 2152d9ce authored by Graham Leggett's avatar Graham Leggett
Browse files

Split each individual proxy protocol into separate modules.

PR:
Obtained from:
Reviewed by:


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@88866 13f79535-47bb-0310-9956-ffa450edef68
parent 006582fa
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -2,8 +2,22 @@ dnl modules enabled in this directory by default

APACHE_MODPATH_INIT(proxy)

proxy_objs="mod_proxy.lo proxy_connect.lo proxy_ftp.lo proxy_http.lo proxy_util.lo"
if test "$enable_proxy" = "no"; then
  proxy_mods_enable=no
else
  proxy_mods_enable=yes
fi
APACHE_MODULE(dav_fs, DAV provider for the filesystem, $dav_fs_objects, ,$dav_fs_enable)

proxy_objs="mod_proxy.lo proxy_util.lo"
APACHE_MODULE(proxy, Apache proxy module, $proxy_objs, , no)

proxy_connect_objs="proxy_connect.lo proxy_util.lo"
APACHE_MODULE(proxy_connect, Apache proxy CONNECT module, $proxy_connect_objs, , $proxy_mods_enable)
proxy_ftp_objs="proxy_ftp.lo proxy_util.lo"
APACHE_MODULE(proxy_ftp, Apache proxy FTP module, $proxy_ftp_objs, , $proxy_mods_enable)
proxy_http_objs="proxy_http.lo proxy_util.lo"
APACHE_MODULE(proxy_http, Apache proxy HTTP module, $proxy_http_objs, , $proxy_mods_enable)


APACHE_MODPATH_FINISH
+39 −40
Original line number Diff line number Diff line
@@ -60,13 +60,7 @@

#include "mod_proxy.h"

APR_HOOK_STRUCT(
	APR_HOOK_LINK(proxy_scheme_handler)
	APR_HOOK_LINK(proxy_canon_handler)
)

AP_IMPLEMENT_HOOK_RUN_FIRST(int, proxy_scheme_handler, (request_rec *r, char *url, const char *proxyhost, apr_port_t proxyport),(r,url,proxyhost,proxyport),DECLINED)
AP_IMPLEMENT_HOOK_RUN_FIRST(int, proxy_canon_handler, (request_rec *r, char *url),(r,url),DECLINED)
extern module AP_MODULE_DECLARE_DATA proxy_module;


/*
@@ -213,7 +207,7 @@ static int proxy_fixup(request_rec *r)
    url = &r->filename[6];

    /* canonicalise each specific scheme */
    if ((access_status = ap_run_proxy_canon_handler(r, url))) {
    if ((access_status = proxy_run_canon_handler(r, url))) {
	return access_status;
    }

@@ -276,7 +270,7 @@ static int proxy_handler(request_rec *r)
        ap_get_module_config(sconf, &proxy_module);
    apr_array_header_t *proxies = conf->proxies;
    struct proxy_remote *ents = (struct proxy_remote *) proxies->elts;
    int i, rc;
    int i, rc, access_status;
    int direct_connect = 0;
    const char *str;
    long maxfwd;
@@ -361,51 +355,44 @@ static int proxy_handler(request_rec *r)
    }

    /* firstly, try a proxy, unless a NoProxy directive is active */

    if (!direct_connect)
    if (!direct_connect) {
	for (i = 0; i < proxies->nelts; i++) {
            p2 = ap_strchr_c(ents[i].scheme, ':');  /* is it a partial URL? */
	    if (strcmp(ents[i].scheme, "*") == 0 ||
		(p2 == NULL && strcasecmp(scheme, ents[i].scheme) == 0) ||
		(p2 != NULL &&
	        strncasecmp(url, ents[i].scheme, strlen(ents[i].scheme)) == 0)) {
		/* CONNECT is a special method that bypasses the normal
		 * proxy code.
		 */
		if (r->method_number == M_CONNECT)
		    rc = ap_proxy_connect_handler(r, url, ents[i].hostname,
					       ents[i].port);
/* we only know how to handle communication to a proxy via http */
		else if (strcasecmp(ents[i].protocol, "http") == 0)
		    rc = ap_proxy_http_handler(r, url, ents[i].hostname,
					    ents[i].port);
		else
		    rc = DECLINED;

		/* handle the scheme */
		ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
			     "Trying to run scheme_handler against proxy");
		access_status = proxy_run_scheme_handler(r, conf, url, NULL, 0);

		/* an error or success */
		if (rc != DECLINED && rc != HTTP_BAD_GATEWAY)
		    return rc;
		if (access_status != DECLINED && access_status != HTTP_BAD_GATEWAY) {
		    return access_status;
		}
		/* we failed to talk to the upstream proxy */
	    }
	}
    }

    /* otherwise, try it direct */
    /* N.B. what if we're behind a firewall, where we must use a proxy or
     * give up??
     */

    /* handle the scheme */
    if (r->method_number == M_CONNECT)
	return ap_proxy_connect_handler(r, url, NULL, 0);
    if (strcasecmp(scheme, "http") == 0)
	return ap_proxy_http_handler(r, url, NULL, 0);
    if (strcasecmp(scheme, "ftp") == 0)
	return ap_proxy_ftp_handler(r, url, NULL, 0);
    else {
    ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
		 "Trying to run scheme_handler");
    access_status = proxy_run_scheme_handler(r, conf, url, NULL, 0);
    if (DECLINED == access_status) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server,
		     "Neither CONNECT, HTTP or FTP for %s",
		     r->uri);
	return HTTP_FORBIDDEN;
    }
    return access_status;
}

/* -------------------------------------------------------------- */
@@ -749,8 +736,6 @@ static void register_hooks(apr_pool_t *p)
    ap_hook_handler(proxy_handler, NULL, NULL, APR_HOOK_FIRST);
    /* filename-to-URI translation */
    ap_hook_translate_name(proxy_trans, NULL, NULL, APR_HOOK_FIRST);
    /* filters */
    ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, AP_FTYPE_CONTENT);
    /* fixups */
    ap_hook_fixups(proxy_fixup, NULL, NULL, APR_HOOK_FIRST);
    /* post read_request handling */
@@ -767,3 +752,17 @@ module AP_MODULE_DECLARE_DATA proxy_module =
    proxy_cmds,			/* command table */
    register_hooks
};

APR_HOOK_STRUCT(
	APR_HOOK_LINK(scheme_handler)
	APR_HOOK_LINK(canon_handler)
)

APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, scheme_handler, 
                                     (request_rec *r, proxy_server_conf *conf, 
                                     char *url, const char *proxyhost, 
                                     apr_port_t proxyport),(r,conf,url,
                                     proxyhost,proxyport),DECLINED)
APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(proxy, PROXY, int, canon_handler, 
                                     (request_rec *r, char *url),(r,
                                     url),DECLINED)
+27 −29
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@

#define CORE_PRIVATE

#include "apr_hooks.h"
#include "apr.h"
#include "apr_compat.h"
#include "apr_lib.h"
@@ -89,7 +90,6 @@
#include "apr_md5.h"
#include "apr_pools.h"
#include "apr_strings.h"
#include "apr_hooks.h"

#include "httpd.h"
#include "http_config.h"
@@ -120,8 +120,6 @@
#include <arpa/inet.h>
#endif

extern module AP_MODULE_DECLARE_DATA proxy_module;

/* for proxy_canonenc() */
enum enctype {
    enc_path, enc_search, enc_user, enc_fpath, enc_parm
@@ -202,27 +200,34 @@ typedef struct {
} proxy_completion;


/* Function prototypes */

/* proxy_connect.c */

int ap_proxy_connect_canon(request_rec *r, char *url);
int ap_proxy_connect_handler(request_rec *r, char *url,
			  const char *proxyhost, apr_port_t proxyport);

/* proxy_ftp.c */

int ap_proxy_ftp_canon(request_rec *r, char *url);
int ap_proxy_ftp_handler(request_rec *r, char *url, const char *proxyhost, apr_port_t proxyport);
apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f,
				      apr_bucket_brigade *bb);

/* hooks */

/* proxy_http.c */
/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and 
 * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
 */
#if !defined(WIN32)
#define PROXY_DECLARE(type)            type
#define PROXY_DECLARE_NONSTD(type)     type
#define PROXY_DECLARE_DATA
#elif defined(PROXY_DECLARE_STATIC)
#define PROXY_DECLARE(type)            type __stdcall
#define PROXY_DECLARE_NONSTD(type)     type
#define PROXY_DECLARE_DATA
#elif defined(PROXY_DECLARE_EXPORT)
#define PROXY_DECLARE(type)            __declspec(dllexport) type __stdcall
#define PROXY_DECLARE_NONSTD(type)     __declspec(dllexport) type
#define PROXY_DECLARE_DATA             __declspec(dllexport)
#else
#define PROXY_DECLARE(type)            __declspec(dllimport) type __stdcall
#define PROXY_DECLARE_NONSTD(type)     __declspec(dllimport) type
#define PROXY_DECLARE_DATA             __declspec(dllimport)
#endif

int ap_proxy_http_canon(request_rec *r, char *url);
int ap_proxy_http_handler(request_rec *r, char *url,
		       const char *proxyhost, apr_port_t proxyport);
APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, scheme_handler, (request_rec *r, 
                          proxy_server_conf *conf, char *url, 
                          const char *proxyhost, apr_port_t proxyport))
APR_DECLARE_EXTERNAL_HOOK(proxy, PROXY, int, canon_handler, (request_rec *r, 
                          char *url))

/* proxy_util.c */

@@ -251,11 +256,4 @@ apr_status_t ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buf
void ap_proxy_reset_output_filters(conn_rec *c);


/* hooks */


AP_DECLARE_HOOK(int, proxy_scheme_handler, (request_rec *r, char *url, const char *proxyhost, apr_port_t proxyport))
AP_DECLARE_HOOK(int, proxy_canon_handler, (request_rec *r, char *url))


#endif /*MOD_PROXY_H*/
+18 −9
Original line number Diff line number Diff line
@@ -64,6 +64,11 @@

module AP_MODULE_DECLARE_DATA proxy_connect_module;

PROXY_DECLARE (int) ap_proxy_connect_canon(request_rec *r, char *url);
PROXY_DECLARE (int) ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf, 
                             char *url, const char *proxyname, 
                             apr_port_t proxyport);

/*  
 * This handles Netscape CONNECT method secure proxy requests.
 * A connection is opened to the specified host and data is
@@ -101,19 +106,22 @@ allowed_port(proxy_server_conf *conf, int port)
}

/* canonicalise CONNECT URLs. */
int ap_proxy_connect_canon(request_rec *r, char *url)
PROXY_DECLARE (int) ap_proxy_connect_canon(request_rec *r, char *url)
{

    if (r->method_number != M_CONNECT) {
	return DECLINED;
    }
    ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
		 "proxy: CONNECT: canonicalising URL %s", url);

    return OK;
}

/* CONNECT handler */
int ap_proxy_connect_handler(request_rec *r, char *url,
			  const char *proxyname, apr_port_t proxyport)
PROXY_DECLARE (int) ap_proxy_connect_handler(request_rec *r, proxy_server_conf *conf, 
                             char *url, const char *proxyname, 
                             apr_port_t proxyport)
{
    apr_pool_t *p = r->pool;
    apr_socket_t *sock;
@@ -130,14 +138,15 @@ int ap_proxy_connect_handler(request_rec *r, char *url,
    const char *connectname;
    int connectport = 0;

    void *sconf = r->server->module_config;
    proxy_server_conf *conf =
    (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);

    /* is this for us? */
    if (r->method_number != M_CONNECT) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
		     "proxy: CONNECT: rejecting URL %s", url);
	return DECLINED;
    }
    ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
		 "proxy: CONNECT: serving URL %s", url);


    /*
     * Step One: Determine Who To Connect To
@@ -403,8 +412,8 @@ int ap_proxy_connect_handler(request_rec *r, char *url,

static void ap_proxy_connect_register_hook(apr_pool_t *p)
{
    ap_hook_proxy_scheme_handler(ap_proxy_connect_handler, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_proxy_canon_handler(ap_proxy_connect_canon, NULL, NULL, APR_HOOK_MIDDLE);
    proxy_hook_scheme_handler(ap_proxy_connect_handler, NULL, NULL, APR_HOOK_MIDDLE);
    proxy_hook_canon_handler(ap_proxy_connect_canon, NULL, NULL, APR_HOOK_MIDDLE);
}

module AP_MODULE_DECLARE_DATA proxy_connect_module = {
+37 −10
Original line number Diff line number Diff line
@@ -64,6 +64,14 @@

module AP_MODULE_DECLARE_DATA proxy_ftp_module;

PROXY_DECLARE (int) ap_proxy_ftp_canon(request_rec *r, char *url);
PROXY_DECLARE (int) ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, 
                         char *url, const char *proxyhost, 
                         apr_port_t proxyport);
apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f,
				      apr_bucket_brigade *bb);


/*
 * Decodes a '%' escaped string, and returns the number of characters
 */
@@ -113,7 +121,7 @@ static int ftp_check_string(const char *x)
/*
 * Canonicalise ftp URLs.
 */
int ap_proxy_ftp_canon(request_rec *r, char *url)
PROXY_DECLARE (int) ap_proxy_ftp_canon(request_rec *r, char *url)
{
    char *user, *password, *host, *path, *parms, *strp, sport[7];
    apr_pool_t *p = r->pool;
@@ -129,6 +137,9 @@ int ap_proxy_ftp_canon(request_rec *r, char *url)
    }
    def_port = ap_default_port_for_scheme("ftp");

    ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
		 "proxy: FTP: canonicalising URL %s", url);

    port = def_port;
    err = ap_proxy_canon_netloc(p, &url, &user, &password, &host, &port);
    if (err)
@@ -514,10 +525,13 @@ static int ftp_unauthorized (request_rec *r, int log_it)
 * PASV added by Chuck
 * Filters by [Graham Leggett <minfrin@sharp.fm>]
 */
int ap_proxy_ftp_handler(request_rec *r, char *url, const char *proxyhost, apr_port_t proxyport)
PROXY_DECLARE (int) ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, 
                         char *url, const char *proxyhost, 
                         apr_port_t proxyport)
{
    apr_pool_t *p = r->pool;
    conn_rec *c = r->connection;
    proxy_conn_rec *backend;
    apr_socket_t *sock, *local_sock, *remote_sock;
    apr_sockaddr_t *connect_addr;
    apr_status_t rv;
@@ -541,18 +555,28 @@ int ap_proxy_ftp_handler(request_rec *r, char *url, const char *proxyhost, apr_p
    int connect = 0, use_port = 0;
    char dates[AP_RFC822_DATE_LEN];

    void *sconf = r->server->module_config;
    proxy_server_conf *conf =
    (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
    /* is this for us? */
    if (proxyhost) {
	ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
		     "proxy: FTP: rejecting URL %s - proxyhost %s specified:", url, proxyhost);
	return DECLINED; /* proxy connections are via HTTP */
    }
    if (strncasecmp(url, "ftp:", 4)) {
	ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
		     "proxy: FTP: rejecting URL %s - not ftp:", url);
	return DECLINED; /* only interested in FTP */
    }
    ap_log_error(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r->server,
		 "proxy: FTP: serving URL %s", url);

    proxy_conn_rec *backend =
    (proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_module);
    /* create space for state information */
    backend = (proxy_conn_rec *) ap_get_module_config(c->conn_config, &proxy_ftp_module);
    if (!backend) {
	backend = ap_pcalloc(c->pool, sizeof(proxy_conn_rec));
	backend->connection = NULL;
	backend->hostname = NULL;
	backend->port = 0;
	ap_set_module_config(c->conn_config, &proxy_module, backend);
	ap_set_module_config(c->conn_config, &proxy_ftp_module, backend);
    }


@@ -1620,8 +1644,11 @@ int ap_proxy_ftp_handler(request_rec *r, char *url, const char *proxyhost, apr_p

static void ap_proxy_ftp_register_hook(apr_pool_t *p)
{
    ap_hook_proxy_scheme_handler(ap_proxy_ftp_handler, NULL, NULL, APR_HOOK_MIDDLE);
    ap_hook_proxy_canon_handler(ap_proxy_ftp_canon, NULL, NULL, APR_HOOK_MIDDLE);
    /* hooks */
    proxy_hook_scheme_handler(ap_proxy_ftp_handler, NULL, NULL, APR_HOOK_MIDDLE);
    proxy_hook_canon_handler(ap_proxy_ftp_canon, NULL, NULL, APR_HOOK_MIDDLE);
    /* filters */
    ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, AP_FTYPE_CONTENT);
}

module AP_MODULE_DECLARE_DATA proxy_ftp_module = {
Loading