From 9e5f5087f1140ba75137027f662e193f29a898ac Mon Sep 17 00:00:00 2001 From: Martin Kraemer Date: Tue, 29 Jan 2002 15:31:28 +0000 Subject: [PATCH] * Prefer compatibility with both HTML-4 and XHTML (rather than XHTML only) * Properly escape URIs and HTML in the FTP filename list * Avoid a pointer underrun git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93075 13f79535-47bb-0310-9956-ffa450edef68 --- modules/proxy/proxy_ftp.c | 135 +++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 60 deletions(-) diff --git a/modules/proxy/proxy_ftp.c b/modules/proxy/proxy_ftp.c index 234b41177a..389862a2af 100644 --- a/modules/proxy/proxy_ftp.c +++ b/modules/proxy/proxy_ftp.c @@ -69,7 +69,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, char *url, const char *proxyhost, apr_port_t proxyport); apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, - apr_bucket_brigade * bb); + apr_bucket_brigade *bb); /* @@ -211,7 +211,7 @@ int ap_proxy_ftp_canon(request_rec *r, char *url) * Reads response lines, returns both the ftp status code and * remembers the response message in the supplied buffer */ -static int ftp_getrc_msg(conn_rec *c, apr_bucket_brigade * bb, char *msgbuf, int msglen) +static int ftp_getrc_msg(conn_rec *ftp_ctrl, apr_bucket_brigade *bb, char *msgbuf, int msglen) { int status; char response[MAX_LINE_LEN]; @@ -220,9 +220,13 @@ static int ftp_getrc_msg(conn_rec *c, apr_bucket_brigade * bb, char *msgbuf, int apr_status_t rv; int eos; - if (APR_SUCCESS != (rv = ap_proxy_string_read(c, bb, response, sizeof(response), &eos))) { + if (APR_SUCCESS != (rv = ap_proxy_string_read(ftp_ctrl, bb, response, sizeof(response), &eos))) { return -1; } +/* + ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, NULL, + "proxy: r; apr_pool_t *p = r->pool; @@ -302,11 +306,12 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, apr_bucket_brigade * in) /* print "ftp://host/" */ str = apr_psprintf(p, DOCTYPE_HTML_3_2 - "\n\n\n\n%s%s\n" - "\n\n\n" - "\n\n

Directory of " - "%s/", - site, path, site, path, site); + "\n\n\n\n%s%s\n" + "\n\n\n" + "\n\n

Directory of " + "%s/", + site, ap_escape_uri(p, path), + site, ap_escape_html(p, path), site); e = apr_bucket_pool_create(str, strlen(str), p); APR_BRIGADE_INSERT_TAIL(out, e); @@ -318,7 +323,9 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, apr_bucket_brigade * in) else ++reldir; /* print "path/" component */ - str = apr_psprintf(p, "%s/", path + 1, reldir); + str = apr_psprintf(p, "%s/", + ap_escape_uri(p, path + 1), + ap_escape_html(p, reldir)); e = apr_bucket_pool_create(str, strlen(str), p); APR_BRIGADE_INSERT_TAIL(out, e); *dir = '/'; @@ -326,18 +333,18 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, apr_bucket_brigade * in) /* If the caller has determined the current directory, and it differs */ /* from what the client requested, then show the real name */ if (pwd == NULL || strncmp(pwd, path, strlen(pwd)) == 0) { - str = apr_psprintf(p, "

\n\n
\n\n
");
+            str = apr_psprintf(p, "\n\n
\n\n
");
         }
         else {
-            str = apr_psprintf(p, "\n\n(%s)\n\n
\n\n
", pwd);
+            str = apr_psprintf(p, "\n\n(%s)\n\n
\n\n
", pwd);
         }
         e = apr_bucket_pool_create(str, strlen(str), p);
         APR_BRIGADE_INSERT_TAIL(out, e);
 
         /* print README */
         if (readme) {
-            str = apr_psprintf(p, "%s\n
\n\n
\n\n
\n",
-                               readme);
+            str = apr_psprintf(p, "%s\n
\n\n
\n\n
\n",
+                               ap_escape_html(p, readme));
 
             e = apr_bucket_pool_create(str, strlen(str), p);
             APR_BRIGADE_INSERT_TAIL(out, e);
@@ -378,7 +385,6 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, apr_bucket_brigade * in)
                 if ((response + len) != (pos + 1)) {
                     len = pos - response + 1;
                     apr_bucket_split(e, pos - response + 1);
-
                 }
                 found = 1;
             }
@@ -410,12 +416,17 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, apr_bucket_brigade * in)
 
             do {
                 filename--;
-            } while (filename[0] != ' ');
-            *(filename++) = '\0';
+            } while (filename[0] != ' ' && filename > ctx->buffer);
+            if (filename > ctx->buffer)
+                *(filename++) = '\0';
             *(link_ptr++) = '\0';
             if ((n = strlen(link_ptr)) > 1 && link_ptr[n - 1] == '\n')
                 link_ptr[n - 1] = '\0';
-            str = apr_psprintf(p, "%s %s %s\n", ctx->buffer, filename, filename, link_ptr);
+            str = apr_psprintf(p, "%s %s %s\n",
+                               ap_escape_html(p, ctx->buffer),
+                               ap_escape_uri(p, filename),
+                               ap_escape_html(p, filename),
+                               ap_escape_html(p, link_ptr));
         }
 
         /* a directory/file? */
@@ -449,16 +460,20 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, apr_bucket_brigade * in)
 
             /* Special handling for '.' and '..' */
             if (!strcmp(filename, ".") || !strcmp(filename, "..") || ctx->buffer[0] == 'd') {
-                str = apr_psprintf(p, "%s %s\n",
-                                   ctx->buffer, filename, filename);
+                str = apr_psprintf(p, "%s %s\n",
+                                   ap_escape_html(p, ctx->buffer),
+                                   ap_escape_uri(p, filename),
+                                   ap_escape_html(p, filename));
             }
             else {
-                str = apr_psprintf(p, "%s %s\n",
-                                   ctx->buffer, filename, filename);
+                str = apr_psprintf(p, "%s %s\n",
+                                   ap_escape_html(p, ctx->buffer),
+                                   ap_escape_uri(p, filename),
+                                   ap_escape_html(p, filename));
             }
         }
         else {
-            str = apr_pstrdup(p, ctx->buffer);
+            str = ap_escape_html(p, ctx->buffer);
         }
 
         /* erase buffer for next time around */
