You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by wr...@apache.org on 2007/12/06 19:50:10 UTC

svn commit: r601812 - /httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c

Author: wrowe
Date: Thu Dec  6 10:50:09 2007
New Revision: 601812

URL: http://svn.apache.org/viewvc?rev=601812&view=rev
Log:
Fix PORT/EPRT proxy error reporting, enhance EPRT parsing to compare
after the requested port is canonicalize, and increase strictness of
the PORT command to catch trailing invalid garbage.


Modified:
    httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c

Modified: httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c
URL: http://svn.apache.org/viewvc/httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c?rev=601812&r1=601811&r2=601812&view=diff
==============================================================================
--- httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c (original)
+++ httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c Thu Dec  6 10:50:09 2007
@@ -1724,28 +1724,6 @@
         return res;
     }
 
-    /* Open data connection only if the PORT connection is to the client's 
-     * IP address.
-     * All other PORT connection requests are denied, unless disabled using:
-     *
-     *   FTPOptions AllowProxyPORT 
-     */
-    if (!(fsc->options & FTP_OPT_ALLOWPROXYPORT)) {
-        /* XXX: Match IPv6 ip_addr strings where c->remote_ip is IPv4 mapped */
-        if (strcasecmp(ip_addr, c->remote_ip) != 0) {
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
-                         "PORT data connection request to %s "
-                         "doesn't match the client IP %s",
-                         ip_addr, c->remote_ip);
-            ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
-                         "PORT data connection request denied, "
-                         "not configured to AllowProxyPORT");
-            fc->response_notes = apr_pstrdup(r->pool, 
-                         "Invalid PORT command, proxy PORT is not permitted");
-            return FTP_REPLY_SYNTAX_ERROR;   
-        }
-    }
-    
 #if 0
     if ((fsc->active_min != -1) && (fsc->active_min < 1024)) {
         /* Here's the case of low numbered port creation; the only way
@@ -1780,19 +1758,23 @@
         sa->port = 0;
     }
 
-    /* XXX: Handle IPv6 ip_addr string where c->remote_ip is IPv4 mapped */
-    if ((c->local_addr->family == APR_INET) && (family == APR_INET)) {
-        apr_sockaddr_info_get(&sa, c->local_ip, family,
-                              sa->port, 0, c->pool);
-    }
-    else if ((c->local_addr->family == APR_INET6) && (family == APR_INET6)) {
+    /* XXX: Anything special to handle IPv6 ip_addr string where c->remote_ip
+     * is IPv4 mapped?
+     */
+    if (((c->local_addr->family == APR_INET) && (family == APR_INET)) ||
+#if APR_HAVE_IPV6
+            ((c->local_addr->family == APR_INET6) && (family == APR_INET6))
+#endif
+       ) {
         apr_sockaddr_info_get(&sa, c->local_ip, family,
                               sa->port, 0, c->pool);
     }
     else {
+        /* If the family differs, it's difficult to map the EPRT origin IP */
         apr_sockaddr_info_get(&sa, NULL, family,
                               sa->port, 0, c->pool);
     }
+
     apr_socket_opt_set(s, APR_SO_REUSEADDR, 1);
     rv = apr_socket_bind(s, sa);
 
@@ -1807,9 +1789,45 @@
     }
 
     apr_socket_addr_get(&fc->clientsa, APR_LOCAL, s);
-    apr_sockaddr_info_get(&fc->clientsa, ip_addr, family,
-                          port, 0, c->pool);
+    rv = apr_sockaddr_info_get(&fc->clientsa, ip_addr, family,
+                               port, 0, c->pool);
+    if (rv) {
+        ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
+                     "Unable to decode EPRT request |%d|%s|%d|",
+#if APR_HAVE_IPV6
+                     (family == APR_INET6) ? 2 : 1, ip_addr, port);
+#else
+                     1, ip_addr, port);
+#endif
+        fc->response_notes = apr_pstrdup(r->pool,
+                     "Invalid EPRT command, unable to decode request");
+        return FTP_REPLY_SYNTAX_ERROR;
+    }
 
+    /* Open data connection only if the EPRT connection is to the client's
+     * IP address.
+     * All other EPRT connection requests are denied, unless disabled using:
+     *
+     *   FTPOptions AllowProxyPORT
+     *
+     * We must canonicalize the IP address first to compare it to our own
+     * idea of the client's IP address.
+     */
+    if (!(fsc->options & FTP_OPT_ALLOWPROXYPORT)) {
+        char *test_ip = "(unknown)";
+        if (apr_sockaddr_ip_get(&test_ip, fc->clientsa) != APR_SUCCESS
+                || (strcasecmp(test_ip, c->remote_ip) != 0)) {
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
+                         "Rejected EPRT data connection request to %s "
+                         "(doesn't match the client IP %s and "
+                         "not configured to AllowProxyPORT)",
+                         test_ip, c->remote_ip);
+            fc->response_notes = apr_pstrdup(r->pool,
+                         "Invalid EPRT command, proxy EPRT is not permitted");
+            return FTP_REPLY_SYNTAX_ERROR;
+        }
+    }
+    
     fc->response_notes = apr_psprintf(r->pool, FTP_MSG_SUCCESS, r->method);
     fc->passive_created = -1; /* Redundant but just for clarity */
     fc->csock = s;
@@ -1824,7 +1842,7 @@
     apr_sockaddr_t *sa;
     apr_socket_t *s;
     apr_status_t rv;
-    char *ip_addr;
+    char *ip_addr, tc;
     short port;
     int res, val[6];
 
@@ -1839,8 +1857,8 @@
         fc->passive_created = -1;
     }
 
-    if ((res = sscanf(arg, "%d,%d,%d,%d,%d,%d", &val[0], &val[1], &val[2],
-                      &val[3], &val[4], &val[5])) != 6) {
+    if ((res = sscanf(arg, "%d,%d,%d,%d,%d,%d%c", &val[0], &val[1], &val[2],
+                      &val[3], &val[4], &val[5], &tc)) != 6) {
         fc->response_notes = apr_pstrdup(r->pool, "Invalid PORT request");
         return FTP_REPLY_SYNTAX_ERROR;   
     }
@@ -1857,14 +1875,13 @@
      */
     if (!(fsc->options & FTP_OPT_ALLOWPROXYPORT)) {
         if (strcasecmp(ip_addr, c->remote_ip) != 0) {
-            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, c->base_server,
-                         "PORT data connection request to %s "
-                         "doesn't match the client IP %s",
-                         ip_addr, c->remote_ip);
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
-                         "PORT data connection request denied, "
-                         "not configured to AllowProxyPORT");
-            fc->response_notes = apr_pstrdup(r->pool, "Invalid PORT command, proxy PORT is not permitted");
+                         "Rejected PORT data connection request to %s "
+                         "(doesn't match the client IP %s and "
+                         "not configured to AllowProxyPORT)",
+                         ip_addr, c->remote_ip);
+            fc->response_notes = apr_pstrdup(r->pool,
+                         "Invalid PORT command, proxy PORT is not permitted");
             return FTP_REPLY_SYNTAX_ERROR;   
         }
     }