From: Graham Leggett Date: Sun, 16 Dec 2012 13:57:38 +0000 (+0000) Subject: mod_proxy_ftp: Fix segfaults on IPv4 requests to hosts with DNS AAAA records. X-Git-Tag: 2.4.4~276 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=324031218736afa2b1f22fc34fad6fed0ddbf116;p=apache mod_proxy_ftp: Fix segfaults on IPv4 requests to hosts with DNS AAAA records. PR 40841. trunk patch: http://svn.apache.org/viewvc?rev=1404625&view=rev http://svn.apache.org/viewvc?rev=1420223&view=rev 2.4.x patch: http://people.apache.org/~jorton/proxyftpepsv-24.patch Submitted by: jorton Reviewed by: jim, minfrin git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1422578 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 2176926aa3..00d908d32f 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,10 @@ Changes with Apache 2.4.4 + *) mod_proxy_ftp: Fix segfaults on IPv4 requests to hosts with DNS + AAAA records. PR 40841. [Andrew Rucker Jones , , Jim Jagielski] + *) mod_auth_form: Make sure that get_notes_auth() sets the user as does get_form_auth() and get_session_auth(). Makes sure that REMOTE_USER does not vanish during mod_include driven subrequests. [Graham diff --git a/STATUS b/STATUS index 637513f3d0..1d25391edc 100644 --- a/STATUS +++ b/STATUS @@ -91,14 +91,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * mod_proxy_ftp: Fix segfaults on IPv4 requests to hosts with DNS AAAA records. - PR 40841. - trunk patch: http://svn.apache.org/viewvc?rev=1404625&view=rev - http://svn.apache.org/viewvc?rev=1420223&view=rev - 2.4.x patch: trunk patch works, or - http://people.apache.org/~jorton/proxyftpepsv-24.patch - +1: jorton, jim, minfrin - * mod_slotmem_*: Add in new fgrab() function which forces a grab and slot allocation on a specified slot. Allow for clearing of inuse array. diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c index b342a1c9d0..59a3dd42e4 100644 --- a/modules/proxy/mod_proxy_ftp.c +++ b/modules/proxy/mod_proxy_ftp.c @@ -16,6 +16,7 @@ /* FTP routines for Apache proxy */ +#define APR_WANT_BYTEFUNC #include "mod_proxy.h" #if APR_HAVE_TIME_H #include @@ -1377,8 +1378,6 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, /* set up data connection - EPSV */ { - apr_sockaddr_t *data_addr; - char *data_ip; apr_port_t data_port; /* @@ -1408,14 +1407,36 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, data_port = parse_epsv_reply(ftpmessage); if (data_port) { - apr_sockaddr_t *epsv_addr; + apr_sockaddr_t *remote_addr, epsv_addr; ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "EPSV contacting remote host on port %d", data_port); - if ((rv = apr_socket_create(&data_sock, connect_addr->family, SOCK_STREAM, 0, r->pool)) != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01040) - "error creating EPSV socket"); + /* Retrieve the client's address. */ + rv = apr_socket_addr_get(&remote_addr, APR_REMOTE, sock); + if (rv == APR_SUCCESS) { + /* Take a shallow copy of the server address to + * modify; the _addr_get function gives back a + * pointer to the socket's internal structure. + * This is awkward given current APR network + * interfaces. */ + epsv_addr = *remote_addr; + epsv_addr.port = data_port; +#if APR_HAVE_IPV6 + if (epsv_addr.family == APR_INET6) { + epsv_addr.sa.sin6.sin6_port = htons(data_port); + } + else +#endif + { + epsv_addr.sa.sin.sin_port = htons(data_port); + } + rv = apr_socket_create(&data_sock, epsv_addr.family, SOCK_STREAM, 0, r->pool); + } + + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01040) + "could not establish socket for client data connection"); proxy_ftp_cleanup(r, backend); return HTTP_INTERNAL_SERVER_ERROR; } @@ -1435,19 +1456,17 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker, "Failed to set"); } - /* make the connection */ - apr_socket_addr_get(&data_addr, APR_REMOTE, sock); - apr_sockaddr_ip_get(&data_ip, data_addr); - apr_sockaddr_info_get(&epsv_addr, data_ip, connect_addr->family, data_port, 0, p); - rv = apr_socket_connect(data_sock, epsv_addr); + rv = apr_socket_connect(data_sock, &epsv_addr); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01043) "EPSV attempt to connect to %pI failed - " - "Firewall/NAT?", epsv_addr); + "Firewall/NAT?", &epsv_addr); return ftp_proxyerror(r, backend, HTTP_BAD_GATEWAY, apr_psprintf(r->pool, - "EPSV attempt to connect to %pI failed - firewall/NAT?", epsv_addr)); + "EPSV attempt to connect to %pI failed - firewall/NAT?", &epsv_addr)); } else { + ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, APLOGNO() + "connected data socket to %pI", &epsv_addr); connect = 1; } }