@@ -476,7 +491,7 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t * f, apr_bucket_brigade * in)
     }
 
     if (FOOTER == ctx->state) {
-        str = apr_psprintf(p, "
\n\n
\n\n%s\n\n\n\n", ap_psignature("", r)); + str = apr_psprintf(p, "
\n\n
\n\n%s\n\n\n\n", ap_psignature("", r)); e = apr_bucket_pool_create(str, strlen(str), p); APR_BRIGADE_INSERT_TAIL(out, e); @@ -539,10 +554,10 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, apr_pool_t *p = r->pool; conn_rec *c = r->connection; proxy_conn_rec *backend; - apr_socket_t *sock, *local_sock, *remote_sock = NULL; + apr_socket_t *sock, *local_sock, *data_sock = NULL; apr_sockaddr_t *connect_addr; apr_status_t rv; - conn_rec *origin, *remote; + conn_rec *origin, *data; int err; apr_bucket *e; apr_bucket_brigade *bb = apr_brigade_create(p); @@ -591,7 +606,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* * I: Who Do I Connect To? ----------------------- - * + * * Break up the URL to determine the host to connect to */ @@ -661,7 +676,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* * II: Make the Connection ----------------------- - * + * * We have determined who to connect to. Now make the connection. */ @@ -711,7 +726,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, * machine to connect to. If configured, reorder this list so that the * "best candidate" is first try. "best candidate" could mean the least * loaded server, the fastest responding server, whatever. - * + * * For now we do nothing, ie we get DNS round robin. XXX FIXME */ @@ -770,7 +785,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* * III: Send Control Request ------------------------- - * + * * Log into the ftp server, send the username & password, change to the * correct directory... */ @@ -791,7 +806,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, if (rc == 120) { /* * RFC2616 states: 14.37 Retry-After - * + * * The Retry-After response-header field can be used with a 503 (Service * Unavailable) response to indicate how long the service is expected * to be unavailable to the requesting client. [...] The value of @@ -975,7 +990,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* * IV: Make Data Connection? ------------------------- - * + * * Try EPSV, if that fails... try PASV, if that fails... try PORT. */ /* this temporarily switches off EPSV/PASV */ @@ -983,9 +998,9 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* set up data connection - EPSV */ { - apr_sockaddr_t *remote_addr; - char *remote_ip; - apr_port_t remote_port; + apr_sockaddr_t *data_addr; + char *data_ip; + apr_port_t data_port; /* * The EPSV command replaces PASV where both IPV4 and IPV6 is @@ -1038,20 +1053,20 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, if (pstr) { apr_sockaddr_t *epsv_addr; - remote_port = atoi(pstr + 3); + data_port = atoi(pstr + 3); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "proxy: FTP: EPSV contacting remote host on port %d", - remote_port); + data_port); - if ((rv = apr_socket_create(&remote_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) { + if ((rv = apr_socket_create(&data_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: FTP: error creating EPSV socket"); return HTTP_INTERNAL_SERVER_ERROR; } #if !defined (TPF) && !defined(BEOS) - if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(remote_sock, APR_SO_RCVBUF, + if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(data_sock, APR_SO_RCVBUF, conf->recv_buffer_size))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: FTP: setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); @@ -1059,10 +1074,10 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, #endif /* make the connection */ - apr_socket_addr_get(&remote_addr, APR_REMOTE, sock); - apr_sockaddr_ip_get(&remote_ip, remote_addr); - apr_sockaddr_info_get(&epsv_addr, remote_ip, APR_INET, remote_port, 0, p); - rv = apr_connect(remote_sock, epsv_addr); + 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, APR_INET, data_port, 0, p); + rv = apr_connect(data_sock, epsv_addr); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, "proxy: FTP: EPSV attempt to connect to %pI failed - Firewall/NAT?", epsv_addr); @@ -1075,7 +1090,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, } else { /* and try the regular way */ - apr_socket_close(remote_sock); + apr_socket_close(data_sock); } } } @@ -1139,14 +1154,14 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, "proxy: FTP: PASV contacting host %d.%d.%d.%d:%d", h3, h2, h1, h0, pasvport); - if ((rv = apr_socket_create(&remote_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) { + if ((rv = apr_socket_create(&data_sock, APR_INET, SOCK_STREAM, r->pool)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: error creating PASV socket"); return HTTP_INTERNAL_SERVER_ERROR; } #if !defined (TPF) && !defined(BEOS) - if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(remote_sock, APR_SO_RCVBUF, + if (conf->recv_buffer_size > 0 && (rv = apr_setsocketopt(data_sock, APR_SO_RCVBUF, conf->recv_buffer_size))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "proxy: FTP: setsockopt(SO_RCVBUF): Failed to set ProxyReceiveBufferSize, using default"); @@ -1155,7 +1170,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* make the connection */ apr_sockaddr_info_get(&pasv_addr, apr_psprintf(p, "%d.%d.%d.%d", h3, h2, h1, h0), APR_INET, pasvport, 0, p); - rv = apr_connect(remote_sock, pasv_addr); + rv = apr_connect(data_sock, pasv_addr); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, "proxy: FTP: PASV attempt to connect to %pI failed - Firewall/NAT?", pasv_addr); @@ -1168,7 +1183,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, } else { /* and try the regular way */ - apr_socket_close(remote_sock); + apr_socket_close(data_sock); } } } @@ -1263,7 +1278,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* * V: Set The Headers ------------------- - * + * * Get the size of the request, set up the environment for HTTP. */ @@ -1537,7 +1552,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* wait for connection */ if (use_port) { for (;;) { - rv = apr_accept(&remote_sock, local_sock, r->pool); + rv = apr_accept(&data_sock, local_sock, r->pool); if (rv == APR_EINTR) { continue; } @@ -1553,8 +1568,8 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, } /* the transfer socket is now open, create a new connection */ - remote = ap_new_connection(p, r->server, remote_sock, r->connection->id, r->connection->sbh); - if (!remote) { + data = ap_new_connection(p, r->server, data_sock, r->connection->id, r->connection->sbh); + if (!data) { /* * the peer reset the connection already; ap_new_connection() closed * the socket @@ -1565,12 +1580,12 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, } /* set up the connection filters */ - ap_proxy_pre_http_connection(remote); + ap_proxy_pre_http_connection(data); /* * VI: Receive the Response ------------------------ - * + * * Get response from the remote ftp socket, and pass it up the filter chain. */ @@ -1589,7 +1604,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, "proxy: FTP: start body send"); /* read the body, pass it to the output filters */ - while (ap_get_brigade(remote->input_filters, bb, AP_MODE_EXHAUSTIVE, + while (ap_get_brigade(data->input_filters, bb, AP_MODE_EXHAUSTIVE, APR_BLOCK_READ, 0) == APR_SUCCESS) { if (APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb))) { ap_pass_brigade(r->output_filters, bb); @@ -1602,8 +1617,8 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, apr_brigade_cleanup(bb); } } - ap_flush_conn(remote); - apr_socket_close(remote_sock); + ap_flush_conn(data); + apr_socket_close(data_sock); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "proxy: FTP: Closing Data connection."); rc = ftp_getrc_msg(origin, cbb, buffer, sizeof(buffer)); @@ -1615,7 +1630,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, /* * VII: Clean Up ------------- - * + * * If there are no KeepAlives, or if the connection has been signalled to * close, close the socket and clean up */ @@ -1642,7 +1657,7 @@ int ap_proxy_ftp_handler(request_rec *r, proxy_server_conf *conf, return OK; } -static void ap_proxy_ftp_register_hook(apr_pool_t * p) +static void ap_proxy_ftp_register_hook(apr_pool_t *p) { /* hooks */ proxy_hook_scheme_handler(ap_proxy_ftp_handler, NULL, NULL, APR_HOOK_MIDDLE); -- 2.50.1