mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Bug 941: Survive an unexpected number of 227 or 229 FTP responses.
And document the functions a little.
[ From commit 71ff470f2e
in ELinks
0.11.2.GIT. --KON ]
This commit is contained in:
parent
253f55b222
commit
049cc9c6b3
@ -906,12 +906,21 @@ next:
|
|||||||
return file_len;
|
return file_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Connect to the host and port specified by a passive FTP server. */
|
||||||
static int
|
static int
|
||||||
ftp_data_connect(struct connection *conn, int pf, struct sockaddr_storage *sa,
|
ftp_data_connect(struct connection *conn, int pf, struct sockaddr_storage *sa,
|
||||||
int size_of_sockaddr)
|
int size_of_sockaddr)
|
||||||
{
|
{
|
||||||
int fd = socket(pf, SOCK_STREAM, 0);
|
int fd;
|
||||||
|
|
||||||
|
if (conn->data_socket->fd != -1) {
|
||||||
|
/* The server maliciously sent multiple 227 or 229
|
||||||
|
* responses. Do not leak the previous data_socket. */
|
||||||
|
abort_connection(conn, S_FTP_ERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = socket(pf, SOCK_STREAM, 0);
|
||||||
if (fd < 0 || set_nonblocking_fd(fd) < 0) {
|
if (fd < 0 || set_nonblocking_fd(fd) < 0) {
|
||||||
abort_connection(conn, S_FTP_ERROR);
|
abort_connection(conn, S_FTP_ERROR);
|
||||||
return -1;
|
return -1;
|
||||||
@ -1036,6 +1045,21 @@ ftp_retr_file(struct socket *socket, struct read_buffer *rb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conn->data_socket->fd == -1) {
|
||||||
|
/* The passive FTP server did not send a 227 or 229
|
||||||
|
* response. We check this down here, rather than
|
||||||
|
* immediately after getting the response to the PASV
|
||||||
|
* or EPSV command, to make sure that nothing can
|
||||||
|
* close the socket between the check and the
|
||||||
|
* following set_handlers call.
|
||||||
|
*
|
||||||
|
* If we were using active FTP, then
|
||||||
|
* get_ftp_data_socket would have created the
|
||||||
|
* data_socket without waiting for anything from the
|
||||||
|
* server. */
|
||||||
|
abort_connection(conn, S_FTP_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
set_handlers(conn->data_socket->fd, (select_handler_T) ftp_data_accept,
|
set_handlers(conn->data_socket->fd, (select_handler_T) ftp_data_accept,
|
||||||
NULL, NULL, conn);
|
NULL, NULL, conn);
|
||||||
|
|
||||||
@ -1302,12 +1326,26 @@ ftp_process_dirlist(struct cache_entry *cached, off_t *pos,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is the initial read handler for conn->data_socket->fd,
|
||||||
|
* which may be either trying to connect to a passive FTP server or
|
||||||
|
* listening for a connection from an active FTP server. In active
|
||||||
|
* FTP, this function then accepts the connection and replaces
|
||||||
|
* conn->data_socket->fd with the resulting socket. In any case,
|
||||||
|
* this function does not read any data from the FTP server, but
|
||||||
|
* rather hands the socket over to got_something_from_data_connection,
|
||||||
|
* which then does the reads. */
|
||||||
static void
|
static void
|
||||||
ftp_data_accept(struct connection *conn)
|
ftp_data_accept(struct connection *conn)
|
||||||
{
|
{
|
||||||
struct ftp_connection_info *ftp = conn->info;
|
struct ftp_connection_info *ftp = conn->info;
|
||||||
int newsock;
|
int newsock;
|
||||||
|
|
||||||
|
/* Because this function is called only as a read handler of
|
||||||
|
* conn->data_socket->fd, the socket must be valid if we get
|
||||||
|
* here. */
|
||||||
|
assert(conn->data_socket->fd >= 0);
|
||||||
|
if_assert_failed return;
|
||||||
|
|
||||||
set_connection_timeout(conn);
|
set_connection_timeout(conn);
|
||||||
clear_handlers(conn->data_socket->fd);
|
clear_handlers(conn->data_socket->fd);
|
||||||
|
|
||||||
@ -1333,6 +1371,9 @@ ftp_data_accept(struct connection *conn)
|
|||||||
NULL, NULL, conn);
|
NULL, NULL, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A read handler for conn->data_socket->fd. This function reads
|
||||||
|
* data from the FTP server, reformats it to HTML if it's a directory
|
||||||
|
* listing, and adds the result to the cache entry. */
|
||||||
static void
|
static void
|
||||||
got_something_from_data_connection(struct connection *conn)
|
got_something_from_data_connection(struct connection *conn)
|
||||||
{
|
{
|
||||||
@ -1340,6 +1381,12 @@ got_something_from_data_connection(struct connection *conn)
|
|||||||
struct ftp_dir_html_format format;
|
struct ftp_dir_html_format format;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
|
/* Because this function is called only as a read handler of
|
||||||
|
* conn->data_socket->fd, the socket must be valid if we get
|
||||||
|
* here. */
|
||||||
|
assert(conn->data_socket->fd >= 0);
|
||||||
|
if_assert_failed return;
|
||||||
|
|
||||||
/* XXX: This probably belongs rather to connect.c ? */
|
/* XXX: This probably belongs rather to connect.c ? */
|
||||||
|
|
||||||
set_connection_timeout(conn);
|
set_connection_timeout(conn);
|
||||||
|
Loading…
Reference in New Issue
Block a user