*) apxs: Use LDFLAGS from config_vars.mk in addition to CFLAGS and CPPFLAGS.
[Stefan Fritsch]
+ *) mod_proxy: Fix memory leak or possible corruption in ProxyBlock
+ implementation. [Ruediger Pluem, Joe Orton]
+
+ *) mod_proxy: Check hostname from request URI against ProxyBlock list,
+ not forward proxy, if ProxyRemote* is configured. [Joe Orton]
+
+ *) mod_proxy_connect: Avoid DNS lookup on hostname from request URI
+ if ProxyRemote* is configured. PR 43697. [Joe Orton]
+
*) mpm_event, mpm_worker: Remain active amidst prevalent child process
resource shortages. [Jeff Trawick]
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- * mod_proxy*: ProxyBlock fixes; PR 43697 and more.
- trunk patch: http://svn.apache.org/viewvc?rev=1365001&view=rev and
- http://svn.apache.org/viewvc?rev=1365020&view=rev and
- http://svn.apache.org/viewvc?rev=1365029&view=rev
- 2.4.x patch: http://people.apache.org/~jorton/ap_proxyblock-24x-v2.diff [avoids major MMN bump]
- +1: jorton, rjung, jim
PATCHES PROPOSED TO BACKPORT FROM TRUNK:
[ New proposals should be added at the end of the list ]
* 20120211.3 (2.4.2-dev) Add forcerecovery to proxy_balancer_shared struct
* 20120211.4 (2.4.3-dev) Add ap_list_provider_groups()
* 20120211.5 (2.4.3-dev) Add missing HTTP status codes registered with IANA.
+ * 20120211.6 (2.4.3-dev) Add ap_proxy_checkproxyblock2.
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 5 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 6 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
char **passwordp, char **hostp, apr_port_t *port);
PROXY_DECLARE(int) ap_proxyerror(request_rec *r, int statuscode, const char *message);
PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf, apr_sockaddr_t *uri_addr);
+
+/** Test whether the hostname/address of the request are blocked by the ProxyBlock
+ * configuration.
+ * @param r request
+ * @param conf server configuration
+ * @param hostname hostname from request URI
+ * @param addr resolved address of hostname, or NULL if not known
+ * @return OK on success, or else an errro
+ */
+PROXY_DECLARE(int) ap_proxy_checkproxyblock2(request_rec *r, proxy_server_conf *conf,
+ const char *hostname, apr_sockaddr_t *addr);
+
PROXY_DECLARE(int) ap_proxy_pre_http_request(conn_rec *c, request_rec *r);
/* DEPRECATED (will be replaced with ap_proxy_connect_backend */
PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, request_rec *);
conn_rec *backconn;
apr_bucket_brigade *bb = apr_brigade_create(p, c->bucket_alloc);
- apr_status_t err, rv;
+ apr_status_t rv;
apr_size_t nbytes;
char buffer[HUGE_STRING_LEN];
apr_socket_t *client_socket = ap_get_conn_socket(c);
const apr_pollfd_t *signalled;
apr_int32_t pollcnt, pi;
apr_int16_t pollevent;
- apr_sockaddr_t *uri_addr, *connect_addr;
+ apr_sockaddr_t *nexthop;
apr_uri_t uri;
const char *connectname;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01019)
"connecting %s to %s:%d", url, uri.hostname, uri.port);
- /* do a DNS lookup for the destination host */
- err = apr_sockaddr_info_get(&uri_addr, uri.hostname, APR_UNSPEC, uri.port,
- 0, p);
- if (APR_SUCCESS != err) {
+ /* Determine host/port of next hop; from request URI or of a proxy. */
+ connectname = proxyname ? proxyname : uri.hostname;
+ connectport = proxyname ? proxyport : uri.port;
+
+ /* Do a DNS lookup for the next hop */
+ rv = apr_sockaddr_info_get(&nexthop, connectname, APR_UNSPEC,
+ connectport, 0, p);
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO()
+ "failed to resolve hostname '%s'", connectname);
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
apr_pstrcat(p, "DNS lookup failure for: ",
- uri.hostname, NULL));
+ connectname, NULL));
}
- /* are we connecting directly, or via a proxy? */
- if (proxyname) {
- connectname = proxyname;
- connectport = proxyport;
- err = apr_sockaddr_info_get(&connect_addr, proxyname, APR_UNSPEC,
- proxyport, 0, p);
- }
- else {
- connectname = uri.hostname;
- connectport = uri.port;
- connect_addr = uri_addr;
+ /* Check ProxyBlock directive on the hostname/address. */
+ if (ap_proxy_checkproxyblock2(r, conf, uri.hostname,
+ proxyname ? NULL : nexthop) != OK) {
+ return ap_proxyerror(r, HTTP_FORBIDDEN,
+ "Connect to remote machine blocked");
}
+
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
"connecting to remote proxy %s on port %d",
connectname, connectport);
- /* check if ProxyBlock directive on this host */
- if (OK != ap_proxy_checkproxyblock(r, conf, uri_addr)) {
- return ap_proxyerror(r, HTTP_FORBIDDEN,
- "Connect to remote machine blocked");
- }
-
/* Check if it is an allowed port */
if(!allowed_port(c_conf, uri.port)) {
return ap_proxyerror(r, HTTP_FORBIDDEN,
* We have determined who to connect to. Now make the connection.
*/
- /* get all the possible IP addresses for the destname and loop through them
- * until we get a successful connection
- */
- if (APR_SUCCESS != err) {
- return ap_proxyerror(r, HTTP_BAD_GATEWAY,
- apr_pstrcat(p, "DNS lookup failure for: ",
- connectname, NULL));
- }
-
/*
* At this point we have a list of one or more IP addresses of
* the machine to connect to. If configured, reorder this
* For now we do nothing, ie we get DNS round robin.
* XXX FIXME
*/
- failed = ap_proxy_connect_to_backend(&sock, "CONNECT", connect_addr,
+ failed = ap_proxy_connect_to_backend(&sock, "CONNECT", nexthop,
connectname, conf, r);
/* handle a permanent error from the above loop */
/* peer reset */
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01021)
"an error occurred creating a new connection "
- "to %pI (%s)", connect_addr, connectname);
+ "to %pI (%s)", nexthop, connectname);
apr_socket_close(sock);
return HTTP_INTERNAL_SERVER_ERROR;
}
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, r,
"connection complete to %pI (%s)",
- connect_addr, connectname);
+ nexthop, connectname);
apr_table_setn(r->notes, "proxy-source-port", apr_psprintf(r->pool, "%hu",
backconn->local_addr->port));
}
/* check if ProxyBlock directive on this host */
- if (OK != ap_proxy_checkproxyblock(r, conf, connect_addr)) {
+ if (OK != ap_proxy_checkproxyblock2(r, conf, connectname, connect_addr)) {
return ap_proxyerror(r, HTTP_FORBIDDEN,
"Connect to remote machine blocked");
}
return host != NULL && ap_strstr_c(host, This->name) != NULL;
}
-/* checks whether a host in uri_addr matches proxyblock */
+/* Backwards-compatible interface. */
PROXY_DECLARE(int) ap_proxy_checkproxyblock(request_rec *r, proxy_server_conf *conf,
apr_sockaddr_t *uri_addr)
+{
+ return ap_proxy_checkproxyblock2(r, conf, uri_addr->hostname, uri_addr);
+}
+
+#define MAX_IP_STR_LEN (46)
+
+PROXY_DECLARE(int) ap_proxy_checkproxyblock2(request_rec *r, proxy_server_conf *conf,
+ const char *hostname, apr_sockaddr_t *addr)
{
int j;
- apr_sockaddr_t * src_uri_addr = uri_addr;
+
/* XXX FIXME: conf->noproxies->elts is part of an opaque structure */
for (j = 0; j < conf->noproxies->nelts; j++) {
struct noproxy_entry *npent = (struct noproxy_entry *) conf->noproxies->elts;
- struct apr_sockaddr_t *conf_addr = npent[j].addr;
- uri_addr = src_uri_addr;
+ struct apr_sockaddr_t *conf_addr;
+
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
"checking remote machine [%s] against [%s]",
- uri_addr->hostname, npent[j].name);
- if (ap_strstr_c(uri_addr->hostname, npent[j].name)
- || npent[j].name[0] == '*') {
+ hostname, npent[j].name);
+ if (ap_strstr_c(hostname, npent[j].name) || npent[j].name[0] == '*') {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00916)
"connect to remote machine %s blocked: name %s "
- "matched", uri_addr->hostname, npent[j].name);
+ "matched", hostname, npent[j].name);
return HTTP_FORBIDDEN;
}
- while (conf_addr) {
- uri_addr = src_uri_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);
+
+ /* No IP address checks if no IP address was passed in,
+ * i.e. the forward address proxy case, where this server does
+ * not resolve the hostname. */
+ if (!addr)
+ continue;
+
+ for (conf_addr = npent[j].addr; conf_addr; conf_addr = conf_addr->next) {
+ char caddr[MAX_IP_STR_LEN], uaddr[MAX_IP_STR_LEN];
+ apr_sockaddr_t *uri_addr;
+
+ if (apr_sockaddr_ip_getbuf(caddr, sizeof caddr, conf_addr))
+ continue;
+
+ for (uri_addr = addr; uri_addr; uri_addr = uri_addr->next) {
+ if (apr_sockaddr_ip_getbuf(uaddr, sizeof uaddr, uri_addr))
+ continue;
ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
- "ProxyBlock comparing %s and %s", conf_ip,
- uri_ip);
- if (!apr_strnatcasecmp(conf_ip, uri_ip)) {
+ "ProxyBlock comparing %s and %s", caddr, uaddr);
+ if (!strcmp(caddr, uaddr)) {
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(00917)
- "connect to remote machine %s blocked: "
- "IP %s matched", uri_addr->hostname, conf_ip);
+ "connect to remote machine %s blocked: "
+ "IP %s matched", hostname, caddr);
return HTTP_FORBIDDEN;
}
- uri_addr = uri_addr->next;
}
- conf_addr = conf_addr->next;
}
}
+
return OK;
}
}
}
/* check if ProxyBlock directive on this host */
- if (OK != ap_proxy_checkproxyblock(r, conf, conn->addr)) {
+ if (OK != ap_proxy_checkproxyblock2(r, conf, uri->hostname,
+ proxyname ? NULL : conn->addr)) {
return ap_proxyerror(r, HTTP_FORBIDDEN,
"Connect to remote machine blocked");
}