From 955b1083071beca66039d134034416f32073b466 Mon Sep 17 00:00:00 2001 From: Paul Howarth Date: Jan 18 2013 15:24:22 +0000 Subject: Fix possible symlink race (CVE-2012-6095) - Fix possible symlink race when applying UserOwner to newly created directory (CVE-2012-6095, #892715, http://bugs.proftpd.org/show_bug.cgi?id=3841) - Add -fno-strict-aliasing, needed for mod_radius - Drop %defattr, redundant since rpm 4.4 --- diff --git a/.gitignore b/.gitignore index 85be963..25551de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,13 @@ +# master/f18/f17/f16 +/proftpd-1.3.4b.tar.gz +/proftpd-mod-geoip-0.3.tar.gz +/proftpd-mod-vroot-0.9.2.tar.gz +/Test-Unit-0.14.tar.gz +# el6 /proftpd-1.3.3g.tar.bz2 /proftpd-mod-geoip-0.2.tar.gz /proftpd-mod-vroot-0.9.2.tar.gz +# el5 +/proftpd-1.3.3g.tar.bz2 +/proftpd-mod-geoip-0.2.tar.gz +/proftpd-mod-vroot-0.8.5.tar.gz diff --git a/proftpd-1.3.3g-bug3841.patch b/proftpd-1.3.3g-bug3841.patch new file mode 100644 index 0000000..fa95e25 --- /dev/null +++ b/proftpd-1.3.3g-bug3841.patch @@ -0,0 +1,511 @@ +--- configure.in ++++ configure.in +@@ -1399,7 +1399,7 @@ AC_PROG_GCC_TRADITIONAL + AC_FUNC_SETPGRP + 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 +@@ -26526,7 +26526,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 +@@ -357,6 +357,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 +@@ -5498,7 +5498,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 +@@ -711,7 +711,7 @@ static int recv_finfo(pool *p, uint32_t + if (xerrno == ENOENT) { + pr_trace_msg(trace_channel, 5, "creating directory '%s'", sp->filename); + +- 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 +@@ -129,6 +129,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 *); +@@ -249,6 +250,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); +@@ -270,6 +272,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 *); +@@ -278,6 +281,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 +@@ -3744,7 +3744,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) { +@@ -4002,7 +4002,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); + +@@ -4043,7 +4042,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): " +@@ -4055,71 +4055,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_REGEX_H + # include +@@ -84,6 +85,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; + +@@ -179,6 +187,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. +@@ -2477,6 +2489,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; +@@ -3336,6 +3555,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; +@@ -3955,6 +4201,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; +@@ -4036,6 +4283,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 +@@ -294,7 +294,7 @@ filter.o: ../include/event.h ../include/ + filter.o: ../include/trace.h ../include/encode.h ../include/compat.h + filter.o: ../include/proctitle.h ../include/pidfile.h ../include/env.h + filter.o: ../include/pr-syslog.h +-fsio.o: ../include/conf.h ../include/version.h ../config.h ++fsio.o: ../include/conf.h ../include/privs.h ../include/version.h ../config.h + fsio.o: ../include/default_paths.h ../include/options.h ../include/pool.h + fsio.o: ../include/str.h ../include/regexp.h ../include/table.h + fsio.o: ../include/proftpd.h ../include/class.h ../include/netacl.h diff --git a/proftpd-mod-vroot-0.9.2-bug3841.patch b/proftpd-mod-vroot-0.9.2-bug3841.patch new file mode 100644 index 0000000..0746371 --- /dev/null +++ b/proftpd-mod-vroot-0.9.2-bug3841.patch @@ -0,0 +1,101 @@ +From f2b7c3c6bc47ba547863a66d558dae7b9ed0ce63 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Sun, 13 Jan 2013 16:43:07 -0800 +Subject: [PATCH] Add use of the new pr_fsio_set_use_mkdtemp() API, to work + around issues seen with mod_vroot due to the fix for + Bug#3841. + +--- + mod_vroot.c | 35 ++++++++++++++++++++++++++++++++--- + 1 file changed, 32 insertions(+), 3 deletions(-) + +diff --git mod_vroot/mod_vroot.c mod_vroot/mod_vroot.c +index e31f11d..2fba410 100644 +--- contrib/mod_vroot.c ++++ contrib/mod_vroot.c +@@ -53,6 +53,8 @@ + static pool *vroot_dir_pool = NULL; + static pr_table_t *vroot_dirtab = NULL; + ++static int vroot_use_mkdtemp = FALSE; ++ + static unsigned int vroot_opts = 0; + #define VROOT_OPT_ALLOW_SYMLINKS 0x0001 + +@@ -777,6 +779,28 @@ + return res; + } + ++static int vroot_lchown(pr_fs_t *fs, const char *path, uid_t uid, gid_t gid) { ++ int res; ++ char vpath[PR_TUNABLE_PATH_MAX + 1]; ++ ++ if (session.curr_phase == LOG_CMD || ++ session.curr_phase == LOG_CMD_ERR || ++ (session.sf_flags & SF_ABORT) || ++ *vroot_base == '\0') { ++ /* NOTE: once stackable FS modules are supported, have this fall through ++ * to the next module in the stack. ++ */ ++ res = lchown(path, uid, gid); ++ return res; ++ } ++ ++ if (vroot_lookup_path(NULL, vpath, sizeof(vpath)-1, path, 0, NULL) < 0) ++ return -1; ++ ++ res = lchown(vpath, uid, gid); ++ return res; ++} ++ + static int vroot_chroot(pr_fs_t *fs, const char *path) { + char *chroot_path = "/", *tmp = NULL; + config_rec *c; +@@ -1390,6 +1414,26 @@ + /* Command handlers + */ + ++MODRET vroot_pre_mkd(cmd_rec *cmd) { ++ if (vroot_engine == FALSE || ++ session.chroot_path == NULL) { ++ return PR_DECLINED(cmd); ++ } ++ ++ vroot_use_mkdtemp = pr_fsio_set_use_mkdtemp(FALSE); ++ return PR_DECLINED(cmd); ++} ++ ++MODRET vroot_post_mkd(cmd_rec *cmd) { ++ if (vroot_engine == FALSE || ++ session.chroot_path == NULL) { ++ return PR_DECLINED(cmd); ++ } ++ ++ pr_fsio_set_use_mkdtemp(vroot_use_mkdtemp); ++ return PR_DECLINED(cmd); ++} ++ + MODRET vroot_pre_pass(cmd_rec *cmd) { + pr_fs_t *fs = NULL; + unsigned char *use_vroot = NULL; +@@ -1433,6 +1477,7 @@ + fs->truncate = vroot_truncate; + fs->chmod = vroot_chmod; + fs->chown = vroot_chown; ++ fs->lchown = vroot_lchown; + fs->chdir = vroot_chdir; + fs->chroot = vroot_chroot; + fs->opendir = vroot_opendir; +@@ -1564,6 +1609,12 @@ + { PRE_CMD, C_PASS, G_NONE, vroot_pre_pass, FALSE, FALSE }, + { POST_CMD, C_PASS, G_NONE, vroot_post_pass, FALSE, FALSE }, + { POST_CMD_ERR, C_PASS, G_NONE, vroot_post_pass_err, FALSE, FALSE }, ++ { PRE_CMD, C_MKD, G_NONE, vroot_pre_mkd, FALSE, FALSE }, ++ { POST_CMD, C_MKD, G_NONE, vroot_post_mkd, FALSE, FALSE }, ++ { POST_CMD_ERR, C_MKD, G_NONE, vroot_post_mkd, FALSE, FALSE }, ++ { PRE_CMD, C_XMKD, G_NONE, vroot_pre_mkd, FALSE, FALSE }, ++ { POST_CMD, C_XMKD, G_NONE, vroot_post_mkd, FALSE, FALSE }, ++ { POST_CMD_ERR, C_XMKD, G_NONE, vroot_post_mkd, FALSE, FALSE }, + { 0, NULL } + }; + diff --git a/proftpd.spec b/proftpd.spec index bf0df01..e3bd735 100644 --- a/proftpd.spec +++ b/proftpd.spec @@ -7,7 +7,7 @@ %endif #global prever rc4 -%global rpmrel 1 +%global rpmrel 2 Summary: Flexible, stable and highly-configurable FTP server Name: proftpd @@ -27,6 +27,8 @@ Source9: proftpd.sysconfig Source10: http://www.castaglia.org/proftpd/modules/proftpd-mod-vroot-0.9.2.tar.gz Source11: http://www.castaglia.org/proftpd/modules/proftpd-mod-geoip-0.2.tar.gz Source12: proftpd-tmpfs.conf +Patch0: proftpd-1.3.3g-bug3841.patch +Patch1: proftpd-mod-vroot-0.9.2-bug3841.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root Requires(post): /sbin/chkconfig Requires(preun): /sbin/service, /sbin/chkconfig, coreutils, findutils @@ -88,6 +90,11 @@ cp -p mod_geoip/mod_geoip.html doc/contrib/ # Avoid documentation name conflicts mv contrib/README contrib/README.contrib +# Fix possible symlink race when applying UserOwner to newly created directory +# (CVE-2012-6095, #892715, http://bugs.proftpd.org/show_bug.cgi?id=3841) +%patch0 +%patch1 + # Set up directory names in config file sed -e 's#@PKIDIR@#%{pkidir}#g' \ %{SOURCE1} > proftpd.conf @@ -146,7 +153,7 @@ SMOD6=mod_sftp:mod_sftp_pam:mod_sftp_sql:mod_tls_shmcache --with-modules=mod_readme:mod_auth_pam:mod_tls:mod_vroot \ --with-shared=${SMOD1}:${SMOD2}:${SMOD3}:${SMOD4}:${SMOD5}:${SMOD6}:mod_ifsession -make %{?_smp_mflags} +make %{?_smp_mflags} CFLAGS="%{optflags} -fno-strict-aliasing" %install rm -rf %{buildroot} @@ -203,7 +210,6 @@ if [ $1 -ge 1 ]; then fi %files -f proftpd.lang -%defattr(-,root,root,-) %doc COPYING CREDITS ChangeLog NEWS README %doc README.DSO README.modules README.IPv6 README.PAM %doc README.capabilities README.classes README.controls README.facl @@ -277,20 +283,23 @@ fi %attr(750, root, root) %dir %{_localstatedir}/log/proftpd/ %files ldap -%defattr(-,root,root,-) %doc README.LDAP contrib/mod_quotatab_ldap.ldif contrib/mod_quotatab_ldap.schema %{_libexecdir}/proftpd/mod_ldap.so %{_libexecdir}/proftpd/mod_quotatab_ldap.so %files mysql -%defattr(-,root,root,-) %{_libexecdir}/proftpd/mod_sql_mysql.so %files postgresql -%defattr(-,root,root,-) %{_libexecdir}/proftpd/mod_sql_postgres.so %changelog +* Fri Jan 18 2013 Paul Howarth 1.3.3g-2 +- Fix possible symlink race when applying UserOwner to newly created directory + (CVE-2012-6095, #892715, http://bugs.proftpd.org/show_bug.cgi?id=3841) +- Add -fno-strict-aliasing, needed for mod_radius +- Drop %%defattr, redundant since rpm 4.4 + * Thu Nov 10 2011 Paul Howarth 1.3.3g-1 - Update to 1.3.3g, fixing the following bugs: - ProFTPD with mod_sql_mysql dies of "Alarm clock" on FreeBSD (bug 3702)