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

Updated to v2.0.5

This commit is contained in:
Dag Wieers 2006-07-03 00:00:00 +02:00
parent d201301b42
commit c4e45fe8ac
20 changed files with 190 additions and 66 deletions

View File

@ -908,3 +908,30 @@ Mads Martin Joergensen <mmj@suse.de>.
At this point: v2.0.4 released!
===============================
- Apply fix for O_NONBLOCK vs. XFS DMAPI filesystem. Thanks to Sudha Srinivasan
<sudhas@sgi.com>.
- Fix build warnings exposed by my upgrade to Fedora Core 5 / GCC4.1.1.
- Be more honest in FEAT response if PORT or PASV are disabled! Reported by
Charles Honton <chas@honton.org>. Allows MS Explorer to get the transfer mode
correct.
- pam_pwdb.so -> pam_unix.so in example PAM file. Thanks to
Rhodes, Colin <colin.rhodes@airways.co.nz>.
- Add FAQ issue regarding "chroot fails with SSL" - in fact, sshd is being hit
here instead ;-)
- Minor man page doc tweaks.
- Tiny bit of paranoia in privops.c.
- Revert change to reject anonymous logins before asking for password. This
fixes complaints about IE not showing the FTP login dialog.
- Change SSL certificate load to cater for chaining too.
- Added delay_failed_login and delay_successful_login to help limit resources
taken by brute force attacks.
- Kick session after a few login fails. Allows IP blocking solutions to be more
immediately effective.
- Replace setenv() with more portable putenv(). First part of Solaris fix.
- Replace tm_gmtoff usage with timezone and daylight. Second part of Solaris
fix.
- Set PAM items TTY and RUSER if possible.
- OpenBSD build warning fixes.
- So, timezone and daylight are not available on BSD, so redo the whole TZ
thing again. Should use only very portable constructs now.

5
FAQ
View File

@ -234,6 +234,11 @@ Q) Help! I'm getting the error "ftp: netin: Interrupted system call".
A) Seems to be a bug in ftp-tls, particularly with SSL transfers with
bandwidth limiting in effect.
Q) Help! When trying SSL transfers, users log in and are no longer restricted
to their home directory! They can browse the entire filesystem!
A) Most likely, your FTP client is in fact using the SSH protocol rather than
the FTP protocol - so sshd is in control and not vsftpd!
Q) Blah.. blah..
A) For a good idea of what vsftpd can do, read the vsftpd.conf.5 man page
and the EXAMPLES.

8
README
View File

@ -1,4 +1,4 @@
This is vsftpd, version 2.0.4
This is vsftpd, version 2.0.5
Author: Chris Evans
Contact: chris@scary.beasts.org
Website: http://vsftpd.beasts.org/
@ -37,9 +37,3 @@ All configuration options are documented in the manual page vsftpd.conf.5.
Various example configurations are discussed in the EXAMPLE directory.
Frequently asked questions are tackled in the FAQ file.
Plug
====
I'm always interested in security-related job offers. I specialize in
application security testing and am very very good at it.

View File

@ -1,6 +1,6 @@
#%PAM-1.0
auth required /lib/security/pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed
auth required /lib/security/pam_pwdb.so shadow nullok
auth required /lib/security/pam_unix.so shadow nullok
auth required /lib/security/pam_shells.so
account required /lib/security/pam_pwdb.so
session required /lib/security/pam_pwdb.so
account required /lib/security/pam_unix.so
session required /lib/security/pam_unix.so

View File

