1
0
mirror of https://github.com/InfrastructureServices/vsftpd.git synced 2025-04-19 01:24:02 +03:00

Updated to v2.3.0pre1

This commit is contained in:
Dag Wieers 2010-03-18 00:00:00 +01:00
parent 58075daf29
commit 7a9842b5f8
14 changed files with 203 additions and 59 deletions

View File

@ -1213,3 +1213,11 @@ his live server.
At this point: v2.2.2 released!
===============================
- Add extremely simply HTTP support. It's very experimental, ignorant of HTTP
protocol and headers, and likely has all sorts of other issues. The use case
it might satisfy is if you need to serve simple static unathenticated content
with large levels of paranoia.
- Fix port_promiscuous breakage. Report from Soeren <soeren84@fastmail.net>.
(v2.3.0pre1)

2
README
View File

@ -1,4 +1,4 @@
This is vsftpd, version 2.2.2
This is vsftpd, version 2.3.0
Author: Chris Evans
Contact: scarybeasts@gmail.com
Website: http://vsftpd.beasts.org/

10
main.c
View File

@ -45,6 +45,8 @@ main(int argc, const char* argv[])
1, 0, INIT_MYSTR, INIT_MYSTR,
/* Protocol state */
0, 1, INIT_MYSTR, 0, 0,
/* HTTP hacks */
0, INIT_MYSTR,
/* Session state */
0,
/* Userids */
@ -282,6 +284,14 @@ do_sanity_checks(void)
{
die("vsftpd: both local and anonymous access disabled!");
}
if (!tunable_ftp_enable && !tunable_http_enable)
{
die("vsftpd: both FTP and HTTP disabled!");
}
if (tunable_http_enable && !tunable_one_process_model)
{
die("vsftpd: HTTP needs 'one_process_model' for now");
}
}
static void

View File

@ -129,7 +129,7 @@ int
vsf_one_process_get_priv_data_sock(struct vsf_session* p_sess)
{
unsigned short port = vsf_sysutil_sockaddr_get_port(p_sess->p_port_sockaddr);
return vsf_privop_get_ftp_port_sock(p_sess, port);
return vsf_privop_get_ftp_port_sock(p_sess, port, 1);
}
void

View File

@ -103,6 +103,8 @@ parseconf_bool_array[] =
{ "require_ssl_reuse", &tunable_require_ssl_reuse },
{ "isolate", &tunable_isolate },
{ "isolate_network", &tunable_isolate_network },
{ "ftp_enable", &tunable_ftp_enable },
{ "http_enable", &tunable_http_enable },
{ 0, 0 }
};

View File

@ -32,7 +32,7 @@
static void handle_pwd(struct vsf_session* p_sess);
static void handle_cwd(struct vsf_session* p_sess);
static void handle_pasv(struct vsf_session* p_sess, int is_epsv);
static void handle_retr(struct vsf_session* p_sess);
static void handle_retr(struct vsf_session* p_sess, int is_http);
static void handle_cdup(struct vsf_session* p_sess);
static void handle_list(struct vsf_session* p_sess);
static void handle_type(struct vsf_session* p_sess);
@ -60,6 +60,7 @@ static void handle_stat(struct vsf_session* p_sess);
static void handle_stat_file(struct vsf_session* p_sess);
static void handle_logged_in_user(struct vsf_session* p_sess);
static void handle_logged_in_pass(struct vsf_session* p_sess);
static void handle_http(struct vsf_session* p_sess);
static int pasv_active(struct vsf_session* p_sess);
static int port_active(struct vsf_session* p_sess);
@ -93,6 +94,12 @@ process_post_login(struct vsf_session* p_sess)
vsf_sysutil_set_umask(tunable_local_umask);
p_sess->bw_rate_max = tunable_local_max_rate;
}
if (p_sess->is_http)
{
handle_http(p_sess);
bug("should not be reached");
}
if (tunable_async_abor_enable)
{
vsf_sysutil_install_sighandler(kVSFSysUtilSigURG, handle_sigurg, p_sess, 0);
@ -101,6 +108,7 @@ process_post_login(struct vsf_session* p_sess)
/* Handle any login message */
vsf_banner_dir_changed(p_sess, FTP_LOGINOK);
vsf_cmdio_write(p_sess, FTP_LOGINOK, "Login successful.");
while(1)
{
int cmd_ok = 1;
@ -204,7 +212,7 @@ process_post_login(struct vsf_session* p_sess)
else if (tunable_download_enable &&
str_equal_text(&p_sess->ftp_cmd_str, "RETR"))
{
handle_retr(p_sess);
handle_retr(p_sess, 0);
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "NOOP"))
{
@ -621,7 +629,7 @@ handle_pasv(struct vsf_session* p_sess, int is_epsv)
}
static void
handle_retr(struct vsf_session* p_sess)
handle_retr(struct vsf_session* p_sess, int is_http)
{
static struct mystr s_mark_str;
static struct vsf_sysutil_statbuf* s_p_statbuf;
@ -631,7 +639,7 @@ handle_retr(struct vsf_session* p_sess)
int is_ascii = 0;
filesize_t offset = p_sess->restart_pos;
p_sess->restart_pos = 0;
if (!data_transfer_checks_ok(p_sess))
if (!is_http && !data_transfer_checks_ok(p_sess))
{
return;
}
@ -708,14 +716,23 @@ handle_retr(struct vsf_session* p_sess)
str_append_filesize_t(&s_mark_str,
vsf_sysutil_statbuf_get_size(s_p_statbuf));
str_append_text(&s_mark_str, " bytes).");
remote_fd = get_remote_transfer_fd(p_sess, str_getbuf(&s_mark_str));
if (vsf_sysutil_retval_is_error(remote_fd))
if (is_http)
{
goto port_pasv_cleanup_out;
remote_fd = VSFTP_COMMAND_FD;
}
else
{
remote_fd = get_remote_transfer_fd(p_sess, str_getbuf(&s_mark_str));
if (vsf_sysutil_retval_is_error(remote_fd))
{
goto port_pasv_cleanup_out;
}
}
trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd,
opened_file, 0, is_ascii);
if (vsf_ftpdataio_dispose_transfer_fd(p_sess) != 1 && trans_ret.retval == 0)
if (!is_http &&
vsf_ftpdataio_dispose_transfer_fd(p_sess) != 1 &&
trans_ret.retval == 0)
{
trans_ret.retval = -2;
}
@ -725,6 +742,10 @@ handle_retr(struct vsf_session* p_sess)
{
vsf_log_do_log(p_sess, 1);
}
if (is_http)
{
goto file_close_out;
}
/* Emit status message _after_ blocking dispose call to avoid buggy FTP
* clients truncating the transfer.
*/
@ -1898,3 +1919,53 @@ static void handle_logged_in_pass(struct vsf_session* p_sess)
{
vsf_cmdio_write(p_sess, FTP_LOGINOK, "Already logged in.");
}
static void
handle_http(struct vsf_session* p_sess)
{
/* Warning: Doesn't respect cmds_allowed etc. because there is currently only
* one command (GET)!
* HTTP likely doesn't respect other important FTP options. I don't think
* logging works.
*/
if (!tunable_download_enable)
{
bug("HTTP needs download - fix your config");
}
/* Eat the HTTP headers, which we don't care about. */
do
{
vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
&p_sess->ftp_arg_str, 1);
}
while (!str_isempty(&p_sess->ftp_cmd_str) ||
!str_isempty(&p_sess->ftp_arg_str));
vsf_cmdio_write_raw(p_sess, "HTTP/1.1 200 OK\r\n");
vsf_cmdio_write_raw(p_sess, "Server: vsftpd\r\n");
vsf_cmdio_write_raw(p_sess, "Connection: close\r\n");
vsf_cmdio_write_raw(p_sess, "X-Frame-Options: SAMEORIGIN\r\n");
vsf_cmdio_write_raw(p_sess, "X-Content-Type-Options: nosniff\r\n");
/* Split the path from the HTTP/1.x */
str_split_char(&p_sess->http_get_arg, &p_sess->ftp_arg_str, ' ');
str_copy(&p_sess->ftp_arg_str, &p_sess->http_get_arg);
str_split_char(&p_sess->http_get_arg, &p_sess->ftp_cmd_str, '.');
str_upper(&p_sess->ftp_cmd_str);
if (str_equal_text(&p_sess->ftp_cmd_str, "HTML") ||
str_equal_text(&p_sess->ftp_cmd_str, "HTM"))
{
vsf_cmdio_write_raw(p_sess, "Content-Type: text/html\r\n");
}
else
{
vsf_cmdio_write_raw(p_sess, "Content-Type: dunno\r\n");
}
vsf_cmdio_write_raw(p_sess, "\r\n");
p_sess->is_ascii = 0;
p_sess->restart_pos = 0;
handle_retr(p_sess, 1);
if (vsf_log_entry_pending(p_sess))
{
vsf_log_do_log(p_sess, 0);
}
vsf_sysutil_exit(0);
}

View File

@ -125,7 +125,7 @@ static void
cmd_process_get_data_sock(struct vsf_session* p_sess)
{
unsigned short port = (unsigned short) priv_sock_get_int(p_sess->parent_fd);
int sock_fd = vsf_privop_get_ftp_port_sock(p_sess, port);
int sock_fd = vsf_privop_get_ftp_port_sock(p_sess, port, 0);
if (sock_fd == -1)
{
priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_BAD);

View File

@ -31,6 +31,7 @@ static void emit_greeting(struct vsf_session* p_sess);
static void parse_username_password(struct vsf_session* p_sess);
static void handle_user_command(struct vsf_session* p_sess);
static void handle_pass_command(struct vsf_session* p_sess);
static void handle_get(struct vsf_session* p_sess);
static void check_login_delay();
static void check_login_fails(struct vsf_session* p_sess);
@ -54,7 +55,10 @@ init_connection(struct vsf_session* p_sess)
{
ssl_control_handshake(p_sess);
}
emit_greeting(p_sess);
if (tunable_ftp_enable)
{
emit_greeting(p_sess);
}
parse_username_password(p_sess);
}
@ -117,53 +121,80 @@ parse_username_password(struct vsf_session* p_sess)
{
vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
&p_sess->ftp_arg_str, 1);
if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))
if (tunable_ftp_enable)
{
handle_user_command(p_sess);
if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))
{
handle_user_command(p_sess);
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS"))
{
handle_pass_command(p_sess);
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
{
vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye.");
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))
{
handle_feat(p_sess);
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "OPTS"))
{
handle_opts(p_sess);
}
else if (tunable_ssl_enable &&
str_equal_text(&p_sess->ftp_cmd_str, "AUTH") &&
!p_sess->control_use_ssl)
{
handle_auth(p_sess);
}
else if (tunable_ssl_enable &&
str_equal_text(&p_sess->ftp_cmd_str, "PBSZ"))
{
handle_pbsz(p_sess);
}
else if (tunable_ssl_enable &&
str_equal_text(&p_sess->ftp_cmd_str, "PROT"))
{
handle_prot(p_sess);
}
else if (str_isempty(&p_sess->ftp_cmd_str) &&
str_isempty(&p_sess->ftp_arg_str))
{
/* Deliberately ignore to avoid NAT device bugs, as per ProFTPd. */
}
else
{
vsf_cmdio_write(p_sess, FTP_LOGINERR,
"Please login with USER and PASS.");
}
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS"))
else if (tunable_http_enable)
{
handle_pass_command(p_sess);
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
{
vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye.");
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))
{
handle_feat(p_sess);
}
else if (str_equal_text(&p_sess->ftp_cmd_str, "OPTS"))
{
handle_opts(p_sess);
}
else if (tunable_ssl_enable &&
str_equal_text(&p_sess->ftp_cmd_str, "AUTH") &&
!p_sess->control_use_ssl)
{
handle_auth(p_sess);
}
else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PBSZ"))
{
handle_pbsz(p_sess);
}
else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PROT"))
{
handle_prot(p_sess);
}
else if (str_isempty(&p_sess->ftp_cmd_str) &&
str_isempty(&p_sess->ftp_arg_str))
{
/* Deliberately ignore to avoid NAT device bugs. ProFTPd does the same. */
}
else
{
vsf_cmdio_write(p_sess, FTP_LOGINERR,
"Please login with USER and PASS.");
if (str_equal_text(&p_sess->ftp_cmd_str, "GET"))
{
handle_get(p_sess);
}
else
{
vsf_cmdio_write(p_sess, FTP_LOGINERR, "Bad HTTP verb.");
}
vsf_sysutil_exit(0);
}
}
}
static void
handle_get(struct vsf_session* p_sess)
{
p_sess->is_http = 1;
str_copy(&p_sess->http_get_arg, &p_sess->ftp_arg_str);
str_alloc_text(&p_sess->user_str, "FTP");
str_alloc_text(&p_sess->ftp_arg_str, "<http>");
handle_pass_command(p_sess);
}
static void
handle_user_command(struct vsf_session* p_sess)
{

View File

@ -33,9 +33,11 @@ static enum EVSFPrivopLoginResult handle_login(
int
vsf_privop_get_ftp_port_sock(struct vsf_session* p_sess,
unsigned short remote_port)
unsigned short remote_port,
int use_port_sockaddr)
{
static struct vsf_sysutil_sockaddr* p_sockaddr;
const struct vsf_sysutil_sockaddr* p_connect_to;
int retval;
int i;
int s = vsf_sysutil_get_ipsock(p_sess->p_local_addr);
@ -71,8 +73,16 @@ vsf_privop_get_ftp_port_sock(struct vsf_session* p_sess,
sleep_for += 1.0;
vsf_sysutil_sleep(sleep_for);
}
vsf_sysutil_sockaddr_set_port(p_sess->p_remote_addr, remote_port);
retval = vsf_sysutil_connect_timeout(s, p_sess->p_remote_addr,
if (use_port_sockaddr)
{
p_connect_to = p_sess->p_port_sockaddr;
}
else
{
vsf_sysutil_sockaddr_set_port(p_sess->p_remote_addr, remote_port);
p_connect_to = p_sess->p_remote_addr;
}
retval = vsf_sysutil_connect_timeout(s, p_connect_to,
tunable_connect_timeout);
if (vsf_sysutil_retval_is_error(retval))
{

View File

@ -9,8 +9,9 @@ struct vsf_session;
* Return a network socket potentially bound to a privileged port (less than
* 1024) and connected to the remote.
* PARAMETERS
* p_sess - the current session object
* remote_port - the remote port to connect to
* p_sess - the current session object
* remote_port - the remote port to connect to
* use_port_sockaddr - true if we should use the specific sockaddr for connect
* RETURNS
* A file descriptor which is a socket bound to the privileged port, and
* connected to the remote on the specified port.
@ -18,7 +19,8 @@ struct vsf_session;
* Returns -1 if the bind() worked but the connect() was not possible.
*/
int vsf_privop_get_ftp_port_sock(struct vsf_session* p_sess,
unsigned short remote_port);
unsigned short remote_port,
int use_port_sockaddr);
/* vsf_privop_pasv_cleanup()
* PURPOSE

View File

@ -44,6 +44,10 @@ struct vsf_session
int abor_received;
int epsv_all;
/* HTTP hacks */
int is_http;
struct mystr http_get_arg;
/* Details of FTP session state */
struct mystr_list* p_visited_dir_list;

View File

@ -84,6 +84,8 @@ int tunable_sandbox;
int tunable_require_ssl_reuse;
int tunable_isolate;
int tunable_isolate_network;
int tunable_ftp_enable;
int tunable_http_enable;
unsigned int tunable_accept_timeout;
unsigned int tunable_connect_timeout;
@ -220,6 +222,8 @@ tunables_load_defaults()
tunable_require_ssl_reuse = 1;
tunable_isolate = 1;
tunable_isolate_network = 1;
tunable_ftp_enable = 1;
tunable_http_enable = 0;
tunable_accept_timeout = 60;
tunable_connect_timeout = 60;

View File

@ -85,6 +85,8 @@ extern int tunable_sandbox; /* Deploy ptrace sandbox */
extern int tunable_require_ssl_reuse; /* Require re-used data conn */
extern int tunable_isolate; /* Use container clone() flags */
extern int tunable_isolate_network; /* Use CLONE_NEWNET */
extern int tunable_ftp_enable; /* Allow FTP protocol */
extern int tunable_http_enable; /* Allow HTTP protocol */
/* Integer/numeric defines */
extern unsigned int tunable_accept_timeout;

View File

@ -1,7 +1,7 @@
#ifndef VSF_VERSION_H
#define VSF_VERSION_H
#define VSF_VERSION "2.2.2"
#define VSF_VERSION "2.3.0"
#endif /* VSF_VERSION_H */