diff --git a/Changelog b/Changelog index ff866c1..514bb78 100644 --- a/Changelog +++ b/Changelog @@ -1253,3 +1253,24 @@ no apparent security impact. At this point: v2.3.3 released! =============================== + +- Fix compile. Extreme suckage. + +At this point: v2.3.4 released! +=============================== + +- Try and force glibc to cache zoneinfo files in an attempt to work around +glibc parsing vulnerability. Thanks to Kingcope. +- Only report CHMOD in SITE HELP if it's enabled. Thanks to Martin Schwenke +. +- Some simple fixes and cleanups from Thorsten Brehm . +- Only advertise "AUTH SSL" if one of SSLv2, SSLv3 is enabled. Thanks to +steve willing . +- Handle connect() failures properly. Thanks to Takayuki Nagata +. +- Add stronger checks for the configuration error of running with a writeable +root directory inside a chroot(). This may bite people who carelessly turned +on chroot_local_user but such is life. + +At this point: v2.3.5 released! +=============================== diff --git a/FAQ b/FAQ index 22443e6..59fe56b 100644 --- a/FAQ +++ b/FAQ @@ -18,13 +18,14 @@ A2) If you run vsftpd in "standalone" mode with the setting listen=YES, then you can investigate the setting (e.g.): max_clients=10 -Q) Help! I'm getting the error message "refusing to run with writable anonymous -root". +Q) Help! I'm getting the error message "refusing to run with writable root". A) vsftpd is protecting against dangerous configurations. The cause of this message is usually dodgy ownership of the ftp home directory. The home directory should NOT be owned by the ftp user itself. Neither should it be writable by the ftp user. A way to fix this is: chown root ~ftp; chmod -w ~ftp +Another cause might be an attempt to use chroot_local_user without setting up +the directory ownership properly. Q) Help! I'm getting the error message "str_getpwnam". A) The most likely cause of this is that the user that is configured as the diff --git a/README b/README index 45a07a2..054206a 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is vsftpd, version 2.3.3 +This is vsftpd, version 2.3.5 Author: Chris Evans Contact: scarybeasts@gmail.com Website: http://vsftpd.beasts.org/ diff --git a/access.c b/access.c index 3b32767..2abd67f 100644 --- a/access.c +++ b/access.c @@ -16,6 +16,7 @@ int vsf_access_check_file(const struct mystr* p_filename_str) { static struct mystr s_access_str; + unsigned int iters = 0; if (!tunable_deny_file) { @@ -25,7 +26,7 @@ vsf_access_check_file(const struct mystr* p_filename_str) { str_alloc_text(&s_access_str, tunable_deny_file); } - if (vsf_filename_passes_filter(p_filename_str, &s_access_str)) + if (vsf_filename_passes_filter(p_filename_str, &s_access_str, &iters)) { return 0; } @@ -45,6 +46,7 @@ int vsf_access_check_file_visible(const struct mystr* p_filename_str) { static struct mystr s_access_str; + unsigned int iters = 0; if (!tunable_hide_file) { @@ -54,7 +56,7 @@ vsf_access_check_file_visible(const struct mystr* p_filename_str) { str_alloc_text(&s_access_str, tunable_hide_file); } - if (vsf_filename_passes_filter(p_filename_str, &s_access_str)) + if (vsf_filename_passes_filter(p_filename_str, &s_access_str, &iters)) { return 0; } diff --git a/features.c b/features.c index da14623..1212980 100644 --- a/features.c +++ b/features.c @@ -18,8 +18,14 @@ handle_feat(struct vsf_session* p_sess) vsf_cmdio_write_hyphen(p_sess, FTP_FEAT, "Features:"); if (tunable_ssl_enable) { - vsf_cmdio_write_raw(p_sess, " AUTH SSL\r\n"); - vsf_cmdio_write_raw(p_sess, " AUTH TLS\r\n"); + if (tunable_sslv2 || tunable_sslv3) + { + vsf_cmdio_write_raw(p_sess, " AUTH SSL\r\n"); + } + if (tunable_tlsv1) + { + vsf_cmdio_write_raw(p_sess, " AUTH TLS\r\n"); + } } if (tunable_port_enable) { diff --git a/logging.c b/logging.c index 2a1ca45..7675657 100644 --- a/logging.c +++ b/logging.c @@ -324,6 +324,8 @@ vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess, struct mystr* p_str, case kVSFLogEntryDebug: str_append_text(p_str, "DEBUG"); break; + case kVSFLogEntryNull: + /* Fall through */ default: bug("bad entry_type in vsf_log_do_log"); break; diff --git a/oneprocess.c b/oneprocess.c index 5dbabea..65e36e0 100644 --- a/oneprocess.c +++ b/oneprocess.c @@ -119,6 +119,10 @@ vsf_one_process_login(struct vsf_session* p_sess, p_sess->is_anonymous = 1; process_post_login(p_sess); break; + case kVSFLoginNull: + /* Fall through. */ + case kVSFLoginReal: + /* Fall through. */ default: bug("bad state in vsf_one_process_login"); break; diff --git a/postlogin.c b/postlogin.c index 8df7c0b..5daee89 100644 --- a/postlogin.c +++ b/postlogin.c @@ -1485,7 +1485,15 @@ handle_site(struct vsf_session* p_sess) } else if (str_equal_text(&p_sess->ftp_arg_str, "HELP")) { - vsf_cmdio_write(p_sess, FTP_SITEHELP, "CHMOD UMASK HELP"); + if (tunable_write_enable && + tunable_chmod_enable) + { + vsf_cmdio_write(p_sess, FTP_SITEHELP, "CHMOD UMASK HELP"); + } + else + { + vsf_cmdio_write(p_sess, FTP_SITEHELP, "UMASK HELP"); + } } else { diff --git a/ptracesandbox.c b/ptracesandbox.c index 1f2bbcc..37efd5a 100644 --- a/ptracesandbox.c +++ b/ptracesandbox.c @@ -652,7 +652,7 @@ get_action(struct pt_sandbox* p_sandbox) } ret = 0; out: - memset(&p_sandbox->regs, '\0', sizeof(&p_sandbox->regs)); + memset(&p_sandbox->regs, '\0', sizeof(p_sandbox->regs)); return ret; } diff --git a/secutil.c b/secutil.c index 1cd9d58..e3debce 100644 --- a/secutil.c +++ b/secutil.c @@ -129,5 +129,15 @@ vsf_secutil_change_credentials(const struct mystr* p_user_str, { vsf_sysutil_set_no_procs(); } + /* Misconfiguration check: don't ever chroot() to a directory writable by + * the current user. + */ + if (options & VSF_SECUTIL_OPTION_CHROOT) + { + if (vsf_sysutil_write_access("/")) + { + die("vsftpd: refusing to run with writable root inside chroot()"); + } + } } diff --git a/sysstr.c b/sysstr.c index 42fd4b4..d86cdf1 100644 --- a/sysstr.c +++ b/sysstr.c @@ -80,6 +80,8 @@ str_open(const struct mystr* p_str, const enum EVSFSysStrOpenMode mode) case kVSFSysStrOpenReadOnly: open_mode = kVSFSysUtilOpenReadOnly; break; + case kVSFSysStrOpenUnknown: + /* Fall through */ default: bug("unknown mode value in str_open"); break; diff --git a/sysutil.c b/sysutil.c index cf16c1f..20a8e3c 100644 --- a/sysutil.c +++ b/sysutil.c @@ -1340,6 +1340,7 @@ vsf_sysutil_statbuf_get_perms(const struct vsf_sysutil_statbuf* p_statbuf) case S_IFSOCK: perms[0] = 's'; break; case S_IFCHR: perms[0] = 'c'; break; case S_IFBLK: perms[0] = 'b'; break; + default: break; } if (p_stat->st_mode & S_IRUSR) perms[1] = 'r'; if (p_stat->st_mode & S_IWUSR) perms[2] = 'w'; @@ -1603,6 +1604,8 @@ vsf_sysutil_get_error(void) case ENOENT: retval = kVSFSysUtilErrNOENT; break; + default: + break; } return retval; } @@ -1704,10 +1707,14 @@ vsf_sysutil_accept_timeout(int fd, struct vsf_sysutil_sockaddr* p_sockaddr, retval = select(fd + 1, &accept_fdset, NULL, NULL, &timeout); saved_errno = errno; vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); - } while (retval < 0 && saved_errno == EINTR); - if (retval == 0) + } + while (retval < 0 && saved_errno == EINTR); + if (retval <= 0) { - errno = EAGAIN; + if (retval == 0) + { + errno = EAGAIN; + } return -1; } } @@ -1785,10 +1792,13 @@ vsf_sysutil_connect_timeout(int fd, const struct vsf_sysutil_sockaddr* p_addr, vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); } while (retval < 0 && saved_errno == EINTR); - if (retval == 0) + if (retval <= 0) { + if (retval == 0) + { + errno = EAGAIN; + } retval = -1; - errno = EAGAIN; } else { @@ -1798,6 +1808,11 @@ vsf_sysutil_connect_timeout(int fd, const struct vsf_sysutil_sockaddr* p_addr, { die("getsockopt"); } + if (retval != 0) + { + errno = retval; + retval = -1; + } } } if (wait_seconds > 0) @@ -2584,6 +2599,19 @@ vsf_sysutil_tzset(void) s_timezone *= -1; } } + /* Call in to the time subsystem again now that TZ is set, trying to force + * caching of the actual zoneinfo for the timezone. + */ + p_tm = localtime(&the_time); + if (p_tm == NULL) + { + die("localtime #2"); + } + p_tm = gmtime(&the_time); + if (p_tm == NULL) + { + die("gmtime"); + } } const char* diff --git a/twoprocess.c b/twoprocess.c index 4cede92..20aceb3 100644 --- a/twoprocess.c +++ b/twoprocess.c @@ -349,6 +349,8 @@ process_login_req(struct vsf_session* p_sess) common_do_login(p_sess, &p_sess->user_str, do_chroot, 0); } break; + case kVSFLoginNull: + /* Fall through */ default: bug("weird state in process_login_request"); break; @@ -436,13 +438,6 @@ common_do_login(struct vsf_session* p_sess, const struct mystr* p_user_str, str_free(&chroot_str); str_free(&chdir_str); str_free(&userdir_str); - /* Guard against the config error of having the anonymous ftp tree owned - * by the user we are running as - */ - if (was_anon && vsf_sysutil_write_access("/")) - { - die("vsftpd: refusing to run with writable anonymous root"); - } p_sess->is_anonymous = anon; process_post_login(p_sess); bug("should not get here: common_do_login"); diff --git a/vsftpd.conf b/vsftpd.conf index 1a72daa..cc1c607 100644 --- a/vsftpd.conf +++ b/vsftpd.conf @@ -92,6 +92,9 @@ 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(). +# (Warning! chroot'ing can be very dangerous. If using chroot, make sure that +# the user does not have write access to the top level directory within the +# chroot) #chroot_local_user=YES #chroot_list_enable=YES # (default follows) diff --git a/vsftpver.h b/vsftpver.h index 7a828df..e7ce230 100644 --- a/vsftpver.h +++ b/vsftpver.h @@ -1,7 +1,7 @@ #ifndef VSF_VERSION_H #define VSF_VERSION_H -#define VSF_VERSION "2.3.3" +#define VSF_VERSION "2.3.5" #endif /* VSF_VERSION_H */