@ -21,10 +21,19 @@ handle_feat(struct vsf_session* p_sess)
vsf_cmdio_write_raw(p_sess, " AUTH SSL\r\n");
vsf_cmdio_write_raw(p_sess, " AUTH TLS\r\n");
}
vsf_cmdio_write_raw(p_sess, " EPRT\r\n");
vsf_cmdio_write_raw(p_sess, " EPSV\r\n");
if (tunable_port_enable)
{
vsf_cmdio_write_raw(p_sess, " EPRT\r\n");
}
if (tunable_pasv_enable)
{
vsf_cmdio_write_raw(p_sess, " EPSV\r\n");
}
vsf_cmdio_write_raw(p_sess, " MDTM\r\n");
vsf_cmdio_write_raw(p_sess, " PASV\r\n");
if (tunable_pasv_enable)
{
vsf_cmdio_write_raw(p_sess, " PASV\r\n");
}
if (tunable_ssl_enable)
{
vsf_cmdio_write_raw(p_sess, " PBSZ\r\n");

View File

@ -55,7 +55,7 @@ vsf_sysutil_parse_ipv6(const struct mystr* p_str)
}
str_append_str(&s_ret, &s_rhs_ret);
}
return str_getbuf(&s_ret);
return (const unsigned char*) str_getbuf(&s_ret);
}
const unsigned char*

4
main.c
View File

@ -61,7 +61,9 @@ main(int argc, const char* argv[])
/* Home directory */
INIT_MYSTR,
/* Secure connection state */
0, 0, 0, 0, 0, 0, -1, -1
0, 0, 0, 0, 0, 0, -1, -1,
/* Login fails */
0
};
int config_specified = 0;
const char* p_config_name = VSFTP_DEFAULT_CONFIG;

View File

@ -125,6 +125,9 @@ parseconf_uint_array[] =
{ "file_open_mode", &tunable_file_open_mode },
{ "max_per_ip", &tunable_max_per_ip },
{ "trans_chunk_size", &tunable_trans_chunk_size },
{ "delay_failed_login", &tunable_delay_failed_login },
{ "delay_successful_login", &tunable_delay_successful_login },
{ "max_login_fails", &tunable_max_login_fails },
{ 0, 0 }
};

View File

@ -659,6 +659,10 @@ handle_retr(struct vsf_session* p_sess)
vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file.");
goto file_close_out;
}
/* Now deactive O_NONBLOCK, otherwise we have a problem on DMAPI filesystems
* such as XFS DMAPI.
*/
vsf_sysutil_deactivate_noblock(opened_file);
/* Optionally, we'll be paranoid and only serve publicly readable stuff */
if (p_sess->is_anonymous && tunable_anon_world_readable_only &&
!vsf_sysutil_statbuf_is_readable_other(s_p_statbuf))
@ -942,6 +946,7 @@ handle_stor(struct vsf_session* p_sess)
static void
handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique)
{
static struct vsf_sysutil_statbuf* s_p_statbuf;
static struct mystr s_filename;
struct mystr* p_filename;
struct vsf_transfer_ret trans_ret;
@ -993,6 +998,14 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique)
vsf_cmdio_write(p_sess, FTP_UPLOADFAIL, "Could not create file.");
return;
}
vsf_sysutil_fstat(new_file_fd, &s_p_statbuf);
if (vsf_sysutil_statbuf_is_regfile(s_p_statbuf))
{
/* Now deactive O_NONBLOCK, otherwise we have a problem on DMAPI filesystems
* such as XFS DMAPI.
*/
vsf_sysutil_deactivate_noblock(new_file_fd);
}
/* Are we required to chown() this file for security? */
if (p_sess->is_anonymous && tunable_chown_uploads)
{

View File

@ -22,6 +22,7 @@
#include "logging.h"
#include "ssl.h"
#include "features.h"
#include "defs.h"
/* Functions used */
static void emit_greeting(struct vsf_session* p_sess);
@ -157,11 +158,6 @@ handle_user_command(struct vsf_session* p_sess)
str_empty(&p_sess->user_str);
return;
}
if (!tunable_anonymous_enable && is_anon)
{
vsf_cmdio_write(
p_sess, FTP_LOGINERR, "This FTP server does not allow anonymous logins.");
}
if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl &&
!tunable_force_anon_logins_ssl)
{
@ -227,6 +223,10 @@ handle_pass_command(struct vsf_session* p_sess)
vsf_two_process_login(p_sess, &p_sess->ftp_arg_str);
}
vsf_cmdio_write(p_sess, FTP_LOGINERR, "Login incorrect.");
if (++p_sess->login_fails >= tunable_max_login_fails)
{
vsf_sysutil_exit(0);
}
str_empty(&p_sess->user_str);
/* FALLTHRU if login fails */
}

View File

@ -86,10 +86,18 @@ vsf_privop_do_login(struct vsf_session* p_sess,
if (result == kVSFLoginFail)
{
vsf_log_do_log(p_sess, 0);
if (tunable_delay_failed_login)
{
vsf_sysutil_sleep((double) tunable_delay_failed_login);
}
}
else
{
vsf_log_do_log(p_sess, 1);
if (tunable_delay_successful_login)
{
vsf_sysutil_sleep((double) tunable_delay_successful_login);
}
}
return result;
}
@ -145,6 +153,10 @@ handle_login(struct vsf_session* p_sess, const struct mystr* p_user_str,
}
else
{
if (!tunable_local_enable)
{
die("unexpected local login in handle_login");
}
result = handle_local_login(p_sess, p_user_str, p_pass_str);
}
return result;

View File

@ -90,6 +90,7 @@ struct vsf_session
int ssl_slave_active;
int ssl_slave_fd;
int ssl_consumer_fd;
unsigned int login_fails;
};
#endif /* VSF_SESSION_H */

6
ssl.c
View File

@ -71,8 +71,7 @@ ssl_init(struct vsf_session* p_sess)
{
p_key = tunable_rsa_cert_file;
}
if (SSL_CTX_use_certificate_file(
p_ctx, tunable_rsa_cert_file, X509_FILETYPE_PEM) != 1)
if (SSL_CTX_use_certificate_chain_file(p_ctx, tunable_rsa_cert_file) != 1)
{
die("SSL: cannot load RSA certificate");
}
@ -88,8 +87,7 @@ ssl_init(struct vsf_session* p_sess)
{
p_key = tunable_dsa_cert_file;
}
if (SSL_CTX_use_certificate_file(
p_ctx, tunable_dsa_cert_file, X509_FILETYPE_PEM) != 1)
if (SSL_CTX_use_certificate_chain_file(p_ctx, tunable_dsa_cert_file) != 1)
{
die("SSL: cannot load DSA certificate");
}

4
str.c
View File

