mirror of
https://github.com/InfrastructureServices/vsftpd.git
synced 2025-04-19 01:24:02 +03:00
Updated to v2.2.0pre1
This commit is contained in:
parent
3f1020a66e
commit
b93ee04314
@ -1,2 +1,3 @@
|
||||
Everything within this tar archive is Copyright (c) Chris Evans.
|
||||
Everything within this tar archive is Copyright (c) Chris Evans, except
|
||||
where otherwise noted in individual files.
|
||||
|
||||
|
18
Changelog
18
Changelog
@ -1132,3 +1132,21 @@ At this point: v2.1.1 released!
|
||||
At this point: v2.1.2 released!
|
||||
===============================
|
||||
|
||||
- Fix compile on systems with no RLIMIT_NPROC, oops.
|
||||
- Change some unsigned int to socklen_t's to avoid warnings on various
|
||||
platforms, e.g. AIX.
|
||||
- Add some syscall constants to ptracesandbox.c to fix the build on systems
|
||||
with 2.4 kernel headers.
|
||||
- Look for libs in /lib64 and /usr/lib64 too (Fixes Fedora 11 x86_64 compile).
|
||||
- Fix EACCES mapping, thanks Solar Designer <solar@openwall.com>.
|
||||
- Dont emit a bogus "OOPS: " message upon a QUIT, report from Solar Designer
|
||||
<solar@openwall.com>.
|
||||
- Tweak example vsftpd.conf to add commented out chroot_local_user=YES,
|
||||
from Ivan I. Grushin <mcgru@intrice.ru>.
|
||||
- Where available, use CLONE_NEWNET to isolate the untrusted processes so that
|
||||
they can't do arbitrary connect() and instead have to ask the privileged
|
||||
process for sockets. Moderate code disturbance - hope for no breakage :-/
|
||||
- Disable implicit activation of one_process_model so that an anonymous setup
|
||||
can benefit from the no-network isolation of the unprivileged process (where
|
||||
available).
|
||||
(vsftpd-2.2.0pre1)
|
||||
|
2
README
2
README
@ -1,4 +1,4 @@
|
||||
This is vsftpd, version 2.1.2
|
||||
This is vsftpd, version 2.2.0
|
||||
Author: Chris Evans
|
||||
Contact: scarybeasts@gmail.com
|
||||
Website: http://vsftpd.beasts.org/
|
||||
|
@ -83,6 +83,7 @@ vsf_cmdio_write_exit(struct vsf_session* p_sess, int status, const char* p_text)
|
||||
*/
|
||||
vsf_sysutil_shutdown_read_failok(VSFTP_COMMAND_FD);
|
||||
ftp_write_text_common(p_sess, status, p_text, 1, ' ');
|
||||
vsf_sysutil_shutdown_failok(VSFTP_COMMAND_FD);
|
||||
vsf_sysutil_exit(0);
|
||||
}
|
||||
|
||||
|
60
ftpdataio.c
60
ftpdataio.c
@ -98,32 +98,27 @@ int
|
||||
vsf_ftpdataio_get_pasv_fd(struct vsf_session* p_sess)
|
||||
{
|
||||
int remote_fd;
|
||||
struct vsf_sysutil_sockaddr* p_accept_addr = 0;
|
||||
vsf_sysutil_sockaddr_alloc(&p_accept_addr);
|
||||
remote_fd = vsf_sysutil_accept_timeout(p_sess->pasv_listen_fd, p_accept_addr,
|
||||
tunable_accept_timeout);
|
||||
if (vsf_sysutil_retval_is_error(remote_fd))
|
||||
if (tunable_one_process_model)
|
||||
{
|
||||
remote_fd = vsf_one_process_get_pasv_fd(p_sess);
|
||||
}
|
||||
else
|
||||
{
|
||||
remote_fd = vsf_two_process_get_pasv_fd(p_sess);
|
||||
}
|
||||
/* Yes, yes, hardcoded bad I know. */
|
||||
if (remote_fd == -1)
|
||||
{
|
||||
vsf_cmdio_write(p_sess, FTP_BADSENDCONN,
|
||||
"Failed to establish connection.");
|
||||
vsf_sysutil_sockaddr_clear(&p_accept_addr);
|
||||
return remote_fd;
|
||||
}
|
||||
/* SECURITY:
|
||||
* Reject the connection if it wasn't from the same IP as the
|
||||
* control connection.
|
||||
*/
|
||||
if (!tunable_pasv_promiscuous)
|
||||
else if (remote_fd == -2)
|
||||
{
|
||||
if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_accept_addr))
|
||||
{
|
||||
vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Security: Bad IP connecting.");
|
||||
vsf_sysutil_close(remote_fd);
|
||||
vsf_sysutil_sockaddr_clear(&p_accept_addr);
|
||||
return -1;
|
||||
}
|
||||
vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Security: Bad IP connecting.");
|
||||
vsf_sysutil_close(remote_fd);
|
||||
return -1;
|
||||
}
|
||||
vsf_sysutil_sockaddr_clear(&p_accept_addr);
|
||||
init_data_sock_params(p_sess, remote_fd);
|
||||
return remote_fd;
|
||||
}
|
||||
@ -131,38 +126,19 @@ vsf_ftpdataio_get_pasv_fd(struct vsf_session* p_sess)
|
||||
int
|
||||
vsf_ftpdataio_get_port_fd(struct vsf_session* p_sess)
|
||||
{
|
||||
int retval;
|
||||
int remote_fd;
|
||||
if (tunable_connect_from_port_20)
|
||||
if (tunable_one_process_model || tunable_port_promiscuous)
|
||||
{
|
||||
if (tunable_one_process_model)
|
||||
{
|
||||
remote_fd = vsf_one_process_get_priv_data_sock(p_sess);
|
||||
}
|
||||
else
|
||||
{
|
||||
remote_fd = vsf_two_process_get_priv_data_sock(p_sess);
|
||||
}
|
||||
remote_fd = vsf_one_process_get_priv_data_sock(p_sess);
|
||||
}
|
||||
else
|
||||
{
|
||||
static struct vsf_sysutil_sockaddr* s_p_addr;
|
||||
remote_fd = vsf_sysutil_get_ipsock(p_sess->p_local_addr);
|
||||
vsf_sysutil_sockaddr_clone(&s_p_addr, p_sess->p_local_addr);
|
||||
vsf_sysutil_sockaddr_set_port(s_p_addr, 0);
|
||||
retval = vsf_sysutil_bind(remote_fd, s_p_addr);
|
||||
if (retval != 0)
|
||||
{
|
||||
die("vsf_sysutil_bind");
|
||||
}
|
||||
remote_fd = vsf_two_process_get_priv_data_sock(p_sess);
|
||||
}
|
||||
retval = vsf_sysutil_connect_timeout(remote_fd, p_sess->p_port_sockaddr,
|
||||
tunable_connect_timeout);
|
||||
if (vsf_sysutil_retval_is_error(retval))
|
||||
if (vsf_sysutil_retval_is_error(remote_fd))
|
||||
{
|
||||
vsf_cmdio_write(p_sess, FTP_BADSENDCONN,
|
||||
"Failed to establish connection.");
|
||||
vsf_sysutil_close(remote_fd);
|
||||
return -1;
|
||||
}
|
||||
init_data_sock_params(p_sess, remote_fd);
|
||||
|
8
main.c
8
main.c
@ -214,14 +214,6 @@ main(int argc, const char* argv[])
|
||||
die2("cannot open email passwords file:", tunable_email_password_file);
|
||||
}
|
||||
}
|
||||
/* Special case - can force one process model if we've got a setup
|
||||
* needing _no_ privs
|
||||
*/
|
||||
if (!tunable_local_enable && !tunable_connect_from_port_20 &&
|
||||
!tunable_chown_uploads)
|
||||
{
|
||||
tunable_one_process_model = 1;
|
||||
}
|
||||
if (tunable_run_as_launching_user)
|
||||
{
|
||||
tunable_one_process_model = 1;
|
||||
|
27
oneprocess.c
27
oneprocess.c
@ -128,7 +128,32 @@ vsf_one_process_login(struct vsf_session* p_sess,
|
||||
int
|
||||
vsf_one_process_get_priv_data_sock(struct vsf_session* p_sess)
|
||||
{
|
||||
return vsf_privop_get_ftp_port_sock(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);
|
||||
}
|
||||
|
||||
void
|
||||
vsf_one_process_pasv_cleanup(struct vsf_session* p_sess)
|
||||
{
|
||||
vsf_privop_pasv_cleanup(p_sess);
|
||||
}
|
||||
|
||||
int
|
||||
vsf_one_process_pasv_active(struct vsf_session* p_sess)
|
||||
{
|
||||
return vsf_privop_pasv_active(p_sess);
|
||||
}
|
||||
|
||||
unsigned short
|
||||
vsf_one_process_listen(struct vsf_session* p_sess)
|
||||
{
|
||||
return vsf_privop_pasv_listen(p_sess);
|
||||
}
|
||||
|
||||
int
|
||||
vsf_one_process_get_pasv_fd(struct vsf_session* p_sess)
|
||||
{
|
||||
return vsf_privop_accept_pasv(p_sess);
|
||||
}
|
||||
|
||||
void
|
||||
|
38
oneprocess.h
38
oneprocess.h
@ -34,6 +34,44 @@ void vsf_one_process_login(struct vsf_session* p_sess,
|
||||
*/
|
||||
int vsf_one_process_get_priv_data_sock(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_one_process_pasv_cleanup()
|
||||
* PURPOSE
|
||||
* Clean up any listening passive socket.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
*/
|
||||
void vsf_one_process_pasv_cleanup(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_one_process_pasv_active()
|
||||
* PURPOSE
|
||||
* Determine whether a listening pasv socket is active.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* 1 if active, 0 if not.
|
||||
*/
|
||||
int vsf_one_process_pasv_active(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_one_process_listen()
|
||||
* PURPOSE
|
||||
* Start listening for an incoming connection.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* The port we listened on.
|
||||
*/
|
||||
unsigned short vsf_one_process_listen(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_one_process_get_pasv_fd()
|
||||
* PURPOSE
|
||||
* Accept an incoming connection.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* The file descriptor for the incoming connection.
|
||||
*/
|
||||
int vsf_one_process_get_pasv_fd(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_one_process_chown_upload()
|
||||
* PURPOSE
|
||||
* Change ownership of an uploaded file using the one process model.
|
||||
|
84
postlogin.c
84
postlogin.c
@ -172,8 +172,7 @@ process_post_login(struct vsf_session* p_sess)
|
||||
}
|
||||
else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
|
||||
{
|
||||
vsf_cmdio_write(p_sess, FTP_GOODBYE, "Goodbye.");
|
||||
vsf_sysutil_exit(0);
|
||||
vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye.");
|
||||
}
|
||||
else if (str_equal_text(&p_sess->ftp_cmd_str, "PWD") ||
|
||||
str_equal_text(&p_sess->ftp_cmd_str, "XPWD"))
|
||||
@ -503,9 +502,16 @@ static int
|
||||
pasv_active(struct vsf_session* p_sess)
|
||||
{
|
||||
int ret = 0;
|
||||
if (p_sess->pasv_listen_fd != -1)
|
||||
if (tunable_one_process_model)
|
||||
{
|
||||
ret = vsf_one_process_pasv_active(p_sess);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = vsf_two_process_pasv_active(p_sess);
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
ret = 1;
|
||||
if (port_active(p_sess))
|
||||
{
|
||||
bug("pasv and port both active");
|
||||
@ -523,23 +529,22 @@ port_cleanup(struct vsf_session* p_sess)
|
||||
static void
|
||||
pasv_cleanup(struct vsf_session* p_sess)
|
||||
{
|
||||
if (p_sess->pasv_listen_fd != -1)
|
||||
if (tunable_one_process_model)
|
||||
{
|
||||
vsf_sysutil_close(p_sess->pasv_listen_fd);
|
||||
p_sess->pasv_listen_fd = -1;
|
||||
vsf_one_process_pasv_cleanup(p_sess);
|
||||
}
|
||||
else
|
||||
{
|
||||
vsf_two_process_pasv_cleanup(p_sess);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_pasv(struct vsf_session* p_sess, int is_epsv)
|
||||
{
|
||||
unsigned short the_port;
|
||||
static struct mystr s_pasv_res_str;
|
||||
static struct vsf_sysutil_sockaddr* s_p_sockaddr;
|
||||
int bind_retries = 10;
|
||||
unsigned short the_port = 0;
|
||||
/* IPPORT_RESERVED */
|
||||
unsigned short min_port = 1024;
|
||||
unsigned short max_port = 65535;
|
||||
int is_ipv6 = vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr);
|
||||
if (is_epsv && !str_isempty(&p_sess->ftp_arg_str))
|
||||
{
|
||||
@ -560,58 +565,13 @@ handle_pasv(struct vsf_session* p_sess, int is_epsv)
|
||||
}
|
||||
pasv_cleanup(p_sess);
|
||||
port_cleanup(p_sess);
|
||||
if (is_ipv6)
|
||||
if (tunable_one_process_model)
|
||||
{
|
||||
p_sess->pasv_listen_fd = vsf_sysutil_get_ipv6_sock();
|
||||
the_port = vsf_one_process_listen(p_sess);
|
||||
}
|
||||
else
|
||||
{
|
||||
p_sess->pasv_listen_fd = vsf_sysutil_get_ipv4_sock();
|
||||
}
|
||||
vsf_sysutil_activate_reuseaddr(p_sess->pasv_listen_fd);
|
||||
|
||||
if (tunable_pasv_min_port > min_port && tunable_pasv_min_port <= max_port)
|
||||
{
|
||||
min_port = tunable_pasv_min_port;
|
||||
}
|
||||
if (tunable_pasv_max_port >= min_port && tunable_pasv_max_port < max_port)
|
||||
{
|
||||
max_port = tunable_pasv_max_port;
|
||||
}
|
||||
|
||||
while (--bind_retries)
|
||||
{
|
||||
int retval;
|
||||
double scaled_port;
|
||||
the_port = vsf_sysutil_get_random_byte();
|
||||
the_port <<= 8;
|
||||
the_port |= vsf_sysutil_get_random_byte();
|
||||
scaled_port = (double) min_port;
|
||||
scaled_port += ((double) the_port / (double) 65536) *
|
||||
((double) max_port - min_port + 1);
|
||||
the_port = (unsigned short) scaled_port;
|
||||
vsf_sysutil_sockaddr_clone(&s_p_sockaddr, p_sess->p_local_addr);
|
||||
vsf_sysutil_sockaddr_set_port(s_p_sockaddr, the_port);
|
||||
retval = vsf_sysutil_bind(p_sess->pasv_listen_fd, s_p_sockaddr);
|
||||
if (!vsf_sysutil_retval_is_error(retval))
|
||||
{
|
||||
retval = vsf_sysutil_listen(p_sess->pasv_listen_fd, 1);
|
||||
if (!vsf_sysutil_retval_is_error(retval))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* SELinux systems can give you an inopportune EACCES, it seems. */
|
||||
if (vsf_sysutil_get_error() == kVSFSysUtilErrADDRINUSE ||
|
||||
vsf_sysutil_get_error() == kVSFSysUtilErrACCES)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
die("vsf_sysutil_bind / listen");
|
||||
}
|
||||
if (!bind_retries)
|
||||
{
|
||||
die("vsf_sysutil_bind");
|
||||
the_port = vsf_two_process_listen(p_sess);
|
||||
}
|
||||
if (is_epsv)
|
||||
{
|
||||
@ -629,6 +589,10 @@ handle_pasv(struct vsf_session* p_sess, int is_epsv)
|
||||
die("invalid pasv_address");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vsf_sysutil_sockaddr_clone(&s_p_sockaddr, p_sess->p_local_addr);
|
||||
}
|
||||
str_alloc_text(&s_pasv_res_str, "Entering Passive Mode (");
|
||||
if (!is_ipv6)
|
||||
{
|
||||
|
@ -26,6 +26,10 @@ static void minimize_privilege(struct vsf_session* p_sess);
|
||||
static void process_post_login_req(struct vsf_session* p_sess);
|
||||
static void cmd_process_chown(struct vsf_session* p_sess);
|
||||
static void cmd_process_get_data_sock(struct vsf_session* p_sess);
|
||||
static void cmd_process_pasv_cleanup(struct vsf_session* p_sess);
|
||||
static void cmd_process_pasv_active(struct vsf_session* p_sess);
|
||||
static void cmd_process_pasv_listen(struct vsf_session* p_sess);
|
||||
static void cmd_process_pasv_accept(struct vsf_session* p_sess);
|
||||
|
||||
void
|
||||
vsf_priv_parent_postlogin(struct vsf_session* p_sess)
|
||||
@ -48,10 +52,26 @@ process_post_login_req(struct vsf_session* p_sess)
|
||||
{
|
||||
cmd_process_chown(p_sess);
|
||||
}
|
||||
else if (tunable_connect_from_port_20 && cmd == PRIV_SOCK_GET_DATA_SOCK)
|
||||
else if (cmd == PRIV_SOCK_GET_DATA_SOCK)
|
||||
{
|
||||
cmd_process_get_data_sock(p_sess);
|
||||
}
|
||||
else if (cmd == PRIV_SOCK_PASV_CLEANUP)
|
||||
{
|
||||
cmd_process_pasv_cleanup(p_sess);
|
||||
}
|
||||
else if (cmd == PRIV_SOCK_PASV_ACTIVE)
|
||||
{
|
||||
cmd_process_pasv_active(p_sess);
|
||||
}
|
||||
else if (cmd == PRIV_SOCK_PASV_LISTEN)
|
||||
{
|
||||
cmd_process_pasv_listen(p_sess);
|
||||
}
|
||||
else if (cmd == PRIV_SOCK_PASV_ACCEPT)
|
||||
{
|
||||
cmd_process_pasv_accept(p_sess);
|
||||
}
|
||||
else
|
||||
{
|
||||
die("bad request in process_post_login_req");
|
||||
@ -104,9 +124,44 @@ cmd_process_chown(struct vsf_session* p_sess)
|
||||
static void
|
||||
cmd_process_get_data_sock(struct vsf_session* p_sess)
|
||||
{
|
||||
int sock_fd = vsf_privop_get_ftp_port_sock(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);
|
||||
if (sock_fd == -1)
|
||||
{
|
||||
priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_BAD);
|
||||
return;
|
||||
}
|
||||
priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
|
||||
priv_sock_send_fd(p_sess->parent_fd, sock_fd);
|
||||
vsf_sysutil_close(sock_fd);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_process_pasv_cleanup(struct vsf_session* p_sess)
|
||||
{
|
||||
vsf_privop_pasv_cleanup(p_sess);
|
||||
priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_process_pasv_active(struct vsf_session* p_sess)
|
||||
{
|
||||
int active = vsf_privop_pasv_active(p_sess);
|
||||
priv_sock_send_int(p_sess->parent_fd, active);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_process_pasv_listen(struct vsf_session* p_sess)
|
||||
{
|
||||
unsigned short port = vsf_privop_pasv_listen(p_sess);
|
||||
priv_sock_send_int(p_sess->parent_fd, port);
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_process_pasv_accept(struct vsf_session* p_sess)
|
||||
{
|
||||
int fd = vsf_privop_accept_pasv(p_sess);
|
||||
priv_sock_send_fd(p_sess->parent_fd, fd);
|
||||
vsf_sysutil_close(fd);
|
||||
}
|
||||
|
||||
|
@ -127,8 +127,7 @@ parse_username_password(struct vsf_session* p_sess)
|
||||
}
|
||||
else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
|
||||
{
|
||||
vsf_cmdio_write(p_sess, FTP_GOODBYE, "Goodbye.");
|
||||
vsf_sysutil_exit(0);
|
||||
vsf_cmdio_write_exit(p_sess, FTP_GOODBYE, "Goodbye.");
|
||||
}
|
||||
else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))
|
||||
{
|
||||
|
140
privops.c
140
privops.c
@ -32,12 +32,22 @@ static enum EVSFPrivopLoginResult handle_login(
|
||||
const struct mystr* p_pass_str);
|
||||
|
||||
int
|
||||
vsf_privop_get_ftp_port_sock(struct vsf_session* p_sess)
|
||||
vsf_privop_get_ftp_port_sock(struct vsf_session* p_sess,
|
||||
unsigned short remote_port)
|
||||
{
|
||||
static struct vsf_sysutil_sockaddr* p_sockaddr;
|
||||
int retval;
|
||||
int i;
|
||||
int s = vsf_sysutil_get_ipsock(p_sess->p_local_addr);
|
||||
int port = 0;
|
||||
if (vsf_sysutil_is_port_reserved(remote_port))
|
||||
{
|
||||
die("Illegal port request");
|
||||
}
|
||||
if (tunable_connect_from_port_20)
|
||||
{
|
||||
port = tunable_ftp_data_port;
|
||||
}
|
||||
vsf_sysutil_activate_reuseaddr(s);
|
||||
/* A report of failure here on Solaris, presumably buggy address reuse
|
||||
* support? We'll retry.
|
||||
@ -46,11 +56,11 @@ vsf_privop_get_ftp_port_sock(struct vsf_session* p_sess)
|
||||
{
|
||||
double sleep_for;
|
||||
vsf_sysutil_sockaddr_clone(&p_sockaddr, p_sess->p_local_addr);
|
||||
vsf_sysutil_sockaddr_set_port(p_sockaddr, tunable_ftp_data_port);
|
||||
vsf_sysutil_sockaddr_set_port(p_sockaddr, port);
|
||||
retval = vsf_sysutil_bind(s, p_sockaddr);
|
||||
if (retval == 0)
|
||||
{
|
||||
return s;
|
||||
break;
|
||||
}
|
||||
if (vsf_sysutil_get_error() != kVSFSysUtilErrADDRINUSE || i == 1)
|
||||
{
|
||||
@ -61,9 +71,133 @@ 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,
|
||||
tunable_connect_timeout);
|
||||
if (vsf_sysutil_retval_is_error(retval))
|
||||
{
|
||||
vsf_sysutil_close(s);
|
||||
s = -1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void
|
||||
vsf_privop_pasv_cleanup(struct vsf_session* p_sess)
|
||||
{
|
||||
if (p_sess->pasv_listen_fd != -1)
|
||||
{
|
||||
vsf_sysutil_close(p_sess->pasv_listen_fd);
|
||||
p_sess->pasv_listen_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
vsf_privop_pasv_active(struct vsf_session* p_sess)
|
||||
{
|
||||
if (p_sess->pasv_listen_fd != -1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned short
|
||||
vsf_privop_pasv_listen(struct vsf_session* p_sess)
|
||||
{
|
||||
static struct vsf_sysutil_sockaddr* s_p_sockaddr;
|
||||
int bind_retries = 10;
|
||||
unsigned short the_port = 0;
|
||||
/* IPPORT_RESERVED */
|
||||
unsigned short min_port = 1024;
|
||||
unsigned short max_port = 65535;
|
||||
int is_ipv6 = vsf_sysutil_sockaddr_is_ipv6(p_sess->p_local_addr);
|
||||
if (is_ipv6)
|
||||
{
|
||||
p_sess->pasv_listen_fd = vsf_sysutil_get_ipv6_sock();
|
||||
}
|
||||
else
|
||||
{
|
||||
p_sess->pasv_listen_fd = vsf_sysutil_get_ipv4_sock();
|
||||
}
|
||||
vsf_sysutil_activate_reuseaddr(p_sess->pasv_listen_fd);
|
||||
|
||||
if (tunable_pasv_min_port > min_port && tunable_pasv_min_port <= max_port)
|
||||
{
|
||||
min_port = tunable_pasv_min_port;
|
||||
}
|
||||
if (tunable_pasv_max_port >= min_port && tunable_pasv_max_port < max_port)
|
||||
{
|
||||
max_port = tunable_pasv_max_port;
|
||||
}
|
||||
|
||||
while (--bind_retries)
|
||||
{
|
||||
int retval;
|
||||
double scaled_port;
|
||||
the_port = vsf_sysutil_get_random_byte();
|
||||
the_port <<= 8;
|
||||
the_port |= vsf_sysutil_get_random_byte();
|
||||
scaled_port = (double) min_port;
|
||||
scaled_port += ((double) the_port / (double) 65536) *
|
||||
((double) max_port - min_port + 1);
|
||||
the_port = (unsigned short) scaled_port;
|
||||
vsf_sysutil_sockaddr_clone(&s_p_sockaddr, p_sess->p_local_addr);
|
||||
vsf_sysutil_sockaddr_set_port(s_p_sockaddr, the_port);
|
||||
retval = vsf_sysutil_bind(p_sess->pasv_listen_fd, s_p_sockaddr);
|
||||
if (!vsf_sysutil_retval_is_error(retval))
|
||||
{
|
||||
retval = vsf_sysutil_listen(p_sess->pasv_listen_fd, 1);
|
||||
if (!vsf_sysutil_retval_is_error(retval))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* SELinux systems can give you an inopportune EACCES, it seems. */
|
||||
if (vsf_sysutil_get_error() == kVSFSysUtilErrADDRINUSE ||
|
||||
vsf_sysutil_get_error() == kVSFSysUtilErrACCES)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
die("vsf_sysutil_bind / listen");
|
||||
}
|
||||
if (!bind_retries)
|
||||
{
|
||||
die("vsf_sysutil_bind");
|
||||
}
|
||||
return the_port;
|
||||
}
|
||||
|
||||
int
|
||||
vsf_privop_accept_pasv(struct vsf_session* p_sess)
|
||||
{
|
||||
struct vsf_sysutil_sockaddr* p_accept_addr = 0;
|
||||
int remote_fd;
|
||||
vsf_sysutil_sockaddr_alloc(&p_accept_addr);
|
||||
remote_fd = vsf_sysutil_accept_timeout(p_sess->pasv_listen_fd, p_accept_addr,
|
||||
tunable_accept_timeout);
|
||||
if (vsf_sysutil_retval_is_error(remote_fd))
|
||||
{
|
||||
vsf_sysutil_sockaddr_clear(&p_accept_addr);
|
||||
return -1;
|
||||
}
|
||||
/* SECURITY:
|
||||
* Reject the connection if it wasn't from the same IP as the
|
||||
* control connection.
|
||||
*/
|
||||
if (!tunable_pasv_promiscuous)
|
||||
{
|
||||
if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_accept_addr))
|
||||
{
|
||||
vsf_sysutil_close(remote_fd);
|
||||
vsf_sysutil_sockaddr_clear(&p_accept_addr);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
vsf_sysutil_sockaddr_clear(&p_accept_addr);
|
||||
return remote_fd;
|
||||
}
|
||||
|
||||
void
|
||||
vsf_privop_do_file_chown(struct vsf_session* p_sess, int fd)
|
||||
{
|
||||
|
52
privops.h
52
privops.h
@ -6,13 +6,59 @@ struct vsf_session;
|
||||
|
||||
/* vsf_privop_get_ftp_port_sock()
|
||||
* PURPOSE
|
||||
* Return a network socket bound to a privileged port (less than 1024).
|
||||
* 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
|
||||
* RETURNS
|
||||
* A file descriptor which is a socket bound to the privileged port, and
|
||||
* connected to the remote on the specified port.
|
||||
* Kills the process / session if the bind() fails.
|
||||
* 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);
|
||||
|
||||
/* vsf_privop_pasv_cleanup()
|
||||
* PURPOSE
|
||||
* Makes sure any listening passive socket is closed.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
*/
|
||||
void vsf_privop_pasv_cleanup(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_privop_pasv_listen()
|
||||
* PURPOSE
|
||||
* Start listening for an FTP data connection.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* A file descriptor which is a socket bound to the privileged port.
|
||||
* The port we ended up listening on.
|
||||
*/
|
||||
int vsf_privop_get_ftp_port_sock(struct vsf_session* p_sess);
|
||||
unsigned short vsf_privop_pasv_listen(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_privop_pasv_active()
|
||||
* PURPOSE
|
||||
* Determine whether there is a passive listening socket active.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* 1 if active, 0 if not.
|
||||
*/
|
||||
int vsf_privop_pasv_active(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_privop_accept_pasv()
|
||||
* PURPOSE
|
||||
* Accept a connection on the listening data socket.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* The file descriptor of the accepted incoming connection; or -1 if a
|
||||
* network error occurred or -2 if the incoming connection was from the
|
||||
* wrong IP (security issue).
|
||||
*/
|
||||
int vsf_privop_accept_pasv(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_privop_do_file_chown()
|
||||
* PURPOSE
|
||||
|
@ -165,6 +165,10 @@ int priv_sock_get_int(int fd);
|
||||
#define PRIV_SOCK_DO_SSL_CLOSE 7
|
||||
#define PRIV_SOCK_DO_SSL_READ 8
|
||||
#define PRIV_SOCK_DO_SSL_WRITE 9
|
||||
#define PRIV_SOCK_PASV_CLEANUP 10
|
||||
#define PRIV_SOCK_PASV_ACTIVE 11
|
||||
#define PRIV_SOCK_PASV_LISTEN 12
|
||||
#define PRIV_SOCK_PASV_ACCEPT 13
|
||||
|
||||
#define PRIV_SOCK_RESULT_OK 1
|
||||
#define PRIV_SOCK_RESULT_BAD 2
|
||||
|
@ -35,6 +35,14 @@
|
||||
|
||||
#include <asm/unistd.h>
|
||||
|
||||
#ifndef __NR_sendfile64
|
||||
#define __NR_sendfile64 239
|
||||
#endif
|
||||
|
||||
#ifndef __NR_exit_group
|
||||
#define __NR_exit_group 252
|
||||
#endif
|
||||
|
||||
#ifndef __NR_utimes
|
||||
#define __NR_utimes 271
|
||||
#endif
|
||||
|
22
sysdeputil.c
22
sysdeputil.c
@ -73,6 +73,9 @@
|
||||
#ifndef CLONE_NEWIPC
|
||||
#define CLONE_NEWIPC 0x08000000
|
||||
#endif
|
||||
#ifndef CLONE_NEWNET
|
||||
#define CLONE_NEWNET 0x40000000
|
||||
#endif
|
||||
#include <linux/unistd.h>
|
||||
#include <errno.h>
|
||||
#include <syscall.h>
|
||||
@ -1255,6 +1258,25 @@ vsf_sysutil_fork_isolate_failok()
|
||||
return vsf_sysutil_fork_failok();
|
||||
}
|
||||
|
||||
int
|
||||
vsf_sysutil_fork_newnet()
|
||||
{
|
||||
#ifdef VSF_SYSDEP_HAVE_LINUX_CLONE
|
||||
static int cloneflags_work = 1;
|
||||
if (cloneflags_work)
|
||||
{
|
||||
int ret = syscall(__NR_clone, CLONE_NEWNET | SIGCHLD, NULL);
|
||||
if (ret != -1 || errno != EINVAL)
|
||||
{
|
||||
vsf_sysutil_clear_pid_cache();
|
||||
return ret;
|
||||
}
|
||||
cloneflags_work = 0;
|
||||
}
|
||||
#endif
|
||||
return vsf_sysutil_fork();
|
||||
}
|
||||
|
||||
int
|
||||
vsf_sysutil_getpid_nocache(void)
|
||||
{
|
||||
|
@ -60,8 +60,12 @@ void vsf_set_die_if_parent_dies();
|
||||
/* Or a softer version delivering SIGTERM. */
|
||||
void vsf_set_term_if_parent_dies();
|
||||
|
||||
/* If supported, the ability to fork into different secure namespaces. */
|
||||
/* If supported, the ability to fork into different secure namespaces (PID
|
||||
* and IPC. Fails back to normal fork() */
|
||||
int vsf_sysutil_fork_isolate_failok();
|
||||
/* If supported, the ability to fork into an empty network namespace.
|
||||
* Fails back to normal fork() */
|
||||
int vsf_sysutil_fork_newnet();
|
||||
int vsf_sysutil_getpid_nocache();
|
||||
|
||||
#endif /* VSF_SYSDEPUTIL_H */
|
||||
|
49
sysutil.c
49
sysutil.c
@ -542,15 +542,7 @@ vsf_sysutil_getpid(void)
|
||||
int
|
||||
vsf_sysutil_fork(void)
|
||||
{
|
||||
/* Child does NOT inherit exit function */
|
||||
exitfunc_t curr_func = s_exit_func;
|
||||
int retval;
|
||||
s_exit_func = 0;
|
||||
retval = vsf_sysutil_fork_failok();
|
||||
if (retval != 0)
|
||||
{
|
||||
s_exit_func = curr_func;
|
||||
}
|
||||
int retval = vsf_sysutil_fork_failok();
|
||||
if (retval < 0)
|
||||
{
|
||||
die("fork");
|
||||
@ -561,7 +553,15 @@ vsf_sysutil_fork(void)
|
||||
int
|
||||
vsf_sysutil_fork_failok(void)
|
||||
{
|
||||
int retval = fork();
|
||||
/* Child does NOT inherit exit function */
|
||||
exitfunc_t curr_func = s_exit_func;
|
||||
int retval;
|
||||
s_exit_func = 0;
|
||||
retval = fork();
|
||||
if (retval != 0)
|
||||
{
|
||||
s_exit_func = curr_func;
|
||||
}
|
||||
if (retval == 0)
|
||||
{
|
||||
vsf_sysutil_clear_pid_cache();
|
||||
@ -1597,7 +1597,7 @@ vsf_sysutil_get_error(void)
|
||||
retval = kVSFSysUtilErrOPNOTSUPP;
|
||||
break;
|
||||
case EACCES:
|
||||
retval = kVSFSysUtilErrOPNOTSUPP;
|
||||
retval = kVSFSysUtilErrACCES;
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
@ -1684,7 +1684,7 @@ vsf_sysutil_accept_timeout(int fd, struct vsf_sysutil_sockaddr* p_sockaddr,
|
||||
int saved_errno;
|
||||
fd_set accept_fdset;
|
||||
struct timeval timeout;
|
||||
unsigned int socklen = sizeof(remote_addr);
|
||||
socklen_t socklen = sizeof(remote_addr);
|
||||
if (p_sockaddr)
|
||||
{
|
||||
vsf_sysutil_memclr(p_sockaddr, sizeof(*p_sockaddr));
|
||||
@ -1808,7 +1808,7 @@ vsf_sysutil_getsockname(int fd, struct vsf_sysutil_sockaddr** p_sockptr)
|
||||
{
|
||||
struct vsf_sysutil_sockaddr the_addr;
|
||||
int retval;
|
||||
unsigned int socklen = sizeof(the_addr);
|
||||
socklen_t socklen = sizeof(the_addr);
|
||||
vsf_sysutil_sockaddr_clear(p_sockptr);
|
||||
retval = getsockname(fd, &the_addr.u.u_sockaddr, &socklen);
|
||||
if (retval != 0)
|
||||
@ -1833,7 +1833,7 @@ vsf_sysutil_getpeername(int fd, struct vsf_sysutil_sockaddr** p_sockptr)
|
||||
{
|
||||
struct vsf_sysutil_sockaddr the_addr;
|
||||
int retval;
|
||||
unsigned int socklen = sizeof(the_addr);
|
||||
socklen_t socklen = sizeof(the_addr);
|
||||
vsf_sysutil_sockaddr_clear(p_sockptr);
|
||||
retval = getpeername(fd, &the_addr.u.u_sockaddr, &socklen);
|
||||
if (retval != 0)
|
||||
@ -2130,6 +2130,25 @@ vsf_sysutil_sockaddr_set_any(struct vsf_sysutil_sockaddr* p_sockaddr)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned short
|
||||
vsf_sysutil_sockaddr_get_port(const struct vsf_sysutil_sockaddr* p_sockptr)
|
||||
{
|
||||
if (p_sockptr->u.u_sockaddr.sa_family == AF_INET)
|
||||
{
|
||||
return ntohs(p_sockptr->u.u_sockaddr_in.sin_port);
|
||||
}
|
||||
else if (p_sockptr->u.u_sockaddr.sa_family == AF_INET6)
|
||||
{
|
||||
return ntohs(p_sockptr->u.u_sockaddr_in6.sin6_port);
|
||||
}
|
||||
else
|
||||
{
|
||||
bug("bad family");
|
||||
}
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
vsf_sysutil_sockaddr_set_port(struct vsf_sysutil_sockaddr* p_sockptr,
|
||||
unsigned short the_port)
|
||||
@ -2779,6 +2798,7 @@ vsf_sysutil_set_no_fds()
|
||||
void
|
||||
vsf_sysutil_set_no_procs()
|
||||
{
|
||||
#ifdef RLIMIT_NPROC
|
||||
int ret;
|
||||
struct rlimit rlim;
|
||||
rlim.rlim_cur = 0;
|
||||
@ -2788,6 +2808,7 @@ vsf_sysutil_set_no_procs()
|
||||
{
|
||||
die("setrlimit NPROC");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -228,6 +228,8 @@ void vsf_sysutil_sockaddr_set_ipv4addr(struct vsf_sysutil_sockaddr* p_sockptr,
|
||||
void vsf_sysutil_sockaddr_set_ipv6addr(struct vsf_sysutil_sockaddr* p_sockptr,
|
||||
const unsigned char* p_raw);
|
||||
void vsf_sysutil_sockaddr_set_any(struct vsf_sysutil_sockaddr* p_sockaddr);
|
||||
unsigned short vsf_sysutil_sockaddr_get_port(
|
||||
const struct vsf_sysutil_sockaddr* p_sockptr);
|
||||
void vsf_sysutil_sockaddr_set_port(struct vsf_sysutil_sockaddr* p_sockptr,
|
||||
unsigned short the_port);
|
||||
int vsf_sysutil_is_port_reserved(unsigned short port);
|
||||
|
@ -83,6 +83,7 @@ int tunable_implicit_ssl;
|
||||
int tunable_sandbox;
|
||||
int tunable_require_ssl_reuse;
|
||||
int tunable_isolate;
|
||||
int tunable_isolate_network;
|
||||
|
||||
unsigned int tunable_accept_timeout;
|
||||
unsigned int tunable_connect_timeout;
|
||||
@ -218,6 +219,7 @@ tunables_load_defaults()
|
||||
tunable_sandbox = 0;
|
||||
tunable_require_ssl_reuse = 1;
|
||||
tunable_isolate = 1;
|
||||
tunable_isolate_network = 1;
|
||||
|
||||
tunable_accept_timeout = 60;
|
||||
tunable_connect_timeout = 60;
|
||||
|
@ -84,6 +84,7 @@ extern int tunable_implicit_ssl; /* Use implicit SSL protocol */
|
||||
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 */
|
||||
|
||||
/* Integer/numeric defines */
|
||||
extern unsigned int tunable_accept_timeout;
|
||||
|
60
twoprocess.c
60
twoprocess.c
@ -90,7 +90,15 @@ vsf_two_process_start(struct vsf_session* p_sess)
|
||||
}
|
||||
vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1);
|
||||
{
|
||||
int newpid = vsf_sysutil_fork();
|
||||
int newpid;
|
||||
if (tunable_isolate_network)
|
||||
{
|
||||
newpid = vsf_sysutil_fork_newnet();
|
||||
}
|
||||
else
|
||||
{
|
||||
newpid = vsf_sysutil_fork();
|
||||
}
|
||||
if (newpid != 0)
|
||||
{
|
||||
priv_sock_set_parent_context(p_sess);
|
||||
@ -200,15 +208,54 @@ int
|
||||
vsf_two_process_get_priv_data_sock(struct vsf_session* p_sess)
|
||||
{
|
||||
char res;
|
||||
unsigned short port = vsf_sysutil_sockaddr_get_port(p_sess->p_port_sockaddr);
|
||||
priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_GET_DATA_SOCK);
|
||||
priv_sock_send_int(p_sess->child_fd, port);
|
||||
res = priv_sock_get_result(p_sess->child_fd);
|
||||
if (res != PRIV_SOCK_RESULT_OK)
|
||||
if (res == PRIV_SOCK_RESULT_BAD)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else if (res != PRIV_SOCK_RESULT_OK)
|
||||
{
|
||||
die("could not get privileged socket");
|
||||
}
|
||||
return priv_sock_recv_fd(p_sess->child_fd);
|
||||
}
|
||||
|
||||
void
|
||||
vsf_two_process_pasv_cleanup(struct vsf_session* p_sess)
|
||||
{
|
||||
char res;
|
||||
priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_CLEANUP);
|
||||
res = priv_sock_get_result(p_sess->child_fd);
|
||||
if (res != PRIV_SOCK_RESULT_OK)
|
||||
{
|
||||
die("could not clean up socket");
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
vsf_two_process_pasv_active(struct vsf_session* p_sess)
|
||||
{
|
||||
priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_ACTIVE);
|
||||
return priv_sock_get_int(p_sess->child_fd);
|
||||
}
|
||||
|
||||
unsigned short
|
||||
vsf_two_process_listen(struct vsf_session* p_sess)
|
||||
{
|
||||
priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_LISTEN);
|
||||
return (unsigned short) priv_sock_get_int(p_sess->child_fd);
|
||||
}
|
||||
|
||||
int
|
||||
vsf_two_process_get_pasv_fd(struct vsf_session* p_sess)
|
||||
{
|
||||
priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_ACCEPT);
|
||||
return priv_sock_recv_fd(p_sess->child_fd);
|
||||
}
|
||||
|
||||
void
|
||||
vsf_two_process_chown_upload(struct vsf_session* p_sess, int fd)
|
||||
{
|
||||
@ -324,7 +371,14 @@ common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str,
|
||||
priv_sock_close(p_sess);
|
||||
priv_sock_init(p_sess);
|
||||
vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1);
|
||||
newpid = vsf_sysutil_fork();
|
||||
if (tunable_isolate_network && !tunable_port_promiscuous)
|
||||
{
|
||||
newpid = vsf_sysutil_fork_newnet();
|
||||
}
|
||||
else
|
||||
{
|
||||
newpid = vsf_sysutil_fork();
|
||||
}
|
||||
if (newpid == 0)
|
||||
{
|
||||
struct mystr guest_user_str = INIT_MYSTR;
|
||||
|
40
twoprocess.h
40
twoprocess.h
@ -33,6 +33,46 @@ void vsf_two_process_login(struct vsf_session* p_sess,
|
||||
*/
|
||||
int vsf_two_process_get_priv_data_sock(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_two_process_pasv_cleanup()
|
||||
* PURPOSE
|
||||
* Clean up any listening passive socket in the privileged side.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
*/
|
||||
void vsf_two_process_pasv_cleanup(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_two_process_pasv_active()
|
||||
* PURPOSE
|
||||
* Determine if the passive socket is listening on the privileged side.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* 1 if active, 0 if not.
|
||||
*/
|
||||
int vsf_two_process_pasv_active(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_two_process_listen()
|
||||
* PURPOSE
|
||||
* Start listening for an incoming connection on the passive socket in the
|
||||
* privileged side.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* The port we listened on.
|
||||
*/
|
||||
unsigned short vsf_two_process_listen(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_two_process_get_pasv_fd()
|
||||
* PURPOSE
|
||||
* Accept an incoming connection on the passive socket in the privileged
|
||||
* side.
|
||||
* PARAMETERS
|
||||
* p_sess - the current session object
|
||||
* RETURNS
|
||||
* The file descriptor for the incoming connection.
|
||||
*/
|
||||
int vsf_two_process_get_pasv_fd(struct vsf_session* p_sess);
|
||||
|
||||
/* vsf_two_process_chown_upload()
|
||||
* PURPOSE
|
||||
* Change ownership of an uploaded file using the two process model.
|
||||
|
@ -14,6 +14,7 @@ fi
|
||||
if find_func pam_start sysdeputil.o; then
|
||||
locate_library /lib/libpam.so.0 && echo "/lib/libpam.so.0";
|
||||
locate_library /usr/lib/libpam.so && echo "-lpam";
|
||||
locate_library /usr/lib64/libpam.so && echo "-lpam";
|
||||
# HP-UX ends shared libraries with .sl
|
||||
locate_library /usr/lib/libpam.sl && echo "-lpam";
|
||||
# AIX ends shared libraries with .a
|
||||
@ -21,6 +22,7 @@ if find_func pam_start sysdeputil.o; then
|
||||
else
|
||||
locate_library /lib/libcrypt.so && echo "-lcrypt";
|
||||
locate_library /usr/lib/libcrypt.so && echo "-lcrypt";
|
||||
locate_library /usr/lib64/libcrypt.so && echo "-lcrypt";
|
||||
fi
|
||||
|
||||
# Look for the dynamic linker library. Needed by older RedHat when
|
||||
@ -50,6 +52,7 @@ elif locate_library /lib/libcap.so.2; then
|
||||
else
|
||||
locate_library /usr/lib/libcap.so && echo "-lcap";
|
||||
locate_library /lib/libcap.so && echo "-lcap";
|
||||
locate_library /lib64/libcap.so && echo "-lcap";
|
||||
fi
|
||||
|
||||
# Solaris needs this for nanosleep()..
|
||||
|
@ -92,6 +92,7 @@ connect_from_port_20=YES
|
||||
# You may specify an explicit list of local users to chroot() to their home
|
||||
# directory. If chroot_local_user is YES, then this list becomes a list of
|
||||
# users to NOT chroot().
|
||||
#chroot_local_user=YES
|
||||
#chroot_list_enable=YES
|
||||
# (default follows)
|
||||
#chroot_list_file=/etc/vsftpd.chroot_list
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef VSF_VERSION_H
|
||||
#define VSF_VERSION_H
|
||||
|
||||
#define VSF_VERSION "2.1.2"
|
||||
#define VSF_VERSION "2.2.0"
|
||||
|
||||
#endif /* VSF_VERSION_H */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user