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 2009/05/27 23:42:01 UTC
svn commit: r779323 - /httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c
Author: wrowe
Date: Wed May 27 21:42:01 2009
New Revision: 779323
URL: http://svn.apache.org/viewvc?rev=779323&view=rev
Log:
Some preparation - merging server-side sockaddr handling for PORT/EPRT
to prepare to handle PORT/EPRT connections from low numbered ports
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=779323&r1=779322&r2=779323&view=diff
==============================================================================
--- httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c (original)
+++ httpd/mod_ftp/trunk/modules/ftp/ftp_commands.c Wed May 27 21:42:01 2009
@@ -1716,53 +1716,67 @@
return FTP_REPLY_COMMAND_OK;
}
-
-static int ftp_cmd_eprt(request_rec *r, const char *arg)
+static int get_outbound_port(apr_sockaddr_t **sa_rv, request_rec *r,
+ apr_int32_t family)
{
- ftp_server_config *fsc = ftp_get_module_config(r->server->module_config);
- ftp_connection *fc = ftp_get_module_config(r->connection->conn_config);
conn_rec *c = r->connection;
+ ftp_connection *fc = ftp_get_module_config(c->conn_config);
+ ftp_server_config *fsc = ftp_get_module_config(r->server->module_config);
apr_sockaddr_t *sa;
apr_socket_t *s;
apr_status_t rv;
- char *arg_tok, *ip_addr;
- apr_int32_t family;
- apr_port_t port;
- int res;
-
- ftp_reset_dataconn(fc);
+ apr_port_t local_port;
- if (fc->all_epsv) {
- fc->response_notes = apr_pstrdup(r->pool, "Restricted by EPSV ALL ");
- return FTP_REPLY_BAD_SEQUENCE;
+ if (fsc->active_min == -1) {
+ local_port = 0;
}
-
- arg_tok = apr_pstrdup(fc->data_pool, arg);
- if ((res = ftp_eprt_decode(&family, &ip_addr, &port, arg_tok))
- != FTP_REPLY_COMMAND_OK) {
- fc->response_notes = apr_pstrdup(r->pool, "Invalid EPRT request");
- return res;
+ else if (fsc->active_max == fsc->active_min) {
+ local_port = fsc->active_min;
+ }
+ else {
+ local_port = fsc->active_min +
+ (apr_port_t) (rand() % (fsc->active_max -
+ fsc->active_min + 1));
}
- sa = apr_palloc(fc->data_pool, sizeof(apr_sockaddr_t));
- memcpy(sa, c->local_addr, sizeof(apr_sockaddr_t));
- sa->next = NULL;
- if (sa->family == APR_INET)
- sa->ipaddr_ptr = &(sa->sa.sin.sin_addr);
+ if (c->local_addr->family == family) {
+ /* Shortcut; duplicate the contents */
+ sa = apr_palloc(fc->data_pool, sizeof(apr_sockaddr_t));
+ memcpy(sa, c->local_addr, sizeof(apr_sockaddr_t));
+ sa->next = NULL;
+ if (sa->family == APR_INET)
+ sa->ipaddr_ptr = &(sa->sa.sin.sin_addr);
#if APR_HAVE_IPV6
- else if (sa->family == APR_INET6)
- sa->ipaddr_ptr = &(sa->sa.sin6.sin6_addr);
+ else if (sa->family == APR_INET6)
+ sa->ipaddr_ptr = &(sa->sa.sin6.sin6_addr);
#endif
-
- if (fsc->active_min != -1) {
- sa->port = fsc->active_min +
- (apr_port_t) (rand() % (fsc->active_max -
- fsc->active_min + 1));
+ sa->sa.sin.sin_port = htons(local_port);
}
else {
- sa->port = 0;
+ /* Long way around, create a fresh sa, attempt to use
+ * the original port, before falling back on the nul adapter
+ * TODO: this could use a config option to specify the
+ * preferred interface/local address
+ */
+ rv = apr_sockaddr_info_get(&sa, c->local_ip, family,
+ local_port, 0, fc->data_pool);
+ if (!sa || rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
+ "Couldn't resolve explicit local socket address"
+ " %s (apr or socket stack bug?) Retrying",
+ c->local_ip);
+ rv = apr_sockaddr_info_get(&sa, NULL, APR_INET,
+ local_port, 0, fc->data_pool);
+ }
+
+ if (!sa || rv) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ "Couldn't resolve emphemeral local socket address"
+ " (apr or socket stack bug?) Giving up");
+ apr_socket_close(s);
+ return FTP_REPLY_CANNOT_OPEN_DATACONN;
+ }
}
- sa->sa.sin.sin_port = htons(sa->port);
#if APR_MAJOR_VERSION < 1
rv = apr_socket_create_ex(&s, family, SOCK_STREAM, APR_PROTO_TCP,
@@ -1790,9 +1804,9 @@
* worker processes.
*/
}
+ else
#endif
-
- rv = apr_socket_bind(s, sa);
+ rv = apr_socket_bind(s, sa);
if (rv != APR_SUCCESS) {
#ifdef EACCES
@@ -1807,6 +1821,38 @@
return FTP_REPLY_CANNOT_OPEN_DATACONN;
}
+ *sa_rv = sa;
+ fc->csock = s;
+ fc->response_notes = apr_psprintf(r->pool, FTP_MSG_SUCCESS, r->method);
+ return FTP_REPLY_COMMAND_OK;
+}
+
+static int ftp_cmd_eprt(request_rec *r, const char *arg)
+{
+ conn_rec *c = r->connection;
+ ftp_connection *fc = ftp_get_module_config(c->conn_config);
+ ftp_server_config *fsc = ftp_get_module_config(r->server->module_config);
+ apr_sockaddr_t *sa;
+ apr_status_t rv;
+ char *arg_tok, *ip_addr;
+ apr_int32_t family;
+ apr_port_t port;
+ int res;
+
+ ftp_reset_dataconn(fc);
+
+ if (fc->all_epsv) {
+ fc->response_notes = apr_pstrdup(r->pool, "Restricted by EPSV ALL ");
+ return FTP_REPLY_BAD_SEQUENCE;
+ }
+
+ arg_tok = apr_pstrdup(fc->data_pool, arg);
+ if ((res = ftp_eprt_decode(&family, &ip_addr, &port, arg_tok))
+ != FTP_REPLY_COMMAND_OK) {
+ fc->response_notes = apr_pstrdup(r->pool, "Invalid EPRT request");
+ return res;
+ }
+
rv = apr_sockaddr_info_get(&fc->clientsa, ip_addr, family,
port, 0, fc->data_pool);
if (!fc->clientsa || rv) {
@@ -1819,7 +1865,6 @@
#endif
fc->response_notes = apr_pstrdup(r->pool,
"Invalid EPRT command, unable to resolve request");
- apr_socket_close(s);
return FTP_REPLY_SYNTAX_ERROR;
}
@@ -1844,25 +1889,20 @@
test_ip, c->remote_ip);
fc->response_notes = apr_pstrdup(r->pool,
"Invalid EPRT command, proxy EPRT is not permitted");
- apr_socket_close(s);
return FTP_REPLY_SYNTAX_ERROR;
}
}
- fc->response_notes = apr_psprintf(r->pool, FTP_MSG_SUCCESS, r->method);
- fc->csock = s;
- return FTP_REPLY_COMMAND_OK;
+ return get_outbound_port(&sa, r, family);
}
static int ftp_cmd_port(request_rec *r, const char *arg)
{
- ftp_server_config *fsc = ftp_get_module_config(r->server->module_config);
- ftp_connection *fc = ftp_get_module_config(r->connection->conn_config);
conn_rec *c = r->connection;
+ ftp_connection *fc = ftp_get_module_config(c->conn_config);
+ ftp_server_config *fsc = ftp_get_module_config(r->server->module_config);
apr_sockaddr_t *sa;
- apr_socket_t *s;
apr_status_t rv;
- apr_port_t local_port;
apr_port_t port;
char *ip_addr, tc;
int res, val[6];
@@ -1905,84 +1945,6 @@
}
}
- if (fsc->active_min != -1) {
- local_port = fsc->active_min +
- (apr_port_t) (rand() % (fsc->active_max -
- fsc->active_min + 1));
- }
- else {
- local_port = 0;
- }
-
- if (c->local_addr->family == APR_INET) {
- rv = apr_sockaddr_info_get(&sa, c->local_ip, APR_INET,
- local_port, 0, fc->data_pool);
- if (!sa || rv) {
- ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, r,
- "Couldn't resolve explicit local socket address"
- " %s (apr or socket stack bug?) Retrying",
- c->local_ip);
- rv = apr_sockaddr_info_get(&sa, NULL, APR_INET,
- local_port, 0, fc->data_pool);
- }
- }
- else {
- rv = apr_sockaddr_info_get(&sa, NULL, APR_INET,
- local_port, 0, fc->data_pool);
- }
-
- if (!sa || rv) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "Couldn't resolve emphemeral local socket address"
- " (apr or socket stack bug?) Giving up");
- apr_socket_close(s);
- return FTP_REPLY_CANNOT_OPEN_DATACONN;
- }
-
-#if APR_MAJOR_VERSION < 1
- rv = apr_socket_create_ex(&s, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
- fc->data_pool);
-#else
- rv = apr_socket_create(&s, APR_INET, SOCK_STREAM, APR_PROTO_TCP,
- fc->data_pool);
-#endif
-
- if (rv != APR_SUCCESS) {
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "Couldn't create socket");
- return FTP_REPLY_CANNOT_OPEN_DATACONN;
- }
-
- apr_socket_opt_set(s, APR_SO_REUSEADDR, 1);
-
-#if 0
- if ((fsc->active_min != -1) && (fsc->active_min < 1024)) {
- /*
- * Here's the case of low numbered port creation; the only way to
- * accomplish this is either grant the apache user/group the right to
- * bind to low numbered ports, or to have the parent running as root
- * spin off socket fd's through a domain socket to all interested ftp
- * worker processes.
- */
- }
- else
-#endif
-
- rv = apr_socket_bind(s, sa);
-
- if (rv != APR_SUCCESS) {
-#ifdef EACCES
- if (sa->port < 1024 && rv == EACCES)
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
- "Couldn't bind to low numbered port (<1024)");
- else
-#endif
- ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
- "Couldn't bind to socket");
- apr_socket_close(s);
- return FTP_REPLY_CANNOT_OPEN_DATACONN;
- }
-
rv = apr_sockaddr_info_get(&fc->clientsa, ip_addr, APR_INET,
port, 0, fc->data_pool);
@@ -1990,13 +1952,10 @@
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
"Couldn't resolve remote socket address %s"
" (apr or socket stack bug?)", ip_addr);
- apr_socket_close(s);
return FTP_REPLY_CANNOT_OPEN_DATACONN;
}
- fc->response_notes = apr_psprintf(r->pool, FTP_MSG_SUCCESS, r->method);
- fc->csock = s;
- return FTP_REPLY_COMMAND_OK;
+ return get_outbound_port(&sa, r, APR_INET);
}
static int ftp_cmd_prot(request_rec *r, const char *arg)