@ -436,6 +436,8 @@ str_locate_chars(const struct mystr* p_str, const char* p_chars)
unsigned int num_chars = vsf_sysutil_strlen(p_chars);
unsigned int i = 0;
retval.found = 0;
retval.char_found = 0;
retval.index = 0;
for (; i < p_str->len; ++i)
{
unsigned int j = 0;
@ -461,6 +463,7 @@ str_locate_text(const struct mystr* p_str, const char* p_text)
unsigned int i;
unsigned int text_len = vsf_sysutil_strlen(p_text);
retval.found = 0;
retval.char_found = 0;
retval.index = 0;
if (text_len == 0 || text_len > p_str->len)
{
@ -487,6 +490,7 @@ str_locate_text_reverse(const struct mystr* p_str, const char* p_text)
unsigned int i;
unsigned int text_len = vsf_sysutil_strlen(p_text);
retval.found = 0;
retval.char_found = 0;
retval.index = 0;
if (text_len == 0 || text_len > p_str->len)
{

View File

@ -201,9 +201,11 @@ static int do_sendfile(const int out_fd, const int in_fd,
unsigned int num_send, filesize_t start_pos);
static void vsf_sysutil_setproctitle_internal(const char* p_text);
static struct mystr s_proctitle_prefix_str;
static void vsf_insert_uwtmp(const struct mystr* p_user_str,
const struct mystr* p_host_str);
static void vsf_remove_uwtmp(void);
/* These two aren't static to avoid OpenBSD build warnings. */
void vsf_insert_uwtmp(const struct mystr* p_user_str,
const struct mystr* p_host_str);
void vsf_remove_uwtmp(void);
#ifndef VSF_SYSDEP_HAVE_PAM
int
@ -310,6 +312,24 @@ vsf_sysdep_check_auth(const struct mystr* p_user_str,
s_pamh = 0;
return 0;
}
#endif
#ifdef PAM_TTY
retval = pam_set_item(s_pamh, PAM_TTY, "ftp");
if (retval != PAM_SUCCESS)
{
(void) pam_end(s_pamh, 0);
s_pamh = 0;
return 0;
}
#endif
#ifdef PAM_RUSER
retval = pam_set_item(s_pamh, PAM_RUSER, str_getbuf(p_user_str));
if (retval != PAM_SUCCESS)
{
(void) pam_end(s_pamh, 0);
s_pamh = 0;
return 0;
}
#endif
retval = pam_authenticate(s_pamh, 0);
if (retval != PAM_SUCCESS)
@ -625,6 +645,7 @@ static int do_sendfile(const int out_fd, const int in_fd,
int retval;
enum EVSFSysUtilError error;
(void) start_pos;
(void) error;
#if defined(VSF_SYSDEP_HAVE_LINUX_SENDFILE) || \
defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE) || \
defined(VSF_SYSDEP_HAVE_HPUX_SENDFILE) || \
@ -1087,7 +1108,7 @@ vsf_sysutil_recv_fd(int sock_fd)
#ifndef VSF_SYSDEP_HAVE_UTMPX
static void
void
vsf_insert_uwtmp(const struct mystr* p_user_str,
const struct mystr* p_host_str)
{
@ -1095,7 +1116,7 @@ vsf_insert_uwtmp(const struct mystr* p_user_str,
(void) p_host_str;
}
static void
void
vsf_remove_uwtmp(void)
{
}
@ -1107,7 +1128,7 @@ vsf_remove_uwtmp(void)
static int s_uwtmp_inserted;
static struct utmpx s_utent;
static void
void
vsf_insert_uwtmp(const struct mystr* p_user_str,
const struct mystr* p_host_str)
{
@ -1147,7 +1168,7 @@ vsf_insert_uwtmp(const struct mystr* p_user_str,
updwtmpx(WTMPX_FILE, &s_utent);
}
static void
void
vsf_remove_uwtmp(void)
{
if (!s_uwtmp_inserted)

View File

@ -1740,7 +1740,7 @@ vsf_sysutil_connect_timeout(int fd, const struct vsf_sysutil_sockaddr* p_addr,
}
else
{
int socklen = sizeof(retval);
socklen_t socklen = sizeof(retval);
int sockoptret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &retval, &socklen);
if (sockoptret != 0)
{
@ -2415,34 +2415,6 @@ vsf_sysutil_chroot(const char* p_root_path)
{
die("chroot");
}
/* Set our timezone in the TZ environment variable to cater for the fact
* that modern glibc does not cache /etc/localtime (which is of course now
* inaccessible).
*/
if (s_timezone)
{
char envtz[sizeof("UTC-hh:mm:ss")];
int hour, min, sec;
hour = s_timezone;
if (hour < 0)
{
hour = -hour;
}
if (hour < 25*60*60)
{
sec = hour % 60;
hour /= 60;
min = hour % 60;
hour /= 60;
if (s_timezone < 0)
{
hour = -hour;
}
snprintf(envtz, sizeof(envtz), "UTC%+d:%d:%d", hour, min, sec);
setenv("TZ", envtz, 1);
}
}
}
unsigned int
@ -2473,12 +2445,50 @@ vsf_sysutil_make_session_leader(void)
void
vsf_sysutil_tzset(void)
{
time_t the_time = 0;
int retval;
char tzbuf[sizeof("+HHMM!")];
time_t the_time = time(NULL);
struct tm* p_tm;
tzset();
the_time = time(NULL);
p_tm = localtime(&the_time);
s_timezone = -p_tm->tm_gmtoff;
if (p_tm == NULL)
{
die("localtime");
}
/* Set our timezone in the TZ environment variable to cater for the fact
* that modern glibc does not cache /etc/localtime (which becomes inaccessible
* when we chroot().
*/
retval = strftime(tzbuf, sizeof(tzbuf), "%z", p_tm);
tzbuf[sizeof(tzbuf) - 1] = '\0';
if (retval == 5)
{
/* Static because putenv() does not copy the string. */
static char envtz[sizeof("TZ=UTC-hh:mm")];
/* Insert a colon so we have e.g. -05:00 instead of -0500 */
tzbuf[5] = tzbuf[4];
tzbuf[4] = tzbuf[3];
tzbuf[3] = ':';
/* Invert the sign - we just got the offset _from_ UTC but for TZ, we need
* the offset _to_ UTC.
*/
if (tzbuf[0] == '+')
{
tzbuf[0] = '-';
}
else
{
tzbuf[0] = '+';
}
snprintf(envtz, sizeof(envtz), "TZ=UTC%s", tzbuf);
putenv(envtz);
s_timezone = ((tzbuf[1] - '0') * 10 + (tzbuf[2] - '0')) * 60 * 60;
s_timezone += ((tzbuf[4] - '0') * 10 + (tzbuf[5] - '0')) * 60;
if (tzbuf[0] == '-')
{
s_timezone *= -1;
}
}
}
const char*

View File

@ -91,6 +91,9 @@ unsigned int tunable_max_clients = 0;
unsigned int tunable_file_open_mode = 0666;
unsigned int tunable_max_per_ip = 0;
unsigned int tunable_trans_chunk_size = 0;
unsigned int tunable_delay_failed_login = 1;
unsigned int tunable_delay_successful_login = 0;
unsigned int tunable_max_login_fails = 3;
const char* tunable_secure_chroot_dir = "/usr/share/empty";
const char* tunable_ftp_username = "ftp";

View File

@ -85,6 +85,9 @@ extern unsigned int tunable_max_clients;
extern unsigned int tunable_file_open_mode;
extern unsigned int tunable_max_per_ip;
extern unsigned int tunable_trans_chunk_size;
extern unsigned int tunable_delay_failed_login;
extern unsigned int tunable_delay_successful_login;
extern unsigned int tunable_max_login_fails;
/* String defines */
extern const char* tunable_secure_chroot_dir;

View File

@ -63,7 +63,9 @@ If set to YES, anonymous users will be permitted to upload files under certain
conditions. For this to work, the option
.BR write_enable
must be activated, and the anonymous ftp user must have write permission on
desired upload locations.
desired upload locations. This setting is also required for virtual users to
upload; by default, virtual users are treated with anonymous (i.e. maximally
restricted) privilege.
Default: NO
.TP
@ -268,7 +270,9 @@ Default: NO
.TP
.B local_enable
Controls whether local logins are permitted or not. If enabled, normal
user accounts in /etc/passwd may be used to log in.
user accounts in /etc/passwd (or wherever your PAM config references) may be
used to log in. This must be enable for any non-anonymous login to work,
including virtual users.
Default: NO
.TP
@ -584,6 +588,16 @@ client is kicked off.
Default: 300
.TP
.B delay_failed_logins
The number of seconds to pause prior to reporting a failed login.
Default: 1
.TP
.B delay_successful_logins
The number of seconds to pause prior to allowing a successful login.
Default: 0
.TP
.B file_open_mode
The permissions with which uploaded files are created. Umasks are applied
on top of this value. You may wish to change to 0777 if you want uploaded
@ -631,6 +645,11 @@ may be connected. Any additional clients connecting will get an error message.
Default: 0 (unlimited)
.TP
.B max_login_fails
After this many login failures, the session is killed.
Default: 3
.TP
.B max_per_ip
If vsftpd is in standalone mode, this is the maximum number of clients which
may be connected from the same source internet address. A client will get an

View File

@ -1,7 +1,7 @@
#ifndef VSF_VERSION_H
#define VSF_VERSION_H
#define VSF_VERSION "2.0.4"
#define VSF_VERSION "2.0.5"
#endif /* VSF_VERSION_H */