Received: (qmail 47010 invoked by uid 501); 18 Mar 2002 20:01:06 -0000 Message-Id: <20020318200106.47009.qmail@apache.org> Date: 18 Mar 2002 20:01:06 -0000 From: David Coffin Reply-To: david.coffin@srs.gov To: submit@bugz.apache.org Subject: Add ProxyConnAllow directive X-Send-Pr-Version: 3.110 >Number: 10246 >Category: mod_proxy >Synopsis: Add ProxyConnAllow directive >Confidential: no >Severity: non-critical >Priority: medium >Responsible: apache >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: apache >Arrival-Date: Mon Mar 18 12:10:00 PST 2002 >Closed-Date: >Last-Modified: >Originator: david.coffin@srs.gov >Release: 1.3.22 >Organization: apache >Environment: SunOS xxxx 5.7 Generic_106541-12 sun4u sparc SUNW,Ultra-Enterprise gcc others also >Description: We want to maintain a list of allowable CONNECT sites via ProxyConnAllow directives - providing opposite functionality from that provided by ProxyBlock, only for the CONNECT (SSL, etc) protocol. If not set (default) or set to *, all CONNECT sessions are allowed. We are filtering and other html tags after the proxy via other firewall software to keep from html/browser-based viruses, etc. However, filtering is not possible with SSL encrypted sessions via CONNECT through the proxy, in which case we cannot read/filter the content. Rather than turning SSL CONNECT sessions off (via AllowCONNECT directive), we would like to maintain a list of allowable sites, rather than a list of known bad sites (via ProxyBlock directive.) For that, we have devised the ProxyConnAllow directive with a few minor code additions, described below. 3 diff files are cut/pasted in suggested fix block, below >How-To-Repeat: >Fix: *** mod_proxy-old.h Fri Oct 5 04:19:15 2001 --- mod_proxy.h Mon Mar 18 14:09:30 2002 *************** *** 170,175 **** --- 170,180 ---- struct in_addr addr; }; + struct connallowproxy_entry { + char *name; + struct in_addr addr; + }; + struct nocache_entry { char *name; struct in_addr addr; *************** *** 209,214 **** --- 214,220 ---- array_header *aliases; array_header *raliases; array_header *noproxies; + array_header *conallowproxies; array_header *dirconn; array_header *nocaches; array_header *allowed_connect_ports; *** mod_proxy-old.c Mon Sep 24 16:14:28 2001 --- mod_proxy.c Mon Mar 18 14:11:24 2002 *************** *** 413,418 **** --- 413,419 ---- ps->aliases = ap_make_array(p, 10, sizeof(struct proxy_alias)); ps->raliases = ap_make_array(p, 10, sizeof(struct proxy_alias)); ps->noproxies = ap_make_array(p, 10, sizeof(struct noproxy_entry)); + ps->conallowproxies = ap_make_array(p, 10, sizeof(struct connallowproxy_entry)); ps->dirconn = ap_make_array(p, 10, sizeof(struct dirconn_entry)); ps->nocaches = ap_make_array(p, 10, sizeof(struct nocache_entry)); ps->allowed_connect_ports = ap_make_array(p, 10, sizeof(int)); *************** *** 458,463 **** --- 459,465 ---- ps->aliases = ap_append_arrays(p, base->aliases, overrides->aliases); ps->raliases = ap_append_arrays(p, base->raliases, overrides->raliases); ps->noproxies = ap_append_arrays(p, base->noproxies, overrides->noproxies); + ps->conallowproxies = ap_append_arrays(p, base->conallowproxies, overrides->conallowproxies); ps->dirconn = ap_append_arrays(p, base->dirconn, overrides->dirconn); ps->nocaches = ap_append_arrays(p, base->nocaches, overrides->nocaches); ps->allowed_connect_ports = ap_append_arrays(p, base->allowed_connect_ports, overrides->allowed_connect_ports); *************** *** 583,588 **** --- 585,621 ---- return NULL; } + static const char * + set_proxy_conn_allow(cmd_parms *parms, void *dummy, char *arg) + { + server_rec *s = parms->server; + proxy_server_conf *conf = + ap_get_module_config(s->module_config, &proxy_module); + struct connallowproxy_entry *new; + struct connallowproxy_entry *list = (struct connallowproxy_entry *) conf->conallowproxies->elts; + struct hostent hp; + int found = 0; + int i; + + /* Don't duplicate entries */ + for (i = 0; i < conf->conallowproxies->nelts; i++) { + if (strcasecmp(arg, list[i].name) == 0) /* ignore case for host names */ + found = 1; + } + + if (!found) { + new = ap_push_array(conf->conallowproxies); + new->name = arg; + /* Don't do name lookups on things that aren't dotted */ + if (strchr(arg, '.') != NULL && ap_proxy_host2addr(new->name, &hp) == NULL) + /*@@@FIXME: This copies only the first of (possibly many) IP addrs */ + memcpy(&new->addr, hp.h_addr, sizeof(struct in_addr)); + else + new->addr.s_addr = 0; + } + return NULL; + } + /* * Set the ports CONNECT can use */ *************** *** 901,906 **** --- 934,941 ---- "a virtual path and a URL for reverse proxy behaviour"}, {"ProxyBlock", set_proxy_exclude, NULL, RSRC_CONF, ITERATE, "A list of names, hosts or domains to which the proxy will not connect"}, + {"ProxyConnAllow", set_proxy_conn_allow, NULL, RSRC_CONF, ITERATE, + "A list of names, hosts or domains to which the proxy will allow CONNECT"}, {"ProxyReceiveBufferSize", set_recv_buffer_size, NULL, RSRC_CONF, TAKE1, "Receive buffer size for outgoing HTTP and FTP connections in bytes"}, {"NoProxy", set_proxy_dirconn, NULL, RSRC_CONF, ITERATE, *** proxy_connect-old.c Fri Oct 5 04:19:16 2001 --- proxy_connect.c Mon Mar 18 14:28:32 2002 *************** *** 122,132 **** --- 122,134 ---- char buffer[HUGE_STRING_LEN]; int nbytes, i, j; fd_set fds; + int pcaTst; void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts; + struct connallowproxy_entry *capent = (struct connallowproxy_entry *) conf->conallowproxies->elts; memset(&server, '\0', sizeof(server)); server.sin_family = AF_INET; *************** *** 151,156 **** --- 153,185 ---- "Connect to remote machine blocked"); } + /* check if ProxyConnAllow directive on this host */ + destaddr.s_addr = ap_inet_addr(host); + pcaTst = 0; // 0 = fails to match + if (conf->conallowproxies->nelts == 0) { + // default, if no entries, allow all + // disallow all via AllowCONNECT directive + pcaTst = 1; // 1 = matched + } + else { + for (i = 0; i < conf->conallowproxies->nelts; i++) { + /* matches if first char of conf entry is * + or entry is contained in hostname + or address equals address of entry + */ + if( capent[i].name[0] == '*' + || (capent[i].name != NULL && strstr(host, capent[i].name) != NULL) + || destaddr.s_addr == capent[i].addr.s_addr ) + { + pcaTst = 1; // 1 = matched + break; + } + } + } + if( pcaTst == 0 ) + 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 */ >Release-Note: >Audit-Trail: >Unformatted: [In order for any reply to be added to the PR database, you need] [to include in the Cc line and make sure the] [subject line starts with the report component and number, with ] [or without any 'Re:' prefixes (such as "general/1098:" or ] ["Re: general/1098:"). If the subject doesn't match this ] [pattern, your message will be misfiled and ignored. The ] ["apbugs" address is not added to the Cc line of messages from ] [the database automatically because of the potential for mail ] [loops. If you do not include this Cc, your reply may be ig- ] [nored unless you are responding to an explicit request from a ] [developer. Reply only with text; DO NOT SEND ATTACHMENTS! ]