--- httpd-2.0.59/docs/manual/mod/directives.html.en.proxyallow 2006-07-12 00:22:22.000000000 -0700 +++ httpd-2.0.59/docs/manual/mod/directives.html.en 2006-08-30 13:47:22.000000000 -0700 @@ -272,6 +272,7 @@
  • PidFile
  • ProtocolEcho
  • <Proxy>
  • +
  • ProxyAllow
  • ProxyBadHeader
  • ProxyBlock
  • ProxyDomain
  • --- httpd-2.0.59/docs/manual/mod/mod_proxy.html.en.proxyallow 2006-07-12 00:22:22.000000000 -0700 +++ httpd-2.0.59/docs/manual/mod/mod_proxy.html.en 2006-08-30 13:47:22.000000000 -0700 @@ -62,6 +62,7 @@
  • AllowCONNECT
  • NoProxy
  • <Proxy>
  • +
  • ProxyAllow
  • ProxyBadHeader
  • ProxyBlock
  • ProxyDomain
  • @@ -299,7 +300,8 @@
    top

    Slow Startup

    -

    If you're using the ProxyBlock directive, hostnames' IP addresses are looked up +

    If you're using the ProxyAllow or + ProxyBlock directive, hostnames' IP addresses are looked up and cached during startup for later match test. This may take a few seconds (or more) depending on the speed with which the hostname lookups occur.

    @@ -537,6 +539,48 @@
    top
    +

    ProxyAllow Directive

    + + + + + + +
    Description:Words, hosts, or domains that are banned from being +proxied
    Syntax:ProxyAllow *|word|host|domain +[word|host|domain] ...
    Context:server config, virtual host
    Status:Extension
    Module:mod_proxy
    +

    The ProxyAllow directive specifies a list of + words, hosts and/or domains, separated by spaces. HTTP, HTTPS, and + FTP document requests to sites whose names contain matched words, + hosts or domains are allowed by the proxy server. The proxy + module will also attempt to determine IP addresses of list items which + may be hostnames during startup, and cache them for match test as + well. That may slow down the startup time of the server.

    + +

    Example

    + ProxyAllow joes-garage.com some-host.co.uk rocky.wotsamattau.edu +

    + +

    rocky.wotsamattau.edu would also be matched if referenced by + IP address.

    + +

    Note that wotsamattau would also be sufficient to match + wotsamattau.edu.

    + +

    Note also that

    + +

    + ProxyAllow * +

    + +

    allows connections to all sites.

    + +

    If the ProxyAllow is not present, + the default is to allow all sites (except those blocked by + ProxyBlock).

    + +
    +
    top

    ProxyBadHeader Directive

    +
    Description:Determines how to handle bad header lines in a --- httpd-2.0.59/docs/manual/mod/quickreference.html.en.proxyallow 2006-07-12 00:22:22.000000000 -0700 +++ httpd-2.0.59/docs/manual/mod/quickreference.html.en 2006-08-30 13:47:22.000000000 -0700 @@ -476,6 +476,9 @@ of the daemon
    ProtocolEcho On|OffsvX
    Turn the echo server on or off
    <Proxy wildcard-url> ...</Proxy>svE
    Container for directives applied to proxied resources
    ProxyAllow *|word|host|domain +[word|host|domain] ...svE
    Words, hosts, or domains that are exclusively allowed to be +proxied
    ProxyBadHeader IsError|Ignore|StartBody IsError svE
    Determines how to handle bad header lines in a response
    ProxyBlock *|word|host|domain --- httpd-2.0.59/modules/proxy/mod_proxy.c.proxyallow 2006-07-12 00:40:55.000000000 -0700 +++ httpd-2.0.59/modules/proxy/mod_proxy.c 2006-08-30 14:06:47.000000000 -0700 @@ -477,6 +477,7 @@ ps->aliases = apr_array_make(p, 10, sizeof(struct proxy_alias)); ps->raliases = apr_array_make(p, 10, sizeof(struct proxy_alias)); ps->noproxies = apr_array_make(p, 10, sizeof(struct noproxy_entry)); + ps->onlyproxies = apr_array_make(p, 10, sizeof(struct noproxy_entry)); ps->dirconn = apr_array_make(p, 10, sizeof(struct dirconn_entry)); ps->allowed_connect_ports = apr_array_make(p, 10, sizeof(int)); ps->domain = NULL; @@ -512,6 +513,7 @@ ps->aliases = apr_array_append(p, base->aliases, overrides->aliases); ps->raliases = apr_array_append(p, base->raliases, overrides->raliases); ps->noproxies = apr_array_append(p, base->noproxies, overrides->noproxies); + ps->onlyproxies = apr_array_append(p, base->onlyproxies, overrides->onlyproxies); ps->dirconn = apr_array_append(p, base->dirconn, overrides->dirconn); ps->allowed_connect_ports = apr_array_append(p, base->allowed_connect_ports, overrides->allowed_connect_ports); @@ -709,6 +711,38 @@ return NULL; } +static const char * + set_proxy_include(cmd_parms *parms, void *dummy, const char *arg) +{ + server_rec *s = parms->server; + proxy_server_conf *conf = + ap_get_module_config(s->module_config, &proxy_module); + struct noproxy_entry *new; + struct noproxy_entry *list = (struct noproxy_entry *) conf->onlyproxies->elts; + struct apr_sockaddr_t *addr; + int found = 0; + int i; + + /* Don't duplicate entries */ + for (i = 0; i < conf->onlyproxies->nelts; i++) { + if (apr_strnatcasecmp(arg, list[i].name) == 0) { /* ignore case for host names */ + found = 1; + } + } + + if (!found) { + new = apr_array_push(conf->onlyproxies); + new->name = arg; + if (APR_SUCCESS == apr_sockaddr_info_get(&addr, new->name, APR_UNSPEC, 0, 0, parms->pool)) { + new->addr = addr; + } + else { + new->addr = NULL; + } + } + return NULL; +} + /* * Set the ports CONNECT can use */ @@ -1042,6 +1076,8 @@ "a virtual path and a URL"), AP_INIT_TAKE12("ProxyPassReverse", add_pass_reverse, NULL, RSRC_CONF|ACCESS_CONF, "a virtual path and a URL for reverse proxy behaviour"), + AP_INIT_ITERATE("ProxyAllow", set_proxy_include, NULL, RSRC_CONF, + "A list of names, hosts or domains to which the proxy may connect"), AP_INIT_ITERATE("ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, "A list of names, hosts or domains to which the proxy will not connect"), AP_INIT_TAKE1("ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, --- httpd-2.0.59/modules/proxy/mod_proxy.h.proxyallow 2006-07-12 00:40:55.000000000 -0700 +++ httpd-2.0.59/modules/proxy/mod_proxy.h 2006-08-30 13:47:22.000000000 -0700 @@ -121,6 +121,7 @@ apr_array_header_t *aliases; apr_array_header_t *raliases; apr_array_header_t *noproxies; + apr_array_header_t *onlyproxies; apr_array_header_t *dirconn; apr_array_header_t *allowed_connect_ports; const char *domain; /* domain name to use in absence of a domain name in the request */ @@ -240,6 +241,7 @@ PROXY_DECLARE(int) ap_proxy_is_domainname(struct dirconn_entry *This, apr_pool_t *p); PROXY_DECLARE(int) ap_proxy_is_hostname(struct dirconn_entry *This, apr_pool_t *p); PROXY_DECLARE(int) ap_proxy_is_word(struct dirconn_entry *This, apr_pool_t *p); +PROXY_DECLARE(int) ap_proxy_checkproxyallow(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr); PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr); PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r); PROXY_DECLARE(apr_status_t) ap_proxy_string_read(conn_rec *c, apr_bucket_brigade *bb, char *buff, size_t bufflen, int *eos); --- httpd-2.0.59/modules/proxy/proxy_connect.c.proxyallow 2006-07-12 00:40:55.000000000 -0700 +++ httpd-2.0.59/modules/proxy/proxy_connect.c 2006-08-30 13:47:22.000000000 -0700 @@ -146,6 +146,12 @@ "Connect to remote machine blocked"); } + /* check if ProxyAllow directive on this host */ + if (OK != ap_proxy_checkproxyallow(r, conf, uri_addr)) { + return ap_proxyerror(r, HTTP_FORBIDDEN, + "Connect to remote machine blocked"); + } + /* Check if it is an allowed port */ if (conf->allowed_connect_ports->nelts == 0) { /* Default setting if not overridden by AllowCONNECT */ --- httpd-2.0.59/modules/proxy/proxy_ftp.c.proxyallow 2006-07-12 00:40:55.000000000 -0700 +++ httpd-2.0.59/modules/proxy/proxy_ftp.c 2006-08-30 13:47:22.000000000 -0700 @@ -899,6 +899,12 @@ "Connect to remote machine blocked"); } + /* check if ProxyAllow directive on this host */ + if (OK != ap_proxy_checkproxyallow(r, conf, connect_addr)) { + return ap_proxyerror(r, HTTP_FORBIDDEN, + "Connect to remote machine blocked"); + } + /* * II: Make the Connection ----------------------- --- httpd-2.0.59/modules/proxy/proxy_http.c.proxyallow 2006-08-30 13:47:22.000000000 -0700 +++ httpd-2.0.59/modules/proxy/proxy_http.c 2006-08-30 13:47:22.000000000 -0700 @@ -234,6 +234,11 @@ return ap_proxyerror(r, HTTP_FORBIDDEN, "Connect to remote machine blocked"); } + /* check if ProxyAllow directive on this host */ + if (OK != ap_proxy_checkproxyallow(r, conf, uri_addr)) { + return ap_proxyerror(r, HTTP_FORBIDDEN, + "Connect to remote machine blocked"); + } return OK; } --- httpd-2.0.59/modules/proxy/proxy_util.c.proxyallow 2006-07-12 00:40:55.000000000 -0700 +++ httpd-2.0.59/modules/proxy/proxy_util.c 2006-08-30 14:08:58.000000000 -0700 @@ -946,6 +946,47 @@ return host != NULL && ap_strstr_c(host, This->name) != NULL; } +/* checks whether a host in uri_addr matches proxyallow */ +PROXY_DECLARE(int) ap_proxy_checkproxyallow(request_rec *r, proxy_server_conf *conf, + apr_sockaddr_t *uri_addr) +{ + int j; + apr_sockaddr_t * src_uri_addr = uri_addr; + /* XXX FIXME: conf->onlyproxies->elts is part of an opaque structure */ + for (j = 0; j < conf->onlyproxies->nelts; j++) { + struct noproxy_entry *opent = (struct noproxy_entry *) conf->onlyproxies->elts; + struct apr_sockaddr_t *conf_addr = opent[j].addr; + uri_addr = src_uri_addr; + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: checking remote machine [%s] against [%s]", uri_addr->hostname, opent[j].name); + if ((opent[j].name && ap_strstr_c(uri_addr->hostname, opent[j].name)) + || opent[j].name[0] == '*') { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, + "proxy: connect to remote machine %s allowed: name %s matched", uri_addr->hostname, opent[j].name); + return OK; + } + while (conf_addr) { + while (uri_addr) { + char *conf_ip; + char *uri_ip; + apr_sockaddr_ip_get(&conf_ip, conf_addr); + apr_sockaddr_ip_get(&uri_ip, uri_addr); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: ProxyAllow comparing %s and %s", conf_ip, uri_ip); + if (!apr_strnatcasecmp(conf_ip, uri_ip)) { + ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, + "proxy: connect to remote machine %s allowed: IP %s matched", uri_addr->hostname, conf_ip); + return OK; + } + uri_addr = uri_addr->next; + } + conf_addr = conf_addr->next; + } + } + /* Default to OK if no hosts were listed in ProxyAllow */ + return conf->onlyproxies->nelts ? HTTP_FORBIDDEN : OK; +} + /* checks whether a host in uri_addr matches proxyblock */ PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr)