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:
parent
58075daf29
commit
7a9842b5f8
@ -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
2
README
@ -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
10
main.c
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
};
|
||||
|
||||
|
87
postlogin.c
87
postlogin.c
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
113
prelogin.c
113
prelogin.c
@ -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)
|
||||
{
|
||||
|
16
privops.c
16
privops.c
@ -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))
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user