--- /dev/null
+--- vsftpd-3.0.0-org/parseconf.c
++++ vsftpd-3.0.0/parseconf.c
+@@ -227,7 +227,6 @@
+ * race conditions.
+ */
+ if (vsf_sysutil_retval_is_error(retval) ||
+- vsf_sysutil_statbuf_get_uid(p_statbuf) != vsf_sysutil_getuid() ||
+ !vsf_sysutil_statbuf_is_regfile(p_statbuf))
+ {
+ die("config file not owned by correct user, or not a file");
+--- vsftpd-3.0.2-org/secutil.c
++++ vsftpd-3.0.2/secutil.c
+@@ -132,13 +132,13 @@
+ /* Misconfiguration check: don't ever chroot() to a directory writable by
+ * the current user.
+ */
+- if ((options & VSF_SECUTIL_OPTION_CHROOT) &&
++/* if ((options & VSF_SECUTIL_OPTION_CHROOT) &&
+ !(options & VSF_SECUTIL_OPTION_ALLOW_WRITEABLE_ROOT))
+ {
+ if (vsf_sysutil_write_access("/"))
+ {
+ die("vsftpd: refusing to run with writable root inside chroot()");
+ }
+- }
++ } */
+ }
+
+--- vsftpd.orig/str.c
++++ vsftpd/str.c
+@@ -104,6 +104,18 @@
+ return vsf_sysutil_strdup(str_getbuf(p_str));
+ }
+
++const char*
++str_strdup_trimmed(const struct mystr* p_str)
++{
++ const char* p_trimmed = str_getbuf(p_str);
++ int h, t, newlen;
++
++ for (h = 0; h < (int)str_getlen(p_str) && vsf_sysutil_isspace(p_trimmed[h]); h++) ;
++ for (t = str_getlen(p_str) - 1; t >= 0 && vsf_sysutil_isspace(p_trimmed[t]); t--) ;
++ newlen = t - h + 1;
++ return newlen ? vsf_sysutil_strndup(p_trimmed+h, (unsigned int)newlen) : 0L;
++}
++
+ void
+ str_alloc_alt_term(struct mystr* p_str, const char* p_src, char term)
+ {
+--- vsftpd.orig/str.h
++++ vsftpd/str.h
+@@ -31,6 +31,7 @@
+ void str_alloc_filesize_t(struct mystr* p_str, filesize_t the_filesize);
+ void str_copy(struct mystr* p_dest, const struct mystr* p_src);
+ const char* str_strdup(const struct mystr* p_str);
++const char* str_strdup_trimmed(const struct mystr* p_str);
+ void str_empty(struct mystr* p_str);
+ void str_free(struct mystr* p_str);
+ void str_trunc(struct mystr* p_str, unsigned int trunc_len);
+--- vsftpd.orig/sysutil.c 2009-10-02 14:15:18.000000000 +0200
++++ vsftpd/sysutil.c 2009-10-18 11:28:31.000000000 +0200
+@@ -1035,6 +1035,18 @@
+ return strdup(p_str);
+ }
+
++char*
++vsf_sysutil_strndup(const char* p_str, unsigned int p_len)
++{
++ char *new = (char *)malloc(p_len+1);
++
++ if (new == NULL)
++ return NULL;
++
++ new[p_len]='\0';
++ return (char *)memcpy(new, p_str, p_len);
++}
++
+ void
+ vsf_sysutil_memclr(void* p_dest, unsigned int size)
+ {
+--- vsftpd.orig/sysutil.h
++++ vsftpd/sysutil.h
+@@ -186,6 +186,7 @@
+ /* Various string functions */
+ unsigned int vsf_sysutil_strlen(const char* p_text);
+ char* vsf_sysutil_strdup(const char* p_str);
++char* vsf_sysutil_strndup(const char* p_str, unsigned int p_len);
+ void vsf_sysutil_memclr(void* p_dest, unsigned int size);
+ void vsf_sysutil_memcpy(void* p_dest, const void* p_src,
+ const unsigned int size);
+--- vsftpd.orig/ls.c 2009-10-02 14:15:18.000000000 +0200
++++ vsftpd/ls.c 2009-10-18 11:48:29.000000000 +0200
+@@ -289,6 +289,25 @@
+ {
+ goto out;
+ }
++ if (!must_match_at_current_pos)
++ {
++ struct mystr scan_fwd = INIT_MYSTR;
++
++ str_mid_to_end(&name_remain_str, &scan_fwd,
++ indexx + str_getlen(&s_match_needed_str));
++ /* We're allowed to be greedy, test if it match further along
++ * keep advancing indexx while we can still match.
++ */
++ while( (locate_result = str_locate_str(&scan_fwd, &s_match_needed_str)),
++ locate_result.found )
++ {
++ indexx += locate_result.index + str_getlen(&s_match_needed_str);
++ str_mid_to_end(&scan_fwd, &temp_str,
++ locate_result.index + str_getlen(&s_match_needed_str));
++ str_copy(&scan_fwd, &temp_str);
++ }
++ str_free(&scan_fwd);
++ }
+ /* Chop matched string out of remainder */
+ str_mid_to_end(&name_remain_str, &temp_str,
+ indexx + str_getlen(&s_match_needed_str));
+--- vsftpd.orig/features.c
++++ vsftpd/features.c
+@@ -27,6 +27,10 @@
+ vsf_cmdio_write_raw(p_sess, " AUTH TLS\r\n");
+ }
+ }
++ if (tunable_utf8_filesystem)
++ {
++ vsf_cmdio_write_raw(p_sess, " UTF8\r\n");
++ }
+ if (tunable_port_enable)
+ {
+ vsf_cmdio_write_raw(p_sess, " EPRT\r\n");
+--- vsftpd.orig/parseconf.c 2009-08-07 18:46:40.000000000 +0000
++++ vsftpd/parseconf.c 2010-02-25 13:28:06.000000000 +0000
+@@ -28,6 +28,7 @@
+ parseconf_bool_array[] =
+ {
+ { "anonymous_enable", &tunable_anonymous_enable },
++ { "utf8_filesystem", &tunable_utf8_filesystem },
+ { "local_enable", &tunable_local_enable },
+ { "pasv_enable", &tunable_pasv_enable },
+ { "port_enable", &tunable_port_enable },
+--- vsftpd.orig/tunables.c
++++ vsftpd/tunables.c
+@@ -10,6 +10,7 @@
+
+ int tunable_anonymous_enable;
+ int tunable_local_enable;
++int tunable_utf8_filesystem;
+ int tunable_pasv_enable;
+ int tunable_port_enable;
+ int tunable_chroot_local_user;
+@@ -150,6 +151,7 @@
+ {
+ tunable_anonymous_enable = 1;
+ tunable_local_enable = 0;
++ tunable_utf8_filesystem = 0;
+ tunable_pasv_enable = 1;
+ tunable_port_enable = 1;
+ tunable_chroot_local_user = 0;
+--- vsftpd.orig/tunables.h
++++ vsftpd/tunables.h
+@@ -11,6 +11,7 @@
+ /* Booleans */
+ extern int tunable_anonymous_enable; /* Allow anon logins */
+ extern int tunable_local_enable; /* Allow local logins */
++extern int tunable_utf8_filesystem; /* Server uses UTF8 Filesystem */
+ extern int tunable_pasv_enable; /* Allow PASV */
+ extern int tunable_port_enable; /* Allow PORT */
+ extern int tunable_chroot_local_user; /* Restrict local to home dir */
--- /dev/null
+--- a/twoprocess.c
++++ b/twoprocess.c
+@@ -41,7 +41,8 @@
+ struct mystr* p_chroot_str,
+ struct mystr* p_chdir_str,
+ const struct mystr* p_user_str,
+- const struct mystr* p_orig_user_str);
++ const struct mystr* p_orig_user_str,
++ int do_chroot);
+
+ static void
+ handle_sigchld(void* duff)
+@@ -454,7 +455,7 @@
+ secutil_option |= VSF_SECUTIL_OPTION_ALLOW_WRITEABLE_ROOT;
+ }
+ calculate_chdir_dir(was_anon, &userdir_str, &chroot_str, &chdir_str,
+- p_user_str, p_orig_user_str);
++ p_user_str, p_orig_user_str, do_chroot);
+ vsf_secutil_change_credentials(p_user_str, &userdir_str, &chroot_str,
+ 0, secutil_option);
+ if (!str_isempty(&chdir_str))
+@@ -522,7 +523,8 @@
+ struct mystr* p_chroot_str,
+ struct mystr* p_chdir_str,
+ const struct mystr* p_user_str,
+- const struct mystr* p_orig_user_str)
++ const struct mystr* p_orig_user_str,
++ int do_chroot)
+ {
+ if (!anon_login)
+ {
+@@ -542,7 +544,7 @@
+ {
+ str_alloc_text(p_chroot_str, tunable_anon_root);
+ }
+- else if (!anon_login && tunable_local_root)
++ else if (!anon_login && tunable_local_root && !do_chroot)
+ {
+ str_alloc_text(p_chroot_str, tunable_local_root);
+ if (tunable_user_sub_token)
$(REMOVE)/ntp-$(NTP_VER)
$(TOUCH)
+VSFTPD_PATCH = vsftpd-3.0.3.patch
+VSFTPD_PATCH += vsftpd-disable-capabilities.patch
+VSFTPD_PATCH += vsftpd-fixchroot.patch
+VSFTPD_PATCH += vsftpd-login-blank-password.patch
+
$(D)/vsftpd: $(ARCHIVE)/vsftpd-$(VSFTPD_VER).tar.gz | $(TARGETPREFIX)
+ $(REMOVE)/vsftpd-$(VSFTPD_VER)
$(START_BUILD)
$(UNTAR)/vsftpd-$(VSFTPD_VER).tar.gz
pushd $(BUILD_TMP)/vsftpd-$(VSFTPD_VER) && \
- mv $(BUILD_TMP)/vsftpd-$(VSFTPD_VER)/parseconf.c $(BUILD_TMP)/vsftpd-$(VSFTPD_VER)/parseconf.tmp && \
- sed -e 's/die("config file not owned by correct user, or not a file");/\/\/die("config file not owned by correct user, or not a file");/g' $(BUILD_TMP)/vsftpd-$(VSFTPD_VER)/parseconf.tmp > $(BUILD_TMP)/vsftpd-$(VSFTPD_VER)/parseconf.c && \
cp $(PATCHES)/vsftpd-new.conf vsftpd.conf && \
- $(PATCH)/vsftpd-new.diff && \
- TARGETPREFIX=$(TARGETPREFIX) $(MAKE) CC=$(TARGET)-gcc CFLAGS="-pipe -O2 -g0 -I$(TARGETPREFIX)/include" LDFLAGS="$(TARGET_LDFLAGS) -Wl,-rpath-link,$(TARGETLIB)" && \
- mkdir -p $(TARGETPREFIX)/sbin && \
+ $(call apply_patches, $(VSFTPD_PATCH)) && \
+ sed -i -e 's/.*VSF_BUILD_PAM/#undef VSF_BUILD_PAM/' builddefs.h && \
+ sed -i -e 's/.*VSF_BUILD_SSL/#define VSF_BUILD_SSL/' builddefs.h && \
+ $(MAKE) CC=$(TARGET)-gcc $(BUILDENV) LIBS="-lcrypt -lcrypto -lssl" && \
install -m755 vsftpd $(TARGETPREFIX)/sbin/vsftpd && \
install -m 644 vsftpd.conf $(TARGETPREFIX)/etc/vsftpd.conf && \
install -d $(TARGETPREFIX)/share/empty && \