diff --git a/.gitignore b/.gitignore index 70973b1..cb09e98 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -# master/f17/f16 -/proftpd-1.3.4b.tar.gz +# master/f19/f18/f17 +/proftpd-1.3.4c.tar.gz /proftpd-mod-geoip-0.3.tar.gz /proftpd-mod-vroot-0.9.2.tar.gz /Test-Unit-0.14.tar.gz diff --git a/proftpd-1.3.4a-bug3744.patch b/proftpd-1.3.4a-bug3744.patch deleted file mode 100644 index dc7ecac..0000000 --- a/proftpd-1.3.4a-bug3744.patch +++ /dev/null @@ -1,380 +0,0 @@ -Index: modules/mod_ls.c -=================================================================== -RCS file: /cvsroot/proftp/proftpd/modules/mod_ls.c,v -retrieving revision 1.187 -diff -u -r1.187 mod_ls.c ---- modules/mod_ls.c 5 Nov 2011 23:01:58 -0000 1.187 -+++ modules/mod_ls.c 1 Feb 2012 18:57:20 -0000 -@@ -81,6 +81,7 @@ - - /* ls options */ - static int -+ opt_1 = 0, - opt_a = 0, - opt_A = 0, - opt_B = 0, -@@ -395,7 +396,6 @@ - p = cmd->tmp_pool; - - if (pr_fsio_lstat(name, &st) == 0) { -- - char *display_name = NULL; - - suffix[0] = suffix[1] = '\0'; -@@ -493,21 +493,24 @@ - break; - } - -- if (list_times_gmt) -+ if (list_times_gmt) { - t = pr_gmtime(p, (time_t *) &sort_time); -- else -+ -+ } else { - t = pr_localtime(p, (time_t *) &sort_time); -+ } - - if (opt_F) { -- if (S_ISLNK(st.st_mode)) -+ if (S_ISLNK(st.st_mode)) { - suffix[0] = '@'; - -- else if (S_ISDIR(st.st_mode)) { -+ } else if (S_ISDIR(st.st_mode)) { - suffix[0] = '/'; - rval = 1; - -- } else if (st.st_mode & 0111) -+ } else if (st.st_mode & 0111) { - suffix[0] = '*'; -+ } - } - - if (opt_l) { -@@ -576,32 +579,38 @@ - m[2] = (mode & S_IWUSR) ? 'w' : '-'; - m[1] = (mode & S_IRUSR) ? 'r' : '-'; - -- if (ls_curtime - sort_time > 180 * 24 * 60 * 60) -+ if (ls_curtime - sort_time > 180 * 24 * 60 * 60) { - snprintf(timeline, sizeof(timeline), "%5d", t->tm_year+1900); - -- else -+ } else { - snprintf(timeline, sizeof(timeline), "%02d:%02d", t->tm_hour, - t->tm_min); -+ } - - ls_fmt_filesize(s, sizeof(s), st.st_size); - -- if (!opt_n) { -- -- /* Format nameline using user/group names. */ -- snprintf(nameline, sizeof(nameline)-1, -- "%s %3d %-8s %-8s %s %s %2d %s %s", m, (int) st.st_nlink, -- MAP_UID(st.st_uid), MAP_GID(st.st_gid), s, -- months[t->tm_mon], t->tm_mday, timeline, -+ if (opt_1) { -+ /* One file per line, with no info other than the file name. Easy. */ -+ snprintf(nameline, sizeof(nameline)-1, "%s", - pr_fs_encode_path(cmd->tmp_pool, display_name)); - - } else { -- -- /* Format nameline using user/group IDs. */ -- snprintf(nameline, sizeof(nameline)-1, -- "%s %3d %-8u %-8u %s %s %2d %s %s", m, (int) st.st_nlink, -- (unsigned) st.st_uid, (unsigned) st.st_gid, s, -- months[t->tm_mon], t->tm_mday, timeline, -- pr_fs_encode_path(cmd->tmp_pool, name)); -+ if (!opt_n) { -+ /* Format nameline using user/group names. */ -+ snprintf(nameline, sizeof(nameline)-1, -+ "%s %3d %-8s %-8s %s %s %2d %s %s", m, (int) st.st_nlink, -+ MAP_UID(st.st_uid), MAP_GID(st.st_gid), s, -+ months[t->tm_mon], t->tm_mday, timeline, -+ pr_fs_encode_path(cmd->tmp_pool, display_name)); -+ -+ } else { -+ /* Format nameline using user/group IDs. */ -+ snprintf(nameline, sizeof(nameline)-1, -+ "%s %3d %-8u %-8u %s %s %2d %s %s", m, (int) st.st_nlink, -+ (unsigned) st.st_uid, (unsigned) st.st_gid, s, -+ months[t->tm_mon], t->tm_mday, timeline, -+ pr_fs_encode_path(cmd->tmp_pool, name)); -+ } - } - - nameline[sizeof(nameline)-1] = '\0'; -@@ -611,40 +620,45 @@ - - suffix[0] = '\0'; - if (opt_F && pr_fsio_stat(name, &st) == 0) { -- if (S_ISLNK(st.st_mode)) -+ if (S_ISLNK(st.st_mode)) { - suffix[0] = '@'; - -- else if (S_ISDIR(st.st_mode)) -+ } else if (S_ISDIR(st.st_mode)) { - suffix[0] = '/'; - -- else if (st.st_mode & 0111) -+ } else if (st.st_mode & 0111) { - suffix[0] = '*'; -+ } - } - - if (!opt_L && list_show_symlinks) { -- if (sizeof(nameline) - strlen(nameline) > 4) -+ if (sizeof(nameline) - strlen(nameline) > 4) { - snprintf(buf, sizeof(nameline) - strlen(nameline) - 4, - " -> %s", l); -- else -+ } else { - pr_log_pri(PR_LOG_NOTICE, "notice: symlink '%s' yields an " - "excessive string, ignoring", name); -+ } - } - - nameline[sizeof(nameline)-1] = '\0'; - } - -- if (opt_STAT) -+ if (opt_STAT) { - pr_response_add(R_211, "%s%s", nameline, suffix); -- else -+ -+ } else { - addfile(cmd, nameline, suffix, sort_time, st.st_size); -+ } - } - - } else { - if (S_ISREG(st.st_mode) || - S_ISDIR(st.st_mode) || -- S_ISLNK(st.st_mode)) -+ S_ISLNK(st.st_mode)) { - addfile(cmd, pr_fs_encode_path(cmd->tmp_pool, name), suffix, - sort_time, st.st_size); -+ } - } - } - -@@ -1302,6 +1316,7 @@ - switch (**opt) { - case '1': - if (strcmp(session.curr_cmd, C_STAT) != 0) { -+ opt_1 = 1; - opt_l = opt_C = 0; - } - break; -@@ -1354,6 +1369,7 @@ - if (strcmp(session.curr_cmd, C_NLST) != 0) { - opt_l = 1; - opt_C = 0; -+ opt_1 = 0; - } - break; - -@@ -1422,7 +1438,7 @@ - while ((*opt)++ && isalnum((int) **opt)) { - switch (**opt) { - case '1': -- opt_l = opt_C = 0; -+ opt_1 = opt_l = opt_C = 0; - break; - - case 'A': -@@ -1571,8 +1587,8 @@ - ls_curtime = time(NULL); - - if (clearflags) { -- opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_h = opt_n = opt_r = -- opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; -+ opt_1 = opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_h = opt_n = -+ opt_r = opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; - } - - if (have_options(cmd, arg)) { -@@ -1671,8 +1687,10 @@ - - /* Open data connection */ - if (!opt_STAT) { -- if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) -+ if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) { - return -1; -+ } -+ - session.sf_flags |= SF_ASCII_OVERRIDE; - } - -@@ -1705,7 +1723,6 @@ - skiparg = TRUE; - - } else { -- - skiparg = FALSE; - - if (use_globbing && -@@ -1945,6 +1962,10 @@ - return -1; - } - -+ /* XXX Note that "NLST " was sent, we might be receiving paths -+ * here, not just file names. And that is not what dir_hide_file() is -+ * expecting. -+ */ - if (dir_hide_file(file)) - return 1; - -@@ -1970,6 +1991,25 @@ - } - #endif /* PR_USE_NLS */ - -+ if (opt_1) { -+ char *ptr; -+ -+ /* If the -1 option is configured, we want to make sure that we only -+ * display a file, not a path. And it's possible that we given a path -+ * here. -+ */ -+ ptr = strrchr(display_name, '/'); -+ if (ptr != NULL) { -+ size_t display_namelen; -+ -+ display_namelen = strlen(display_name); -+ if (display_namelen > 1) { -+ /* Make sure that we handle a possible display_name of '/' properly. */ -+ display_name = ptr + 1; -+ } -+ } -+ } -+ - /* Be sure to flush the output */ - res = sendline(0, "%s\n", pr_fs_encode_path(cmd->tmp_pool, display_name)); - if (res < 0) -@@ -2098,8 +2138,16 @@ - continue; - - if (!curdir) { -- char *str = pr_fs_encode_path(cmd->tmp_pool, -- pdircat(cmd->tmp_pool, dir, p, NULL)); -+ char *str = NULL; -+ -+ if (opt_1) { -+ /* Send just the file name, not the path. */ -+ str = pr_fs_encode_path(cmd->tmp_pool, p); -+ -+ } else { -+ str = pr_fs_encode_path(cmd->tmp_pool, -+ pdircat(cmd->tmp_pool, dir, p, NULL)); -+ } - - if (sendline(0, "%s\n", str) < 0) { - count = -1; -@@ -2204,26 +2252,32 @@ - fakeuser = get_param_ptr(CURRENT_CONF, "DirFakeUser", FALSE); - - /* Check for a configured "logged in user" DirFakeUser. */ -- if (fakeuser && strcmp(fakeuser, "~") == 0) -+ if (fakeuser != NULL && -+ strcmp(fakeuser, "~") == 0) { - fakeuser = session.user; -+ } - - fakegroup = get_param_ptr(CURRENT_CONF, "DirFakeGroup", FALSE); - - /* Check for a configured "logged in user" DirFakeGroup. */ -- if (fakegroup && strcmp(fakegroup, "~") == 0) -+ if (fakegroup != NULL && -+ strcmp(fakegroup, "~") == 0) { - fakegroup = session.group; -+ } - - fake_mode = get_param_ptr(CURRENT_CONF, "DirFakeMode", FALSE); - if (fake_mode) { - fakemode = *fake_mode; - have_fake_mode = TRUE; - -- } else -+ } else { - have_fake_mode = FALSE; -+ } - - tmp = get_param_ptr(TOPLEVEL_CONF, "TimesGMT", FALSE); -- if (tmp != NULL) -+ if (tmp != NULL) { - list_times_gmt = *tmp; -+ } - - res = dolist(cmd, pr_fs_decode_path(cmd->tmp_pool, cmd->arg), TRUE); - -@@ -2231,8 +2285,9 @@ - pr_data_abort(0, 0); - res = -1; - -- } else if (session.sf_flags & SF_XFER) -+ } else if (session.sf_flags & SF_XFER) { - ls_done(cmd); -+ } - - opt_l = 0; - -@@ -2415,8 +2470,9 @@ - list_nfiles.logged = list_ndirs.logged = list_ndepth.logged = FALSE; - - tmp = get_param_ptr(TOPLEVEL_CONF, "ShowSymlinks", FALSE); -- if (tmp != NULL) -+ if (tmp != NULL) { - list_show_symlinks = *tmp; -+ } - - target = cmd->argc == 1 ? "." : - pr_fs_decode_path(cmd->tmp_pool, cmd->arg); -@@ -2444,8 +2500,8 @@ - } - - /* Clear the listing option flags. */ -- opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_n = opt_r = opt_R = -- opt_S = opt_t = opt_STAT = opt_L = 0; -+ opt_1 = opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_n = opt_r = -+ opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; - - if (have_options(cmd, target)) { - if (!list_strict_opts) { -@@ -2602,8 +2658,10 @@ - - } else { - if (list_flags & LS_FL_NO_ERROR_IF_ABSENT) { -- if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) -+ if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) { - return PR_ERROR(cmd); -+ } -+ - session.sf_flags |= SF_ASCII_OVERRIDE; - pr_response_add(R_226, _("Transfer complete")); - ls_done(cmd); -@@ -2617,8 +2675,10 @@ - - } else { - if (list_flags & LS_FL_NO_ERROR_IF_ABSENT) { -- if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) -+ if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) { - return PR_ERROR(cmd); -+ } -+ - session.sf_flags |= SF_ASCII_OVERRIDE; - pr_response_add(R_226, _("Transfer complete")); - ls_done(cmd); -@@ -2631,8 +2691,10 @@ - } - } - -- if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) -+ if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) { - return PR_ERROR(cmd); -+ } -+ - session.sf_flags |= SF_ASCII_OVERRIDE; - - /* Iterate through each matching entry */ diff --git a/proftpd-1.3.4a-bug3747.patch b/proftpd-1.3.4a-bug3747.patch deleted file mode 100644 index 80d933f..0000000 --- a/proftpd-1.3.4a-bug3747.patch +++ /dev/null @@ -1,193 +0,0 @@ -Index: modules/mod_facts.c -=================================================================== -RCS file: /cvsroot/proftp/proftpd/modules/mod_facts.c,v -retrieving revision 1.47 -diff -u -r1.47 mod_facts.c ---- modules/mod_facts.c 17 Jan 2012 00:51:02 -0000 1.47 -+++ modules/mod_facts.c 3 Feb 2012 06:56:26 -0000 -@@ -46,7 +46,9 @@ - #define FACTS_OPT_SHOW_UNIX_MODE 0x00040 - #define FACTS_OPT_SHOW_UNIX_OWNER 0x00080 - --#define FACTS_MLINFO_FL_SHOW_SYMLINKS 0x00001 -+static unsigned long facts_mlinfo_opts = 0; -+#define FACTS_MLINFO_FL_SHOW_SYMLINKS 0x00001 -+#define FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK 0x00002 - - struct mlinfo { - pool *pool; -@@ -339,7 +341,56 @@ - info->st.st_ino = target_st.st_ino; - - if (flags & FACTS_MLINFO_FL_SHOW_SYMLINKS) { -- info->type = "OS.unix=symlink"; -+ -+ /* Do we use the proper RFC 3659 syntax (i.e. following the BNF rules -+ * of RFC 3659), which would be: -+ * -+ * type=OS.unix=symlink -+ * -+ * See: -+ * http://www.rfc-editor.org/errata_search.php?rfc=3659 -+ * -+ * and search for "OS.unix=slink". -+ * -+ * Or do we use the syntax in the _examples_ presented in RFC 3659, -+ * which is what clients such as FileZilla expect: -+ * -+ * type=OS.unix=slink: -+ * -+ * See: -+ * http://trac.filezilla-project.org/ticket/4490 -+ */ -+ -+ if (flags & FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK) { -+ char target[PR_TUNABLE_PATH_MAX+1]; -+ int targetlen; -+ -+ targetlen = pr_fsio_readlink(path, target, sizeof(target)-1); -+ if (targetlen < 0) { -+ int xerrno = errno; -+ -+ pr_log_debug(DEBUG4, MOD_FACTS_VERSION -+ ": error reading symlink '%s': %s", path, strerror(xerrno)); -+ -+ errno = xerrno; -+ return -1; -+ } -+ -+ if (targetlen >= sizeof(target)-1) { -+ targetlen = sizeof(target)-1; -+ } -+ -+ target[targetlen] = '\0'; -+ -+ info->type = pstrcat(info->pool, "OS.unix=slink:", -+ dir_best_path(info->pool, target), NULL); -+ -+ } else { -+ /* Use the proper syntax. Too bad for the not-really-compliant -+ * FileZilla. -+ */ -+ info->type = "OS.unix=symlink"; -+ } - - } else { - info->type = "file"; -@@ -1024,6 +1075,10 @@ - if (ptr && - *ptr == TRUE) { - flags |= FACTS_MLINFO_FL_SHOW_SYMLINKS; -+ -+ if (facts_mlinfo_opts & FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK) { -+ flags |= FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK; -+ } - } - - best_path = dir_best_path(cmd->tmp_pool, decoded_path); -@@ -1087,11 +1142,11 @@ - } - - /* Open data connection */ -- session.sf_flags |= SF_ASCII_OVERRIDE; - if (pr_data_open(NULL, C_MLSD, PR_NETIO_IO_WR, 0) < 0) { - pr_fsio_closedir(dirh); - return PR_ERROR(cmd); - } -+ session.sf_flags |= SF_ASCII_OVERRIDE; - - pr_fs_clear_cache(); - facts_mlinfobuf_init(); -@@ -1207,6 +1262,10 @@ - if (ptr && - *ptr == TRUE) { - flags |= FACTS_MLINFO_FL_SHOW_SYMLINKS; -+ -+ if (facts_mlinfo_opts & FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK) { -+ flags |= FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK; -+ } - } - - fake_mode = get_param_ptr(get_dir_ctxt(cmd->tmp_pool, (char *) decoded_path), -@@ -1274,10 +1333,15 @@ - /* XXX What about chroots? */ - - if (flags & FACTS_MLINFO_FL_SHOW_SYMLINKS) { -- /* If we are supposed to symlinks, then use dir_best_path() to get the -- * full path, including dereferencing the symlink. -- */ -- info.path = dir_best_path(cmd->tmp_pool, path); -+ if (flags & FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK) { -+ info.path = dir_canonical_path(cmd->tmp_pool, path); -+ -+ } else { -+ /* If we are supposed to show symlinks, then use dir_best_path() to get -+ * the full path, including dereferencing the symlink. -+ */ -+ info.path = dir_best_path(cmd->tmp_pool, path); -+ } - - } else { - info.path = dir_canonical_path(cmd->tmp_pool, path); -@@ -1407,6 +1471,36 @@ - return PR_HANDLED(cmd); - } - -+/* usage: FactsOptions opt1 ... optN */ -+MODRET set_factsoptions(cmd_rec *cmd) { -+ register unsigned int i; -+ config_rec *c; -+ unsigned long opts = 0UL; -+ -+ if (cmd->argc-1 == 0) { -+ CONF_ERROR(cmd, "wrong number of parameters"); -+ } -+ -+ CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL); -+ -+ c = add_config_param(cmd->argv[0], 1, NULL); -+ -+ for (i = 1; i < cmd->argc; i++) { -+ if (strncmp(cmd->argv[i], "UseSlink", 9) == 0) { -+ opts |= FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK; -+ -+ } else { -+ CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown FactsOption '", -+ cmd->argv[i], "'", NULL)); -+ } -+ } -+ -+ c->argv[0] = palloc(c->pool, sizeof(unsigned long)); -+ *((unsigned long *) c->argv[0]) = opts; -+ -+ return PR_HANDLED(cmd); -+} -+ - /* Initialization functions - */ - -@@ -1426,8 +1520,14 @@ - advertise = *((int *) c->argv[0]); - } - -- if (advertise == FALSE) -+ if (advertise == FALSE) { - return 0; -+ } -+ -+ c = find_config(main_server->conf, CONF_PARAM, "FactsOptions", FALSE); -+ if (c) { -+ facts_mlinfo_opts = *((unsigned long *) c->argv[0]); -+ } - - facts_opts = FACTS_OPT_SHOW_MODIFY|FACTS_OPT_SHOW_PERM|FACTS_OPT_SHOW_SIZE| - FACTS_OPT_SHOW_TYPE|FACTS_OPT_SHOW_UNIQUE|FACTS_OPT_SHOW_UNIX_GROUP| -@@ -1451,6 +1551,7 @@ - - static conftable facts_conftab[] = { - { "FactsAdvertise", set_factsadvertise, NULL }, -+ { "FactsOptions", set_factsoptions, NULL }, - { NULL } - }; - - diff --git a/proftpd-1.3.4b-bug3841.patch b/proftpd-1.3.4b-bug3841.patch deleted file mode 100644 index e070d1f..0000000 --- a/proftpd-1.3.4b-bug3841.patch +++ /dev/null @@ -1,511 +0,0 @@ ---- configure.in -+++ configure.in -@@ -1653,7 +1653,7 @@ LDFLAGS=$old_LDFLAGS - AC_PROG_GCC_TRADITIONAL - AC_TYPE_SIGNAL - AC_FUNC_VPRINTF --AC_CHECK_FUNCS(bcopy crypt fdatasync fgetgrent fgetpwent fgetspent flock fpathconf freeaddrinfo futimes getpgid getpgrp nl_langinfo) -+AC_CHECK_FUNCS(bcopy crypt fdatasync fgetgrent fgetpwent fgetspent flock fpathconf freeaddrinfo futimes getpgid getpgrp mkdtemp nl_langinfo) - AC_CHECK_FUNC(gai_strerror, - AC_DEFINE(HAVE_GAI_STRERROR, 1, - [Define if you have the gai_strerror() function]), ---- configure -+++ configure -@@ -27910,7 +27910,8 @@ done - - - --for ac_func in bcopy crypt fdatasync fgetgrent fgetpwent fgetspent flock fpathconf freeaddrinfo futimes getpgid getpgrp nl_langinfo -+ -+for ac_func in bcopy crypt fdatasync fgetgrent fgetpwent fgetspent flock fpathconf freeaddrinfo futimes getpgid getpgrp mkdtemp nl_langinfo - do - as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` - { echo "$as_me:$LINENO: checking for $ac_func" >&5 ---- config.h.in -+++ config.h.in -@@ -375,6 +375,9 @@ - /* Define if you have the mkdir function. */ - #undef HAVE_MKDIR - -+/* Define if you have the mkdtemp function. */ -+#undef HAVE_MKDTEMP -+ - /* Define if you have the mkstemp function. */ - #undef HAVE_MKSTEMP - ---- contrib/mod_sftp/fxp.c -+++ contrib/mod_sftp/fxp.c -@@ -6114,7 +6114,7 @@ static int fxp_handle_mkdir(struct fxp_p - (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, - "creating directory '%s' with mode 0%o", path, (unsigned int) dir_mode); - -- res = pr_fsio_mkdir(path, dir_mode); -+ res = pr_fsio_smkdir(fxp->pool, path, dir_mode, (uid_t) -1, (gid_t) -1); - if (res < 0) { - const char *reason; - int xerrno = errno; ---- contrib/mod_sftp/scp.c -+++ contrib/mod_sftp/scp.c -@@ -820,7 +820,7 @@ static int recv_finfo(pool *p, uint32_t - * recursive directory uploads via SCP? - */ - -- if (pr_fsio_mkdir(sp->filename, 0777) < 0) { -+ if (pr_fsio_smkdir(p, sp->filename, 0777, (uid_t) -1, (gid_t) -1) < 0) { - xerrno = errno; - - (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION, ---- include/fsio.h -+++ include/fsio.h -@@ -125,6 +125,7 @@ struct fs_rec { - int (*fchmod)(pr_fh_t *, int, mode_t); - int (*chown)(pr_fs_t *, const char *, uid_t, gid_t); - int (*fchown)(pr_fh_t *, int, uid_t, gid_t); -+ int (*lchown)(pr_fs_t *, const char *, uid_t, gid_t); - int (*access)(pr_fs_t *, const char *, int, uid_t, gid_t, array_header *); - int (*faccess)(pr_fh_t *, int, uid_t, gid_t, array_header *); - int (*utimes)(pr_fs_t *, const char *, struct timeval *); -@@ -243,6 +244,7 @@ int pr_fsio_mkdir(const char *, mode_t); - int pr_fsio_rmdir(const char *); - int pr_fsio_rename(const char *, const char *); - int pr_fsio_rename_canon(const char *, const char *); -+int pr_fsio_smkdir(pool *, const char *, mode_t, uid_t, gid_t); - int pr_fsio_unlink(const char *); - int pr_fsio_unlink_canon(const char *); - pr_fh_t *pr_fsio_open(const char *, int); -@@ -264,6 +266,7 @@ int pr_fsio_fchmod(pr_fh_t *, mode_t); - int pr_fsio_chmod_canon(const char *, mode_t); - int pr_fsio_chown(const char *, uid_t, gid_t); - int pr_fsio_fchown(pr_fh_t *, uid_t, gid_t); -+int pr_fsio_lchown(const char *, uid_t, gid_t); - int pr_fsio_chown_canon(const char *, uid_t, gid_t); - int pr_fsio_chroot(const char *); - int pr_fsio_access(const char *, int, uid_t, gid_t, array_header *); -@@ -272,6 +275,11 @@ int pr_fsio_utimes(const char *, struct - int pr_fsio_futimes(pr_fh_t *, struct timeval *); - off_t pr_fsio_lseek(pr_fh_t *, off_t, int); - -+/* Set a flag determining whether to use mkdtemp(3) (if available) or not. -+ * Returns the previously-set value. -+ */ -+int pr_fsio_set_use_mkdtemp(int); -+ - /* FS-related functions */ - - char *pr_fsio_getline(char *, int, pr_fh_t *, unsigned int *); ---- modules/mod_core.c -+++ modules/mod_core.c -@@ -4306,7 +4306,7 @@ int core_chgrp(cmd_rec *cmd, char *dir, - } - cmd->argv[0] = cmd_name; - -- return pr_fsio_chown(dir, uid, gid); -+ return pr_fsio_lchown(dir, uid, gid); - } - - int core_chmod(cmd_rec *cmd, char *dir, mode_t mode) { -@@ -4583,7 +4583,6 @@ MODRET core_rmd(cmd_rec *cmd) { - MODRET core_mkd(cmd_rec *cmd) { - int res; - char *dir; -- struct stat st; - - CHECK_CMD_MIN_ARGS(cmd, 2); - -@@ -4638,7 +4637,8 @@ MODRET core_mkd(cmd_rec *cmd) { - return PR_ERROR(cmd); - } - -- if (pr_fsio_mkdir(dir, 0777) < 0) { -+ if (pr_fsio_smkdir(cmd->tmp_pool, dir, 0777, session.fsuid, -+ session.fsgid) < 0) { - int xerrno = errno; - - (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " -@@ -4652,71 +4652,6 @@ MODRET core_mkd(cmd_rec *cmd) { - return PR_ERROR(cmd); - } - -- /* Check to see if we need to change the ownership (user and/or group) of -- * the newly created directory. -- */ -- if (session.fsuid != (uid_t) -1) { -- int err = 0, iserr = 0; -- -- pr_fsio_stat(dir, &st); -- -- PRIVS_ROOT -- if (pr_fsio_chown(dir, session.fsuid, session.fsgid) == -1) { -- iserr++; -- err = errno; -- } -- PRIVS_RELINQUISH -- -- if (iserr) { -- pr_log_pri(PR_LOG_WARNING, "chown() as root failed: %s", strerror(err)); -- -- } else { -- if (session.fsgid != (gid_t) -1) { -- pr_log_debug(DEBUG2, "root chown(%s) to uid %lu, gid %lu successful", -- dir, (unsigned long) session.fsuid, (unsigned long) session.fsgid); -- -- } else { -- pr_log_debug(DEBUG2, "root chown(%s) to uid %lu successful", dir, -- (unsigned long) session.fsuid); -- } -- } -- -- } else if (session.fsgid != (gid_t) -1) { -- register unsigned int i; -- int use_root_privs = TRUE; -- -- pr_fsio_stat(dir, &st); -- -- /* Check if session.fsgid is in session.gids. If not, use root privs. */ -- for (i = 0; i < session.gids->nelts; i++) { -- gid_t *group_ids = session.gids->elts; -- -- if (group_ids[i] == session.fsgid) { -- use_root_privs = FALSE; -- break; -- } -- } -- -- if (use_root_privs) { -- PRIVS_ROOT -- } -- -- res = pr_fsio_chown(dir, (uid_t) -1, session.fsgid); -- -- if (use_root_privs) { -- PRIVS_RELINQUISH -- } -- -- if (res == -1) { -- pr_log_pri(PR_LOG_WARNING, "%schown() failed: %s", -- use_root_privs ? "root " : "", strerror(errno)); -- -- } else { -- pr_log_debug(DEBUG2, "%schown(%s) to gid %lu successful", -- use_root_privs ? "root " : "", dir, (unsigned long) session.fsgid); -- } -- } -- - pr_response_add(R_257, _("\"%s\" - Directory successfully created"), - quote_dir(cmd, dir)); - ---- src/fsio.c -+++ src/fsio.c -@@ -29,6 +29,7 @@ - */ - - #include "conf.h" -+#include "privs.h" - - #ifdef HAVE_SYS_STATVFS_H - # include -@@ -80,6 +81,13 @@ static unsigned char chk_fs_map = FALSE; - static char vwd[PR_TUNABLE_PATH_MAX + 1] = "/"; - static char cwd[PR_TUNABLE_PATH_MAX + 1] = "/"; - -+/* Runtime enabling/disabling of mkdtemp(3) use. */ -+#ifdef HAVE_MKDTEMP -+static int use_mkdtemp = TRUE; -+#else -+static int use_mkdtemp = FALSE; -+#endif /* HAVE_MKDTEMP */ -+ - /* Runtime enabling/disabling of encoding of paths. */ - static int use_encoding = TRUE; - -@@ -175,6 +183,10 @@ static int sys_fchown(pr_fh_t *fh, int f - return fchown(fd, uid, gid); - } - -+static int sys_lchown(pr_fs_t *fs, const char *path, uid_t uid, gid_t gid) { -+ return lchown(path, uid, gid); -+} -+ - /* We provide our own equivalent of access(2) here, rather than using - * access(2) directly, because access(2) uses the real IDs, rather than - * the effective IDs, of the process. -@@ -2498,6 +2510,213 @@ int pr_fsio_mkdir(const char *path, mode - return res; - } - -+int pr_fsio_set_use_mkdtemp(int value) { -+ int prev_value; -+ -+ prev_value = use_mkdtemp; -+ -+#ifdef HAVE_MKDTEMP -+ use_mkdtemp = value; -+#endif /* HAVE_MKDTEMP */ -+ -+ return prev_value; -+} -+ -+/* "safe mkdir" variant of mkdir(2), uses mkdtemp(3), lchown(2), and -+ * rename(2) to create a directory which cannot be hijacked by a symlink -+ * race (hopefully) before the UserOwner/GroupOwner ownership changes are -+ * applied. -+ */ -+int pr_fsio_smkdir(pool *p, const char *path, mode_t mode, uid_t uid, -+ gid_t gid) { -+ int res, use_root_privs = TRUE, xerrno = 0; -+ char *tmpl_path; -+ char *dst_dir, *tmpl; -+ size_t dst_dirlen, tmpl_len; -+ -+ if (path == NULL) { -+ errno = EINVAL; -+ return -1; -+ } -+ -+#ifdef HAVE_MKDTEMP -+ if (use_mkdtemp == TRUE) { -+ char *ptr; -+ struct stat st; -+ -+ ptr = strrchr(path, '/'); -+ if (ptr == NULL) { -+ errno = EINVAL; -+ return -1; -+ } -+ -+ if (ptr != path) { -+ dst_dirlen = (ptr - path); -+ dst_dir = pstrndup(p, path, dst_dirlen); -+ -+ } else { -+ dst_dirlen = 1; -+ dst_dir = "/"; -+ } -+ -+ res = lstat(dst_dir, &st); -+ if (res < 0) { -+ return -1; -+ } -+ -+ if (!S_ISDIR(st.st_mode) && -+ !S_ISLNK(st.st_mode)) { -+ errno = EPERM; -+ return -1; -+ } -+ -+ /* Allocate enough space for the temporary name: the length of the -+ * destination directory, a slash, 9 X's, 3 for the prefix, and 1 for the -+ * trailing NUL. -+ */ -+ tmpl_len = strlen(dst_dir) + 14; -+ tmpl = pcalloc(p, tmpl_len); -+ snprintf(tmpl, tmpl_len-1, "%s/dstXXXXXXXXX", -+ dst_dirlen > 1 ? dst_dir : ""); -+ -+ /* Use mkdtemp(3) to create the temporary directory (in the same destination -+ * directory as the target path). -+ */ -+ tmpl_path = mkdtemp(tmpl); -+ if (tmpl_path == NULL) { -+ return -1; -+ } -+ -+ } else { -+ res = pr_fsio_mkdir(path, mode); -+ if (res < 0) { -+ return -1; -+ } -+ -+ tmpl_path = pstrdup(p, path); -+ } -+#else -+ -+ res = pr_fsio_mkdir(path, mode); -+ if (res < 0) { -+ return -1; -+ } -+ -+ tmpl_path = pstrdup(p, path); -+#endif /* HAVE_MKDTEMP */ -+ -+ if (uid != (uid_t) -1) { -+ PRIVS_ROOT -+ res = pr_fsio_lchown(tmpl_path, uid, gid); -+ xerrno = errno; -+ PRIVS_RELINQUISH -+ -+ if (res < 0) { -+ pr_log_pri(PR_LOG_WARNING, "lchown(%s) as root failed: %s", tmpl_path, -+ strerror(xerrno)); -+ -+ } else { -+ if (gid != (gid_t) -1) { -+ pr_log_debug(DEBUG2, "root lchown(%s) to UID %lu, GID %lu successful", -+ tmpl_path, (unsigned long) uid, (unsigned long) gid); -+ -+ } else { -+ pr_log_debug(DEBUG2, "root lchown(%s) to UID %lu successful", -+ tmpl_path, (unsigned long) uid); -+ } -+ } -+ -+ } else if (gid != (gid_t) -1) { -+ register unsigned int i; -+ -+ /* Check if session.fsgid is in session.gids. If not, use root privs. */ -+ for (i = 0; i < session.gids->nelts; i++) { -+ gid_t *group_ids = session.gids->elts; -+ -+ if (group_ids[i] == gid) { -+ use_root_privs = FALSE; -+ break; -+ } -+ } -+ -+ if (use_root_privs) { -+ PRIVS_ROOT -+ } -+ -+ res = pr_fsio_lchown(tmpl_path, (uid_t) -1, gid); -+ xerrno = errno; -+ -+ if (use_root_privs) { -+ PRIVS_RELINQUISH -+ } -+ -+ if (res < 0) { -+ pr_log_pri(PR_LOG_WARNING, "%slchown(%s) failed: %s", -+ use_root_privs ? "root " : "", tmpl_path, strerror(xerrno)); -+ -+ } else { -+ pr_log_debug(DEBUG2, "%slchown(%s) to GID %lu successful", -+ use_root_privs ? "root " : "", tmpl_path, (unsigned long) gid); -+ } -+ } -+ -+ if (use_mkdtemp == TRUE) { -+ mode_t mask, *dir_umask; -+ -+ /* Use chmod(2) to set the permission that we want. -+ * -+ * mkdtemp(3) creates a directory with 0700 perms; we are given the -+ * target mode (modulo the configured Umask). -+ */ -+ dir_umask = get_param_ptr(CURRENT_CONF, "DirUmask", FALSE); -+ if (dir_umask) { -+ mask = *dir_umask; -+ -+ } else { -+ mask = (mode_t) 0022; -+ } -+ -+ if (use_root_privs) { -+ PRIVS_ROOT -+ } -+ -+ res = chmod(tmpl_path, mode & ~mask); -+ xerrno = errno; -+ -+ if (use_root_privs) { -+ PRIVS_RELINQUISH -+ } -+ -+ if (res < 0) { -+ pr_log_pri(PR_LOG_WARNING, "%schmod(%s) failed: %s", -+ use_root_privs ? "root " : "", tmpl_path, strerror(xerrno)); -+ -+ (void) rmdir(tmpl_path); -+ -+ errno = xerrno; -+ return -1; -+ } -+ -+ /* Use rename(2) to move the temporary directory into place at the -+ * target path. -+ */ -+ res = rename(tmpl_path, path); -+ if (res < 0) { -+ xerrno = errno; -+ -+ pr_log_pri(PR_LOG_WARNING, "renaming '%s' to '%s' failed: %s", tmpl_path, -+ path, strerror(xerrno)); -+ -+ (void) rmdir(tmpl_path); -+ -+ errno = xerrno; -+ return -1; -+ } -+ } -+ -+ return 0; -+} -+ - int pr_fsio_rmdir(const char *path) { - int res; - pr_fs_t *fs; -@@ -3357,6 +3576,33 @@ int pr_fsio_fchown(pr_fh_t *fh, uid_t ui - return res; - } - -+int pr_fsio_lchown(const char *name, uid_t uid, gid_t gid) { -+ int res; -+ pr_fs_t *fs; -+ -+ fs = lookup_file_fs(name, NULL, FSIO_FILE_CHOWN); -+ if (fs == NULL) { -+ return -1; -+ } -+ -+ /* Find the first non-NULL custom lchown handler. If there are none, -+ * use the system chown. -+ */ -+ while (fs && fs->fs_next && !fs->lchown) { -+ fs = fs->fs_next; -+ } -+ -+ pr_trace_msg(trace_channel, 8, "using %s lchown() for path '%s'", -+ fs->fs_name, name); -+ res = (fs->lchown)(fs, name, uid, gid); -+ -+ if (res == 0) { -+ pr_fs_clear_cache(); -+ } -+ -+ return res; -+} -+ - int pr_fsio_access(const char *path, int mode, uid_t uid, gid_t gid, - array_header *suppl_gids) { - pr_fs_t *fs; -@@ -4015,6 +4261,7 @@ int init_fs(void) { - root_fs->fchmod = sys_fchmod; - root_fs->chown = sys_chown; - root_fs->fchown = sys_fchown; -+ root_fs->lchown = sys_lchown; - root_fs->access = sys_access; - root_fs->faccess = sys_faccess; - root_fs->utimes = sys_utimes; -@@ -4096,6 +4343,12 @@ static const char *get_fs_hooks_str(pool - if (fs->chown) - hooks = pstrcat(p, hooks, *hooks ? ", " : "", "chown(2)", NULL); - -+ if (fs->fchown) -+ hooks = pstrcat(p, hooks, *hooks ? ", " : "", "fchown(2)", NULL); -+ -+ if (fs->lchown) -+ hooks = pstrcat(p, hooks, *hooks ? ", " : "", "lchown(2)", NULL); -+ - if (fs->access) - hooks = pstrcat(p, hooks, *hooks ? ", " : "", "access(2)", NULL); - ---- src/Makefile.in -+++ src/Makefile.in -@@ -332,7 +332,7 @@ fsio.o: ../include/session.h ../include/ - fsio.o: ../include/throttle.h ../include/trace.h ../include/encode.h - fsio.o: ../include/compat.h ../include/proctitle.h ../include/pidfile.h - fsio.o: ../include/env.h ../include/pr-syslog.h ../include/memcache.h --fsio.o: ../include/tpl.h -+fsio.o: ../include/tpl.h ../include/privs.h - ftpdctl.o: ../include/conf.h ../include/version.h ../config.h - ftpdctl.o: ../include/default_paths.h ../include/options.h ../include/pool.h - ftpdctl.o: ../include/str.h ../include/table.h ../include/proftpd.h diff --git a/proftpd-1.3.4c-bug3744.patch b/proftpd-1.3.4c-bug3744.patch new file mode 100644 index 0000000..c9079e1 --- /dev/null +++ b/proftpd-1.3.4c-bug3744.patch @@ -0,0 +1,327 @@ +--- modules/mod_ls.c ++++ modules/mod_ls.c +@@ -81,6 +81,7 @@ static struct list_limit_rec list_nfiles + + /* ls options */ + static int ++ opt_1 = 0, + opt_a = 0, + opt_A = 0, + opt_B = 0, +@@ -419,7 +420,6 @@ static int listfile(cmd_rec *cmd, pool * + p = cmd->tmp_pool; + + if (pr_fsio_lstat(name, &st) == 0) { +- + char *display_name = NULL; + + suffix[0] = suffix[1] = '\0'; +@@ -531,21 +531,24 @@ static int listfile(cmd_rec *cmd, pool * + break; + } + +- if (list_times_gmt) ++ if (list_times_gmt) { + t = pr_gmtime(p, (time_t *) &sort_time); +- else ++ ++ } else { + t = pr_localtime(p, (time_t *) &sort_time); ++ } + + if (opt_F) { +- if (S_ISLNK(st.st_mode)) ++ if (S_ISLNK(st.st_mode)) { + suffix[0] = '@'; + +- else if (S_ISDIR(st.st_mode)) { ++ } else if (S_ISDIR(st.st_mode)) { + suffix[0] = '/'; + rval = 1; + +- } else if (st.st_mode & 0111) ++ } else if (st.st_mode & 0111) { + suffix[0] = '*'; ++ } + } + + if (opt_l) { +@@ -614,32 +617,38 @@ static int listfile(cmd_rec *cmd, pool * + m[2] = (mode & S_IWUSR) ? 'w' : '-'; + m[1] = (mode & S_IRUSR) ? 'r' : '-'; + +- if (ls_curtime - sort_time > 180 * 24 * 60 * 60) ++ if (ls_curtime - sort_time > 180 * 24 * 60 * 60) { + snprintf(timeline, sizeof(timeline), "%5d", t->tm_year+1900); + +- else ++ } else { + snprintf(timeline, sizeof(timeline), "%02d:%02d", t->tm_hour, + t->tm_min); ++ } + + ls_fmt_filesize(s, sizeof(s), st.st_size); + +- if (!opt_n) { +- +- /* Format nameline using user/group names. */ +- snprintf(nameline, sizeof(nameline)-1, +- "%s %3d %-8s %-8s %s %s %2d %s %s", m, (int) st.st_nlink, +- MAP_UID(st.st_uid), MAP_GID(st.st_gid), s, +- months[t->tm_mon], t->tm_mday, timeline, ++ if (opt_1) { ++ /* One file per line, with no info other than the file name. Easy. */ ++ snprintf(nameline, sizeof(nameline)-1, "%s", + pr_fs_encode_path(cmd->tmp_pool, display_name)); + + } else { +- +- /* Format nameline using user/group IDs. */ +- snprintf(nameline, sizeof(nameline)-1, +- "%s %3d %-8u %-8u %s %s %2d %s %s", m, (int) st.st_nlink, +- (unsigned) st.st_uid, (unsigned) st.st_gid, s, +- months[t->tm_mon], t->tm_mday, timeline, +- pr_fs_encode_path(cmd->tmp_pool, name)); ++ if (!opt_n) { ++ /* Format nameline using user/group names. */ ++ snprintf(nameline, sizeof(nameline)-1, ++ "%s %3d %-8s %-8s %s %s %2d %s %s", m, (int) st.st_nlink, ++ MAP_UID(st.st_uid), MAP_GID(st.st_gid), s, ++ months[t->tm_mon], t->tm_mday, timeline, ++ pr_fs_encode_path(cmd->tmp_pool, display_name)); ++ ++ } else { ++ /* Format nameline using user/group IDs. */ ++ snprintf(nameline, sizeof(nameline)-1, ++ "%s %3d %-8u %-8u %s %s %2d %s %s", m, (int) st.st_nlink, ++ (unsigned) st.st_uid, (unsigned) st.st_gid, s, ++ months[t->tm_mon], t->tm_mday, timeline, ++ pr_fs_encode_path(cmd->tmp_pool, name)); ++ } + } + + nameline[sizeof(nameline)-1] = '\0'; +@@ -649,40 +658,45 @@ static int listfile(cmd_rec *cmd, pool * + + suffix[0] = '\0'; + if (opt_F && pr_fsio_stat(name, &st) == 0) { +- if (S_ISLNK(st.st_mode)) ++ if (S_ISLNK(st.st_mode)) { + suffix[0] = '@'; + +- else if (S_ISDIR(st.st_mode)) ++ } else if (S_ISDIR(st.st_mode)) { + suffix[0] = '/'; + +- else if (st.st_mode & 0111) ++ } else if (st.st_mode & 0111) { + suffix[0] = '*'; ++ } + } + + if (!opt_L && list_show_symlinks) { +- if (sizeof(nameline) - strlen(nameline) > 4) ++ if (sizeof(nameline) - strlen(nameline) > 4) { + snprintf(buf, sizeof(nameline) - strlen(nameline) - 4, + " -> %s", l); +- else ++ } else { + pr_log_pri(PR_LOG_NOTICE, "notice: symlink '%s' yields an " + "excessive string, ignoring", name); ++ } + } + + nameline[sizeof(nameline)-1] = '\0'; + } + +- if (opt_STAT) ++ if (opt_STAT) { + pr_response_add(R_211, "%s%s", nameline, suffix); +- else ++ ++ } else { + addfile(cmd, nameline, suffix, sort_time, st.st_size); ++ } + } + + } else { + if (S_ISREG(st.st_mode) || + S_ISDIR(st.st_mode) || +- S_ISLNK(st.st_mode)) ++ S_ISLNK(st.st_mode)) { + addfile(cmd, pr_fs_encode_path(cmd->tmp_pool, name), suffix, + sort_time, st.st_size); ++ } + } + } + +@@ -1340,6 +1354,7 @@ static void parse_list_opts(char **opt, + switch (**opt) { + case '1': + if (strcmp(session.curr_cmd, C_STAT) != 0) { ++ opt_1 = 1; + opt_l = opt_C = 0; + } + break; +@@ -1392,6 +1407,7 @@ static void parse_list_opts(char **opt, + if (strcmp(session.curr_cmd, C_NLST) != 0) { + opt_l = 1; + opt_C = 0; ++ opt_1 = 0; + } + break; + +@@ -1460,7 +1476,7 @@ static void parse_list_opts(char **opt, + while ((*opt)++ && isalnum((int) **opt)) { + switch (**opt) { + case '1': +- opt_l = opt_C = 0; ++ opt_1 = opt_l = opt_C = 0; + break; + + case 'A': +@@ -1609,8 +1625,8 @@ static int dolist(cmd_rec *cmd, const ch + ls_curtime = time(NULL); + + if (clearflags) { +- opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_h = opt_n = opt_r = +- opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; ++ opt_1 = opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_h = opt_n = ++ opt_r = opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; + } + + if (have_options(cmd, arg)) { +@@ -1745,7 +1761,6 @@ static int dolist(cmd_rec *cmd, const ch + skiparg = TRUE; + + } else { +- + skiparg = FALSE; + + if (use_globbing && +@@ -1987,6 +2002,10 @@ static int nlstfile(cmd_rec *cmd, const + return -1; + } + ++ /* XXX Note that "NLST " was sent, we might be receiving paths ++ * here, not just file names. And that is not what dir_hide_file() is ++ * expecting. ++ */ + if (dir_hide_file(file)) + return 1; + +@@ -2012,6 +2031,25 @@ static int nlstfile(cmd_rec *cmd, const + } + #endif /* PR_USE_NLS */ + ++ if (opt_1) { ++ char *ptr; ++ ++ /* If the -1 option is configured, we want to make sure that we only ++ * display a file, not a path. And it's possible that we given a path ++ * here. ++ */ ++ ptr = strrchr(display_name, '/'); ++ if (ptr != NULL) { ++ size_t display_namelen; ++ ++ display_namelen = strlen(display_name); ++ if (display_namelen > 1) { ++ /* Make sure that we handle a possible display_name of '/' properly. */ ++ display_name = ptr + 1; ++ } ++ } ++ } ++ + /* Be sure to flush the output */ + res = sendline(0, "%s\r\n", pr_fs_encode_path(cmd->tmp_pool, display_name)); + if (res < 0) +@@ -2140,8 +2178,16 @@ static int nlstdir(cmd_rec *cmd, const c + continue; + + if (!curdir) { +- char *str = pr_fs_encode_path(cmd->tmp_pool, +- pdircat(cmd->tmp_pool, dir, p, NULL)); ++ char *str = NULL; ++ ++ if (opt_1) { ++ /* Send just the file name, not the path. */ ++ str = pr_fs_encode_path(cmd->tmp_pool, p); ++ ++ } else { ++ str = pr_fs_encode_path(cmd->tmp_pool, ++ pdircat(cmd->tmp_pool, dir, p, NULL)); ++ } + + if (sendline(0, "%s\r\n", str) < 0) { + count = -1; +@@ -2246,26 +2292,32 @@ MODRET genericlist(cmd_rec *cmd) { + fakeuser = get_param_ptr(CURRENT_CONF, "DirFakeUser", FALSE); + + /* Check for a configured "logged in user" DirFakeUser. */ +- if (fakeuser && strcmp(fakeuser, "~") == 0) ++ if (fakeuser != NULL && ++ strcmp(fakeuser, "~") == 0) { + fakeuser = session.user; ++ } + + fakegroup = get_param_ptr(CURRENT_CONF, "DirFakeGroup", FALSE); + + /* Check for a configured "logged in user" DirFakeGroup. */ +- if (fakegroup && strcmp(fakegroup, "~") == 0) ++ if (fakegroup != NULL && ++ strcmp(fakegroup, "~") == 0) { + fakegroup = session.group; ++ } + + fake_mode = get_param_ptr(CURRENT_CONF, "DirFakeMode", FALSE); + if (fake_mode) { + fakemode = *fake_mode; + have_fake_mode = TRUE; + +- } else ++ } else { + have_fake_mode = FALSE; ++ } + + tmp = get_param_ptr(TOPLEVEL_CONF, "TimesGMT", FALSE); +- if (tmp != NULL) ++ if (tmp != NULL) { + list_times_gmt = *tmp; ++ } + + res = dolist(cmd, pr_fs_decode_path(cmd->tmp_pool, cmd->arg), TRUE); + +@@ -2273,8 +2325,9 @@ MODRET genericlist(cmd_rec *cmd) { + pr_data_abort(0, 0); + res = -1; + +- } else if (session.sf_flags & SF_XFER) ++ } else if (session.sf_flags & SF_XFER) { + ls_done(cmd); ++ } + + opt_l = 0; + +@@ -2457,8 +2510,9 @@ MODRET ls_nlst(cmd_rec *cmd) { + list_nfiles.logged = list_ndirs.logged = list_ndepth.logged = FALSE; + + tmp = get_param_ptr(TOPLEVEL_CONF, "ShowSymlinks", FALSE); +- if (tmp != NULL) ++ if (tmp != NULL) { + list_show_symlinks = *tmp; ++ } + + target = cmd->argc == 1 ? "." : + pr_fs_decode_path(cmd->tmp_pool, cmd->arg); +@@ -2486,8 +2540,8 @@ MODRET ls_nlst(cmd_rec *cmd) { + } + + /* Clear the listing option flags. */ +- opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_n = opt_r = opt_R = +- opt_S = opt_t = opt_STAT = opt_L = 0; ++ opt_1 = opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_n = opt_r = ++ opt_R = opt_S = opt_t = opt_STAT = opt_L = 0; + + if (have_options(cmd, target)) { + if (!list_strict_opts) { diff --git a/proftpd-1.3.4rc3-mysql-password.patch b/proftpd-1.3.4rc3-mysql-password.patch deleted file mode 100644 index 08156e0..0000000 --- a/proftpd-1.3.4rc3-mysql-password.patch +++ /dev/null @@ -1,25 +0,0 @@ -It appears that make_scrambled_password has been deprecated for some time and -has gone away in MySQL 5.5 on Fedora, though not upstream, in favour of -my_make_scrambled_password. - -http://bugs.proftpd.org/3669 -http://bugzilla.redhat.com/718327 - ---- proftpd-1.3.4rc3/contrib/mod_sql_mysql.c -+++ proftpd-1.3.4rc3/contrib/mod_sql_mysql.c -@@ -1477,8 +1477,14 @@ - - #if MYSQL_VERSION_ID >= 40100 && MYSQL_VERSION_ID < 40101 - make_scrambled_password(scrambled, c_clear, 1, NULL); --#else -+#elif MYSQL_VERSION_ID >= 40101 && MYSQL_VERSION_ID < 50501 - make_scrambled_password(scrambled, c_clear); -+#else -+ /* Fedora 15 has removed the long-deprecated make_scrambled_password -+ * symbol, so use the preferred my_make_scrambled_password routine -+ * instead. -+ */ -+ my_make_scrambled_password(scrambled, c_clear, strlen(c_clear)); - #endif - - success = !strcmp(scrambled, c_hash); diff --git a/proftpd.spec b/proftpd.spec index 1962100..f8697f1 100644 --- a/proftpd.spec +++ b/proftpd.spec @@ -41,11 +41,11 @@ %define _hardened_build 1 #global prever rc3 -%global rpmrel 6 +%global rpmrel 1 Summary: Flexible, stable and highly-configurable FTP server Name: proftpd -Version: 1.3.4b +Version: 1.3.4c Release: %{?prever:0.}%{rpmrel}%{?prever:.%{prever}}%{?dist} License: GPLv2+ Group: System Environment/Daemons @@ -62,15 +62,13 @@ Source11: http://www.castaglia.org/proftpd/modules/proftpd-mod-geoip-0.3.tar.gz # (they are disabled by default); it is not included as part of the built package and should therefore # not fall foul of the rules against library bundling Source13: http://search.cpan.org/CPAN/authors/id/C/CL/CLEMBURG/Test-Unit-0.14.tar.gz -Patch1: proftpd-1.3.4rc3-mysql-password.patch Patch2: proftpd.conf-no-memcached.patch Patch4: proftpd-1.3.4rc1-mod_vroot-test.patch Patch5: proftpd-1.3.4-utf8.patch Patch14: proftpd-1.3.4a-bug3720.patch -Patch23: proftpd-1.3.4a-bug3744.patch +Patch23: proftpd-1.3.4c-bug3744.patch Patch24: proftpd-1.3.4a-bug3745.patch Patch25: proftpd-1.3.4a-bug3746.patch -Patch26: proftpd-1.3.4b-bug3841.patch Patch27: proftpd-mod-vroot-0.9.2-bug3841.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root Requires(preun): coreutils, findutils @@ -207,11 +205,6 @@ cp -p mod_geoip/mod_geoip.html doc/contrib/ # Copy default config file into place cp -p %{SOURCE1} proftpd.conf -# Use my_make_scrambled_password rather than the deprecated -# make_scrambled_password, which isn't exported from Fedora's MySQL -# in F-15 onwards (#718327, upstream bug 3669) -%patch1 -p1 -b .mypasswd - # If we're running the full test suite, include the mod_vroot test %patch4 -p1 -b .test_vroot @@ -236,7 +229,6 @@ cp -p %{SOURCE1} proftpd.conf # Fix possible symlink race when applying UserOwner to newly created directory # http://bugs.proftpd.org/show_bug.cgi?id=3841 -%patch26 %patch27 # Avoid documentation name conflicts @@ -535,7 +527,18 @@ fi %{_mandir}/man1/ftpwho.1* %changelog -* Thu Feb 14 2013 Fedora Release Engineering - 1.3.4b-6 +* Thu Mar 7 2013 Paul Howarth 1.3.4c-1 +- Update to 1.3.4c + - Added Spanish translation + - Fixed several mod_sftp issues, including SFTPPassPhraseProvider, + handling of symlinks for REALPATH requests, and response code logging + - Fixed symlink race for creating directories when UserOwner is in effect + - Increased performance of FTP directory listings +- Drop MySQL password patch, no longer needed +- Drop upstreamed proftpd patch for CVE-2012-6095 +- Update patch for bug 3744 to apply against updated proftpd code + +* Thu Feb 14 2013 Fedora Release Engineering 1.3.4b-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild * Wed Jan 16 2013 Paul Howarth 1.3.4b-5 diff --git a/sources b/sources index a419287..c65bd46 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -0871e0b93c9c3c88ca950b6d9a04aed2 proftpd-1.3.4b.tar.gz +65f61e953bea249f8377e681594143a5 proftpd-1.3.4c.tar.gz cc0e479406436e474ca7d59994fa73bb proftpd-mod-geoip-0.3.tar.gz 6db495b25e9da2ba0c901e7c44e119bc proftpd-mod-vroot-0.9.2.tar.gz ad574713bcd00f62883ff2f9a84eec1f Test-Unit-0.14.tar.gz