On 29.05.2017 18:57, Michael Tremer wrote:
Hi,
Hi,
thank you for working on this.
No problem - had fun... ;-)
Yes, Arne submitted a patch that at least fixes the security vulnerability.
However, could you split this patch into two with the two remaining changes so that we can merge those?
Done. I pushed the - hopefully last - remaining patches.
Best, Matthias
Best, -Michael
On Sun, 2017-05-28 at 11:22 +0200, Matthias Fischer wrote:
Based on:
https://anonscm.debian.org/cgit/pkg-samba/samba.git/commit/?h=wheezy&id=... fd8eb45526e44cd0b2ae8a5b1a058ec647
https://www.samba.org/samba/history/security.html
https://www.samba.org/samba/samba/ftp/patches/security/
Fixes current CVE-2017-7494 and some more...
Removed three 'unrecognized' configure-options.
Some 'lfs'-tuning was made, too.
I altered 'PAK_VER' from "64" to "65" - if not necessary, please change back.
Best, Matthias
Signed-off-by: Matthias Fischer matthias.fischer@ipfire.org
lfs/samba | 22 +- .../samba/CVE-2017-2619-race-condition-fix.patch | 1150 ++++++++++++++++++++ .../CVE-2017-2619-regression-bug-12721-fix.patch | 179 +++ src/patches/samba/CVE-2017-2619-tests.patch | 296 +++++ src/patches/samba/samba-3.6.25-CVE-2017-7494.patch | 14 + .../samba/samba-3.6.25-security-2015-12-16.patch | 255 +++++ 6 files changed, 1909 insertions(+), 7 deletions(-) create mode 100644 src/patches/samba/CVE-2017-2619-race-condition-fix.patch create mode 100644 src/patches/samba/CVE-2017-2619-regression-bug-12721- fix.patch create mode 100644 src/patches/samba/CVE-2017-2619-tests.patch create mode 100644 src/patches/samba/samba-3.6.25-CVE-2017-7494.patch create mode 100644 src/patches/samba/samba-3.6.25-security-2015-12-16.patch
diff --git a/lfs/samba b/lfs/samba index 076152f48..445646464 100644 --- a/lfs/samba +++ b/lfs/samba @@ -1,7 +1,7 @@ ############################################################################# ## # # # IPFire.org - A linux based firewall # -# Copyright (C) 2007-2016 IPFire Team info@ipfire.org # +# Copyright (C) 2007-2017 IPFire Team info@ipfire.org # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -32,7 +32,7 @@ DL_FROM = $(URL_IPFIRE) DIR_APP = $(DIR_SRC)/$(THISAPP) TARGET = $(DIR_INFO)/$(THISAPP) PROG = samba -PAK_VER = 64 +PAK_VER = 65
DEPS = "cups krb5"
@@ -54,7 +54,7 @@ download :$(patsubst %,$(DIR_DL)/%,$(objects))
md5 : $(subst %,%_MD5,$(objects))
-dist: +dist: @$(PAK)
############################################################################# ## @@ -88,6 +88,17 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2016- 2118-v3-6.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2015- 5370-v3-6.patch
- # Apply Debian CVE patches
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2017-
2619-race-condition-fix.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2017-
2619-regression-bug-12721-fix.patch
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2017-
2619-tests.patch
- # Fixes CVE-2015-5252 - Samba
- cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/samba-
3.6.25-security-2015-12-16.patch
- # Fixes CVE-2017-7494 - Samba
- cd $(DIR_APP) && patch -Np0 < $(DIR_SRC)/src/patches/samba/samba-
3.6.25-CVE-2017-7494.patch
- cd $(DIR_APP)/source3 && ./autogen.sh cd $(DIR_APP)/source3 && ./configure \ --prefix=/usr \
@@ -102,10 +113,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) --with-libsmbclient \ --with-libsmbsharemodes \ --with-sendfile-support \
--without-smbwrapper \
--with-fhs \--with-mmap \
--with-winbind \ --disable-swat \ --enable-cups \--with-vfs \
@@ -119,8 +127,8 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) #cd $(DIR_APP)/source3 && install -v -m755 nsswitch/libnss_winbind.so /lib #cd $(DIR_APP)/source3 && ln -v -sf libnss_winbind.so /lib/libnss_winbind.so.2 #cd $(DIR_APP)/source3 && ln -v -sf libnss_wins.so /lib/libnss_wins.so.2
- -mkdir -p /var/ipfire/samba cd $(DIR_APP)/source3 && install -v -m644
../examples/smb.conf.default /var/ipfire/samba
- -mkdir -p /var/ipfire/samba cp -vrf $(DIR_SRC)/config/samba/* /var/ipfire/samba/ chown nobody:nobody -R /var/ipfire/samba/ cp -vfp /var/ipfire/samba/default.global /var/ipfire/samba/global
diff --git a/src/patches/samba/CVE-2017-2619-race-condition-fix.patch b/src/patches/samba/CVE-2017-2619-race-condition-fix.patch new file mode 100644 index 000000000..a96d6be3b --- /dev/null +++ b/src/patches/samba/CVE-2017-2619-race-condition-fix.patch @@ -0,0 +1,1150 @@ +Description: This patch is a consolidation of several patches described by the Git commit summaries below +Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2017-261 9 +bug: https://bugzilla.samba.org/show_bug.cgi?id=12496
+From ec1bca1d5315549e945c93cbf5e3abdb695de782 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 20 Mar 2017 11:32:19 -0700 +Subject: [PATCH 01/15] CVE-2017-2619: s3/smbd: re-open directory after
- dptr_CloseDir()
+dptr_CloseDir() will close and invalidate the fsp's file descriptor, we +have to reopen it.
+Bug: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Ralph Bohme slow@samba.org +Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/open.c | 2 +-
- source3/smbd/proto.h | 2 ++
- source3/smbd/smb2_find.c | 17 +++++++++++++++++
- 3 files changed, 20 insertions(+), 1 deletion(-)
+From 2bb9a3d35f6a0cc43a30638594969c4860ffd5a5 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Tue, 28 Feb 2017 09:24:07 -0800 +Subject: [PATCH 02/15] s3: vfs: dirsort doesn't handle opendir of "."
- correctly.
+Needs to store $cwd path for correct sorting.
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12499
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/modules/vfs_dirsort.c | 4 ++++
- 1 file changed, 4 insertions(+)
+From 327d09ba641046f68daa5b2bb98f09530294cb0d Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 13 Mar 2017 13:44:42 -0700 +Subject: [PATCH 03/15] s3: VFS: vfs_streams_xattr.c: Make streams_xattr_open()
- store the same path as streams_xattr_recheck().
+If the open is changing directories, fsp->fsp_name->base_name +will be the full path from the share root, whilst +smb_fname will be relative to the $cwd.
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12546
+Back-ported from a24ba3e4083200ec9885363efc5769f43183fb6b
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/modules/vfs_streams_xattr.c | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
+From 27871d3bfb0857ad3306aabdce6f9b55e32fff3d Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 13 Mar 2017 13:54:04 -0700 +Subject: [PATCH 04/15] vfs_streams_xattr: use fsp, not base_fsp
+The base_fsp's fd is always -1 as it's closed after being openend in +create_file_unixpath().
+Additionally in streams_xattr_open force using of SMB_VFS_FSETXATTR() by +sticking the just created fd into the fsp (and removing it afterwards).
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12591
+Back-ported from 021189e32ba507832b5e821e5cda8a2889225955.
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/modules/vfs_streams_xattr.c | 205 +++++++++++++++++-----------------
--
- 1 file changed, 99 insertions(+), 106 deletions(-)
+From a419b277c5994459c956ebdd324679e728ebae10 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 19 Dec 2016 11:55:56 -0800 +Subject: [PATCH 05/15] s3: smbd: Create wrapper function for OpenDir in
- preparation for making robust.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/dir.c | 15 ++++++++++++++-
- 1 file changed, 14 insertions(+), 1 deletion(-)
+From e47e3c40b5fc8f52fe70c3e1edf5489ac8b4badf Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 19 Dec 2016 16:25:26 -0800 +Subject: [PATCH 06/15] s3: smbd: Opendir_internal() early return if
- SMB_VFS_OPENDIR failed.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/dir.c | 14 +++++++-------
- 1 file changed, 7 insertions(+), 7 deletions(-)
+From 45e41b709b6c2e67acb99f29aa05b61b53091e57 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 19 Dec 2016 16:35:00 -0800 +Subject: [PATCH 07/15] s3: smbd: Create and use open_dir_safely(). Use from
- OpenDir().
+Hardens OpenDir against TOC/TOU races.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/dir.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 59 insertions(+), 7 deletions(-)
+From 720abcec65b04fdac1052a14898180c8cc816464 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 19 Dec 2016 12:13:20 -0800 +Subject: [PATCH 08/15] s3: smbd: OpenDir_fsp() use early returns.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/dir.c | 34 +++++++++++++++++++++-------------
- 1 file changed, 21 insertions(+), 13 deletions(-)
+From 5070f319bbb7dda87766621a83691910414d06a1 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 19 Dec 2016 12:15:59 -0800 +Subject: [PATCH 09/15] s3: smbd: OpenDir_fsp() - Fix memory leak on error.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/dir.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
+From 65d37759f8b4979bc0c0833e0a5eecd277dfa604 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 19 Dec 2016 12:32:07 -0800 +Subject: [PATCH 10/15] s3: smbd: Move the reference counting and destructor
- setup to just before retuning success.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/dir.c | 10 +++++-----
- 1 file changed, 5 insertions(+), 5 deletions(-)
+From 5a821d791aba90643ddf7a3c29dad4f6621ef185 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 19 Dec 2016 12:35:32 -0800 +Subject: [PATCH 11/15] s3: smbd: Correctly fallback to open_dir_safely if
- FDOPENDIR not supported on system.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/dir.c | 15 +++++++--------
- 1 file changed, 7 insertions(+), 8 deletions(-)
+From 597aa3b99a2790133a4839260607b0a8df41c8e3 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Thu, 15 Dec 2016 12:52:13 -0800 +Subject: [PATCH 12/15] s3: smbd: Remove O_NOFOLLOW guards. We insist on
- O_NOFOLLOW existing.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/open.c | 4 +---
- 1 file changed, 1 insertion(+), 3 deletions(-)
+From 563af2ffec05a2c0b54897e2d28ac7e1adb66e0f Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Thu, 15 Dec 2016 12:56:08 -0800 +Subject: [PATCH 13/15] s3: smbd: Move special handling of symlink errno's into
- a utility function.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/open.c | 30 ++++++++++++++++++++++++++++--
- 1 file changed, 28 insertions(+), 2 deletions(-)
+From b34a67cd3a996804ba7bf90e86cf9e22edf60eb3 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Thu, 15 Dec 2016 13:04:46 -0800 +Subject: [PATCH 14/15] s3: smbd: Add the core functions to prevent symlink
- open races.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/open.c | 242
++++++++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 242 insertions(+)
+From 5920309d2f62dd24fc50530c92dd68077f96a6d2 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Thu, 15 Dec 2016 13:06:31 -0800 +Subject: [PATCH 15/15] s3: smbd: Use the new non_widelink_open() function.
+CVE-2017-2619
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12496
+Signed-off-by: Jeremy Allison jra@samba.org +---
- source3/smbd/open.c | 23 ++++++++++++++++++++++-
- 1 file changed, 22 insertions(+), 1 deletion(-)
+--- samba-3.6.6.orig/source3/smbd/open.c ++++ samba-3.6.6/source3/smbd/open.c +@@ -187,10 +187,277 @@
- }
/**************************************************************************** ++ Handle differing symlink errno's ++**************************************************************************** / ++ ++static int link_errno_convert(int err) ++{ ++#if defined(ENOTSUP) && defined(OSF1) ++ /* handle special Tru64 errno */ ++ if (err == ENOTSUP) { ++ err = ELOOP; ++ } ++#endif /* ENOTSUP */ ++#ifdef EFTYPE ++ /* fix broken NetBSD errno */ ++ if (err == EFTYPE) { ++ err = ELOOP; ++ } ++#endif /* EFTYPE */ ++ /* fix broken FreeBSD errno */ ++ if (err == EMLINK) { ++ err = ELOOP; ++ } ++ return err; ++} ++ ++static int non_widelink_open(struct connection_struct *conn, ++ const char *conn_rootdir, ++ files_struct *fsp, ++ struct smb_filename *smb_fname, ++ int flags, ++ mode_t mode, ++ unsigned int link_depth); ++ ++/***************************************************************************
++ Follow a symlink in userspace. ++**************************************************************************** / ++ ++static int process_symlink_open(struct connection_struct *conn, ++ const char *conn_rootdir, ++ files_struct *fsp, ++ struct smb_filename *smb_fname, ++ int flags, ++ mode_t mode, ++ unsigned int link_depth) ++{ ++ int fd = -1; ++ char *link_target = NULL; ++ int link_len = -1; ++ char *oldwd = NULL; ++ size_t rootdir_len = 0; ++ char *resolved_name = NULL; ++ bool matched = false; ++ int saved_errno = 0; ++ ++ /* ++ * Ensure we don't get stuck in a symlink loop. ++ */ ++ link_depth++; ++ if (link_depth >= 20) { ++ errno = ELOOP; ++ goto out; ++ } ++ ++ /* Allocate space for the link target. */ ++ link_target = talloc_array(talloc_tos(), char, PATH_MAX); ++ if (link_target == NULL) { ++ errno = ENOMEM; ++ goto out; ++ } ++ ++ /* Read the link target. */ ++ link_len = SMB_VFS_READLINK(conn, ++ smb_fname->base_name, ++ link_target, ++ PATH_MAX - 1); ++ if (link_len == -1) { ++ goto out; ++ } ++ ++ /* Ensure it's at least null terminated. */ ++ link_target[link_len] = '\0'; ++ ++ /* Convert to an absolute path. */ ++ resolved_name = SMB_VFS_REALPATH(conn, link_target); ++ if (resolved_name == NULL) { ++ goto out; ++ } ++ ++ /* ++ * We know conn_rootdir starts with '/' and ++ * does not end in '/'. FIXME ! Should we ++ * smb_assert this ? ++ */ ++ rootdir_len = strlen(conn_rootdir); ++ ++ matched = (strncmp(conn_rootdir, resolved_name, rootdir_len) == 0); ++ if (!matched) { ++ errno = EACCES; ++ goto out; ++ } ++ ++ /* ++ * Turn into a path relative to the share root. ++ */ ++ if (resolved_name[rootdir_len] == '\0') { ++ /* Link to the root of the share. */ ++ smb_fname->base_name = talloc_strdup(talloc_tos(), "."); ++ if (smb_fname->base_name == NULL) { ++ errno = ENOMEM; ++ goto out; ++ } ++ } else if (resolved_name[rootdir_len] == '/') { ++ smb_fname->base_name = &resolved_name[rootdir_len+1]; ++ } else { ++ errno = EACCES; ++ goto out; ++ } ++ ++ oldwd = vfs_GetWd(talloc_tos(), conn); ++ if (oldwd == NULL) { ++ goto out; ++ } ++ ++ /* Ensure we operate from the root of the share. */ ++ if (vfs_ChDir(conn, conn_rootdir) == -1) { ++ goto out; ++ } ++ ++ /* And do it all again.. */ ++ fd = non_widelink_open(conn, ++ conn_rootdir, ++ fsp, ++ smb_fname, ++ flags, ++ mode, ++ link_depth); ++ if (fd == -1) { ++ saved_errno = errno; ++ } ++ ++ out: ++ ++ SAFE_FREE(resolved_name); ++ TALLOC_FREE(link_target); ++ if (oldwd != NULL) { ++ int ret = vfs_ChDir(conn, oldwd); ++ if (ret == -1) { ++ smb_panic("unable to get back to old directory\n"); ++ } ++ TALLOC_FREE(oldwd); ++ } ++ if (saved_errno != 0) { ++ errno = saved_errno; ++ } ++ return fd; ++} ++ ++/***************************************************************************
++ Non-widelink open. ++**************************************************************************** / ++ ++static int non_widelink_open(struct connection_struct *conn, ++ const char *conn_rootdir, ++ files_struct *fsp, ++ struct smb_filename *smb_fname, ++ int flags, ++ mode_t mode, ++ unsigned int link_depth) ++{ ++ NTSTATUS status; ++ int fd = -1; ++ struct smb_filename *smb_fname_rel = NULL; ++ int saved_errno = 0; ++ char *oldwd = NULL; ++ char *parent_dir = NULL; ++ const char *final_component = NULL; ++ ++ if (!parent_dirname(talloc_tos(), ++ smb_fname->base_name, ++ &parent_dir, ++ &final_component)) { ++ goto out; ++ } ++ ++ oldwd = vfs_GetWd(talloc_tos(), conn); ++ if (oldwd == NULL) { ++ goto out; ++ } ++ ++ /* Pin parent directory in place. */ ++ if (vfs_ChDir(conn, parent_dir) == -1) { ++ goto out; ++ } ++ ++ /* Ensure the relative path is below the share. */ ++ status = check_reduced_name(conn, final_component); ++ if (!NT_STATUS_IS_OK(status)) { ++ saved_errno = map_errno_from_nt_status(status); ++ goto out; ++ } ++ ++ status = create_synthetic_smb_fname(talloc_tos(), ++ final_component, ++ smb_fname->stream_name, ++ &smb_fname->st, ++ &smb_fname_rel); ++ if (!NT_STATUS_IS_OK(status)) { ++ saved_errno = map_errno_from_nt_status(status); ++ goto out; ++ } ++ ++ flags |= O_NOFOLLOW; ++ ++ { ++ struct smb_filename *tmp_name = fsp->fsp_name; ++ fsp->fsp_name = smb_fname_rel; ++ fd = SMB_VFS_OPEN(conn, smb_fname_rel, fsp, flags, mode); ++ fsp->fsp_name = tmp_name; ++ } ++ ++ if (fd == -1) { ++ saved_errno = link_errno_convert(errno); ++ if (saved_errno == ELOOP) { ++ if (fsp->posix_open) { ++ /* Never follow symlinks on posix open. */ ++ goto out; ++ } ++ if (!lp_symlinks(SNUM(conn))) { ++ /* Explicitly no symlinks. */ ++ goto out; ++ } ++ /* ++ * We have a symlink. Follow in userspace ++ * to ensure it's under the share definition. ++ */ ++ fd = process_symlink_open(conn, ++ conn_rootdir, ++ fsp, ++ smb_fname_rel, ++ flags, ++ mode, ++ link_depth); ++ if (fd == -1) { ++ saved_errno = ++ link_errno_convert(errno); ++ } ++ } ++ } ++ ++ out: ++ ++ TALLOC_FREE(parent_dir); ++ TALLOC_FREE(smb_fname_rel); ++ ++ if (oldwd != NULL) { ++ int ret = vfs_ChDir(conn, oldwd); ++ if (ret == -1) { ++ smb_panic("unable to get back to old directory\n"); ++ } ++ TALLOC_FREE(oldwd); ++ } ++ if (saved_errno != 0) { ++ errno = saved_errno; ++ } ++ return fd; ++} ++ ++/***************************************************************************
- fd support routines - attempt to do a dos_open.
****************************************************************************/
+-static NTSTATUS fd_open(struct connection_struct *conn, ++NTSTATUS fd_open(struct connection_struct *conn,
files_struct *fsp,
int flags,
mode_t mode)
+@@ -198,8 +465,7 @@
- struct smb_filename *smb_fname = fsp->fsp_name;
- NTSTATUS status = NT_STATUS_OK;
+-#ifdef O_NOFOLLOW +- /* ++ /*
* Never follow symlinks on a POSIX client. The
* client should be doing this.
*/
+@@ -207,12 +473,33 @@
- if (fsp->posix_open || !lp_symlinks(SNUM(conn))) {
flags |= O_NOFOLLOW;
- }
+-#endif
+- fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode); ++ /* Ensure path is below share definition. */ ++ if (!lp_widelinks(SNUM(conn))) { ++ const char *conn_rootdir = SMB_VFS_CONNECTPATH(conn, ++ smb_fname->base_name); ++ if (conn_rootdir == NULL) { ++ return NT_STATUS_NO_MEMORY; ++ } ++ /* ++ * Only follow symlinks within a share ++ * definition. ++ */ ++ fsp->fh->fd = non_widelink_open(conn, ++ conn_rootdir, ++ fsp, ++ smb_fname, ++ flags, ++ mode, ++ 0); ++ } else { ++ fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode); ++ } ++
- if (fsp->fh->fd == -1) {
+- status = map_nt_error_from_unix(errno); +- if (errno == EMFILE) { ++ int posix_errno = link_errno_convert(errno); ++ status = map_nt_error_from_unix(posix_errno); ++ if (posix_errno == EMFILE) {
static time_t last_warned = 0L;
if (time((time_t *) NULL) > last_warned) {
+--- samba-3.6.6.orig/source3/smbd/proto.h ++++ samba-3.6.6/source3/smbd/proto.h +@@ -592,6 +592,8 @@
const struct security_token *token,
uint32_t access_desired,
uint32_t *access_granted);
++NTSTATUS fd_open(struct connection_struct *conn, files_struct *fsp, ++ int flags, mode_t mode);
- NTSTATUS fd_close(files_struct *fsp);
- void change_file_owner_to_parent(connection_struct *conn,
const char *inherit_from_dir,
+--- samba-3.6.6.orig/source3/smbd/smb2_find.c ++++ samba-3.6.6/source3/smbd/smb2_find.c +@@ -24,6 +24,7 @@
- #include "../libcli/smb/smb_common.h"
- #include "trans2.h"
- #include "../lib/util/tevent_ntstatus.h"
++#include "system/filesys.h"
- static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
+@@ -300,7 +301,23 @@
- }
- if (in_flags & SMB2_CONTINUE_FLAG_REOPEN) {
++ int flags; ++
dptr_CloseDir(fsp);
++ ++ /* ++ * dptr_CloseDir() will close and invalidate the fsp's file ++ * descriptor, we have to reopen it. ++ */ ++ ++ flags = O_RDONLY; ++#ifdef O_DIRECTORY ++ flags |= O_DIRECTORY; ++#endif ++ status = fd_open(conn, fsp, flags, 0); ++ if (tevent_req_nterror(req, status)) { ++ return tevent_req_post(req, ev); ++ }
- }
- if (fsp->dptr == NULL) {
+--- samba-3.6.6.orig/source3/modules/vfs_dirsort.c ++++ samba-3.6.6/source3/modules/vfs_dirsort.c +@@ -141,6 +141,10 @@
return NULL;
- }
++ if (ISDOT(data->smb_fname->base_name)) { ++ data->smb_fname->base_name = vfs_GetWd(data, handle->conn); ++ } ++
- /* Open the underlying directory and count the number of entries */
- data->source_directory = SMB_VFS_NEXT_OPENDIR(handle, fname, mask,
attr);
+--- samba-3.6.6.orig/source3/modules/vfs_streams_xattr.c ++++ samba-3.6.6/source3/modules/vfs_streams_xattr.c +@@ -229,7 +229,7 @@
return -1;
- }
+- sbuf->st_ex_size = get_xattr_size(handle->conn, fsp->base_fsp, ++ sbuf->st_ex_size = get_xattr_size(handle->conn, fsp,
io->base, io->xattr_name);
- if (sbuf->st_ex_size == -1) {
return -1;
+@@ -364,6 +364,7 @@
- char *xattr_name = NULL;
- int baseflags;
- int hostfd = -1;
++ int ret;
- DEBUG(10, ("streams_xattr_open called for %s\n",
smb_fname_str_dbg(smb_fname)));
+@@ -375,133 +376,125 @@
- /* If the default stream is requested, just open the base file. */
- if (is_ntfs_default_stream_smb_fname(smb_fname)) {
char *tmp_stream_name;
+- int ret;
tmp_stream_name = smb_fname->stream_name;
smb_fname->stream_name = NULL;
ret = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags,
mode);
+- smb_fname->stream_name = tmp_stream_name; +- +- return ret; +- } ++ smb_fname->stream_name = tmp_stream_name;
+- status = streams_xattr_get_name(talloc_tos(), smb_fname-
stream_name,
+- &xattr_name); +- if (!NT_STATUS_IS_OK(status)) { +- errno = map_errno_from_nt_status(status); +- goto fail; +- } ++ return ret; ++ }
+- /* Create an smb_filename with stream_name == NULL. */ +- status = create_synthetic_smb_fname(talloc_tos(), +- smb_fname->base_name, +- NULL, NULL, +- &smb_fname_base); +- if (!NT_STATUS_IS_OK(status)) { +- errno = map_errno_from_nt_status(status); +- goto fail; +- } ++ status = streams_xattr_get_name(talloc_tos(), smb_fname-
stream_name,
++ &xattr_name); ++ if (!NT_STATUS_IS_OK(status)) { ++ errno = map_errno_from_nt_status(status); ++ goto fail; ++ }
+- /* +- * We use baseflags to turn off nasty side-effects when opening the +- * underlying file. +- */ +- baseflags = flags; +- baseflags &= ~O_TRUNC; +- baseflags &= ~O_EXCL; +- baseflags &= ~O_CREAT; +- +- hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp, +- baseflags, mode); +- +- TALLOC_FREE(smb_fname_base); +- +- /* It is legit to open a stream on a directory, but the base +- * fd has to be read-only. +- */ +- if ((hostfd == -1) && (errno == EISDIR)) { +- baseflags &= ~O_ACCMODE; +- baseflags |= O_RDONLY; +- hostfd = SMB_VFS_OPEN(handle->conn, smb_fname, fsp, baseflags, +- mode); +- } ++ /* Create an smb_filename with stream_name == NULL. */ ++ status = create_synthetic_smb_fname(talloc_tos(), ++ smb_fname->base_name, ++ NULL, NULL, ++ &smb_fname_base); ++ if (!NT_STATUS_IS_OK(status)) { ++ errno = map_errno_from_nt_status(status); ++ goto fail; ++ }
+- if (hostfd == -1) { +- goto fail; +- } ++ /* ++ * We use baseflags to turn off nasty side-effects when opening the ++ * underlying file. ++ */ ++ baseflags = flags; ++ baseflags &= ~O_TRUNC; ++ baseflags &= ~O_EXCL; ++ baseflags &= ~O_CREAT;
+- status = get_ea_value(talloc_tos(), handle->conn, NULL, +- smb_fname->base_name, xattr_name, &ea); ++ hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp, ++ baseflags, mode);
+- DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status))); ++ TALLOC_FREE(smb_fname_base);
+- if (!NT_STATUS_IS_OK(status) +- && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { +- /* +- * The base file is not there. This is an error even if we got +- * O_CREAT, the higher levels should have created the base +- * file for us. ++ /* It is legit to open a stream on a directory, but the base ++ * fd has to be read-only.
*/
+- DEBUG(10, ("streams_xattr_open: base file %s not around, " +- "returning ENOENT\n", smb_fname->base_name)); +- errno = ENOENT; +- goto fail; +- } ++ if ((hostfd == -1) && (errno == EISDIR)) { ++ baseflags &= ~O_ACCMODE; ++ baseflags |= O_RDONLY; ++ hostfd = SMB_VFS_OPEN(handle->conn, smb_fname, fsp, baseflags, ++ mode); ++ }
+- if (!NT_STATUS_IS_OK(status)) { +- /* +- * The attribute does not exist +- */ ++ if (hostfd == -1) { ++ goto fail; ++ } ++ ++ status = get_ea_value(talloc_tos(), handle->conn, NULL, ++ smb_fname->base_name, xattr_name, &ea);
+- if (flags & O_CREAT) { ++ DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status))); ++ ++ if (!NT_STATUS_IS_OK(status) ++ && !NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
/*
+- * Darn, xattrs need at least 1 byte ++ * The base file is not there. This is an error even if we got ++ * O_CREAT, the higher levels should have created the base ++ * file for us.
*/
+- char null = '\0'; ++ DEBUG(10, ("streams_xattr_open: base file %s not around, " ++ "returning ENOENT\n", smb_fname-
base_name));
++ errno = ENOENT; ++ goto fail; ++ }
+- DEBUG(10, ("creating attribute %s on file %s\n", +- xattr_name, smb_fname->base_name)); ++ if (!NT_STATUS_IS_OK(status)) { ++ /* ++ * The attribute does not exist ++ */
++ if (flags & O_CREAT) { ++ /* ++ * Darn, xattrs need at least 1 byte ++ */ ++ char null = '\0'; ++ ++ DEBUG(10, ("creating attribute %s on file %s\n", ++ xattr_name, smb_fname-
base_name));
++ ++ fsp->fh->fd = hostfd; ++ ret = SMB_VFS_FSETXATTR(fsp, xattr_name, ++ &null, sizeof(null), ++ flags & O_EXCL ? XATTR_CREATE : 0); ++ fsp->fh->fd = -1; ++ if (ret != 0) { ++ goto fail; ++ } ++ } ++ } ++ ++ if (flags & O_TRUNC) { ++ char null = '\0';
if (fsp->base_fsp->fh->fd != -1) {
+- if (SMB_VFS_FSETXATTR( +- fsp->base_fsp, xattr_name, +- &null, sizeof(null), +- flags & O_EXCL ? XATTR_CREATE : 0) == -1) { ++ if (SMB_VFS_FSETXATTR( ++ fsp->base_fsp, xattr_name, ++ &null, sizeof(null), ++ flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
goto fail;
}
} else {
+- if (SMB_VFS_SETXATTR( +- handle->conn, smb_fname->base_name, +- xattr_name, &null, sizeof(null), +- flags & O_EXCL ? XATTR_CREATE : 0) == -1) { ++ if (SMB_VFS_SETXATTR( ++ handle->conn, smb_fname-
base_name,
++ xattr_name, &null, sizeof(null), ++ flags & O_EXCL ? XATTR_CREATE : 0) == -1) {
goto fail;
}
}
}
+- } +- +- if (flags & O_TRUNC) { +- char null = '\0'; +- if (fsp->base_fsp->fh->fd != -1) { +- if (SMB_VFS_FSETXATTR( +- fsp->base_fsp, xattr_name, +- &null, sizeof(null), +- flags & O_EXCL ? XATTR_CREATE : 0) == -1) { +- goto fail; +- } +- } else { +- if (SMB_VFS_SETXATTR( +- handle->conn, smb_fname->base_name, +- xattr_name, &null, sizeof(null), +- flags & O_EXCL ? XATTR_CREATE : 0) == -1) { +- goto fail; +- } +- } +- }
+- sio = (struct stream_io *)VFS_ADD_FSP_EXTENSION(handle, fsp, ++ sio = (struct stream_io *)VFS_ADD_FSP_EXTENSION(handle, fsp,
struct stream_io,
NULL);
if (sio == NULL) {
+@@ -511,8 +504,15 @@
sio->xattr_name = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle,
fsp),
xattr_name);
++ /* ++ * sio->base needs to be a copy of fsp->fsp_name->base_name, ++ * making it identical to streams_xattr_recheck(). If the ++ * open is changing directories, fsp->fsp_name->base_name ++ * will be the full path from the share root, whilst ++ * smb_fname will be relative to the $cwd. ++ */
sio->base = talloc_strdup(VFS_MEMCTX_FSP_EXTENSION(handle, fsp),
+- smb_fname->base_name); ++ fsp->fsp_name->base_name);
- sio->fsp_name_ptr = fsp->fsp_name;
- sio->handle = handle;
- sio->fsp = fsp;
+@@ -861,7 +861,7 @@
return -1;
- }
+- status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp, ++ status = get_ea_value(talloc_tos(), handle->conn, fsp,
sio->base, sio->xattr_name, &ea);
- if (!NT_STATUS_IS_OK(status)) {
return -1;
+@@ -885,13 +885,13 @@
memcpy(ea.value.data + offset, data, n);
+- if (fsp->base_fsp->fh->fd != -1) { +- ret = SMB_VFS_FSETXATTR(fsp->base_fsp, ++ if (fsp->fh->fd != -1) { ++ ret = SMB_VFS_FSETXATTR(fsp,
sio->xattr_name,
ea.value.data, ea.value.length, 0);
- } else {
ret = SMB_VFS_SETXATTR(fsp->conn,
+- fsp->base_fsp->fsp_name->base_name, ++ fsp->fsp_name->base_name,
sio->xattr_name,
ea.value.data, ea.value.length, 0);
- }
+@@ -925,7 +925,7 @@
return -1;
- }
+- status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp, ++ status = get_ea_value(talloc_tos(), handle->conn, fsp,
sio->base, sio->xattr_name, &ea);
- if (!NT_STATUS_IS_OK(status)) {
return -1;
+@@ -970,7 +970,7 @@
return -1;
- }
+- status = get_ea_value(talloc_tos(), handle->conn, fsp->base_fsp, ++ status = get_ea_value(talloc_tos(), handle->conn, fsp,
sio->base, sio->xattr_name, &ea);
- if (!NT_STATUS_IS_OK(status)) {
return -1;
+@@ -995,13 +995,13 @@
- ea.value.length = offset + 1;
- ea.value.data[offset] = 0;
+- if (fsp->base_fsp->fh->fd != -1) { +- ret = SMB_VFS_FSETXATTR(fsp->base_fsp, ++ if (fsp->fh->fd != -1) { ++ ret = SMB_VFS_FSETXATTR(fsp,
sio->xattr_name,
ea.value.data, ea.value.length, 0);
- } else {
ret = SMB_VFS_SETXATTR(fsp->conn,
+- fsp->base_fsp->fsp_name->base_name, ++ fsp->fsp_name->base_name,
sio->xattr_name,
ea.value.data, ea.value.length, 0);
- }
+--- samba-3.6.6.orig/source3/smbd/dir.c ++++ samba-3.6.6/source3/smbd/dir.c +@@ -1358,7 +1358,8 @@
- Open a directory.
- ********************************************************************/
+-struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, ++static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx, ++ connection_struct *conn,
const char *name,
const char *mask,
uint32 attr)
+@@ -1370,27 +1371,21 @@
return NULL;
- }
+- dirp->conn = conn; +- dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn)); +- +- dirp->dir_path = talloc_strdup(dirp, name); +- if (!dirp->dir_path) { +- errno = ENOMEM; ++ dirp->dir = SMB_VFS_OPENDIR(conn, name, mask, attr); ++ if (!dirp->dir) { ++ DEBUG(5,("OpenDir: Can't open %s. %s\n", name, ++ strerror(errno) ));
goto fail;
- }
++ dirp->conn = conn; ++ dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn)); ++
- if (sconn && !sconn->using_smb2) {
sconn->searches.dirhandles_open++;
- }
- talloc_set_destructor(dirp, smb_Dir_destructor);
+- dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); +- if (!dirp->dir) { +- DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, +- strerror(errno) )); +- goto fail; +- } +-
- return dirp;
- fail:
+@@ -1398,6 +1393,76 @@
- return NULL;
- }
++/***************************************************************************
++ Open a directory handle by pathname, ensuring it's under the share path. ++**************************************************************************** / ++ ++static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx, ++ connection_struct *conn, ++ const char *name, ++ const char *wcard, ++ uint32_t attr) ++{ ++ struct smb_Dir *dir_hnd = NULL; ++ char *saved_dir = vfs_GetWd(ctx, conn); ++ NTSTATUS status; ++ ++ if (saved_dir == NULL) { ++ return NULL; ++ } ++ ++ if (vfs_ChDir(conn, name) == -1) { ++ goto out; ++ } ++ ++ /* ++ * Now the directory is pinned, use ++ * REALPATH to ensure we can access it. ++ */ ++ status = check_name(conn, "."); ++ if (!NT_STATUS_IS_OK(status)) { ++ goto out; ++ } ++ ++ dir_hnd = OpenDir_internal(ctx, ++ conn, ++ ".", ++ wcard, ++ attr); ++ ++ if (dir_hnd == NULL) { ++ goto out; ++ } ++ ++ /* ++ * OpenDir_internal only gets "." as the dir name. ++ * Store the real dir name here. ++ */ ++ ++ dir_hnd->dir_path = talloc_strdup(dir_hnd, name); ++ if (!dir_hnd->dir_path) { ++ errno = ENOMEM; ++ } ++ ++ out: ++ ++ vfs_ChDir(conn, saved_dir); ++ TALLOC_FREE(saved_dir); ++ return dir_hnd; ++} ++ ++struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn, ++ const char *name, ++ const char *mask, ++ uint32_t attr) ++{ ++ return open_dir_safely(mem_ctx, ++ conn, ++ name, ++ mask, ++ attr); ++} ++
- /*******************************************************************
- Open a directory from an fsp.
- ********************************************************************/
+@@ -1411,7 +1476,17 @@
- struct smbd_server_connection *sconn = conn->sconn;
- if (!dirp) {
+- return NULL; ++ goto fail; ++ } ++ ++ if (!fsp->is_directory) { ++ errno = EBADF; ++ goto fail; ++ } ++ ++ if (fsp->fh->fd == -1) { ++ errno = EBADF; ++ goto fail;
- }
- dirp->conn = conn;
+@@ -1423,36 +1498,33 @@
goto fail;
- }
+- if (sconn && !sconn->using_smb2) { +- sconn->searches.dirhandles_open++; +- } +- talloc_set_destructor(dirp, smb_Dir_destructor); +- +- if (fsp->is_directory && fsp->fh->fd != -1) { +- dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr); +- if (dirp->dir != NULL) { +- dirp->fsp = fsp; +- } else { +- DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned " +- "NULL (%s)\n", +- dirp->dir_path, +- strerror(errno))); +- if (errno != ENOSYS) { +- return NULL; +- } ++ dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr); ++ if (dirp->dir != NULL) { ++ dirp->fsp = fsp; ++ } else { ++ DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned " ++ "NULL (%s)\n", ++ dirp->dir_path, ++ strerror(errno))); ++ if (errno != ENOSYS) { ++ goto fail;
}
- }
- if (dirp->dir == NULL) {
+- /* FDOPENDIR didn't work. Use OPENDIR instead. */ +- dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr); ++ /* FDOPENDIR is not supported. Use OPENDIR instead. */ ++ TALLOC_FREE(dirp); ++ return open_dir_safely(mem_ctx, ++ conn, ++ fsp->fsp_name->base_name, ++ mask, ++ attr);
- }
+- if (!dirp->dir) { +- DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path, +- strerror(errno) )); +- goto fail; ++ if (sconn && !sconn->using_smb2) { ++ sconn->searches.dirhandles_open++;
- }
++ talloc_set_destructor(dirp, smb_Dir_destructor);
- return dirp;
diff --git a/src/patches/samba/CVE-2017-2619-regression-bug-12721-fix.patch b/src/patches/samba/CVE-2017-2619-regression-bug-12721-fix.patch new file mode 100644 index 000000000..cefdd86ea --- /dev/null +++ b/src/patches/samba/CVE-2017-2619-regression-bug-12721-fix.patch @@ -0,0 +1,179 @@ +bug: https://bugzilla.samba.org/show_bug.cgi?id=12721 +Description: This patch is a consolidation of several patches described by the Git commit summaries below
+From 5d4ef6ff0970c93fed49e51a01e63cb67d49d087 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 27 Mar 2017 10:46:47 -0700 +Subject: [PATCH 1/3] s3: smbd: Fix incorrect logic exposed by fix for the
- security bug 12496 (CVE-2017-2619).
+In a UNIX filesystem, the names "." and ".." by definition can *never* +be symlinks - they are already reserved names.
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+Signed-off-by: Jeremy Allison jra@samba.org +Reviewed-by: Uri Simchoni uri@samba.org +(cherry picked from commit ae17bebd250bdde5614b2ac17e53512f19fe9b68) +---
- source3/smbd/vfs.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
+From 71500662d1098d17657b0148a0aa06cd69482c7d Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 27 Mar 2017 17:04:58 -0700 +Subject: [PATCH 2/3] s3: smbd: Fix "follow symlink = no" regression part 2.
+Add an extra paramter to cwd_name to check_reduced_name().
+If cwd_name == NULL then fname is a client given path relative +to the root path of the share.
+If cwd_name != NULL then fname is a client given path relative +to cwd_name. cwd_name is relative to the root path of the share.
+Not yet used, logic added in the next commit.
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+Signed-off-by: Jeremy Allison jra@samba.org +Reviewed-by: Ralph Boehme slow@samba.org +(cherry picked from commit 83e30cb48859b412b76572b6a3ba84d8fde167af) +---
- source3/smbd/filename.c | 2 +-
- source3/smbd/open.c | 2 +-
- source3/smbd/proto.h | 4 +++-
- source3/smbd/vfs.c | 10 +++++++++-
- 4 files changed, 14 insertions(+), 4 deletions(-)
+From e3fd46264b82ffc22424ee7364b3fd2c0fc14a7e Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 27 Mar 2017 17:09:38 -0700 +Subject: [PATCH 3/3] s3: smbd: Fix "follow symlink = no" regression part 2.
+Use the cwd_name parameter to reconstruct the original +client name for symlink testing.
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+Signed-off-by: Jeremy Allison jra@samba.org +Reviewed-by: Ralph Boehme slow@samba.org +(cherry picked from commit e182a4d39e86c9694e255efdf6ee2ea3ccb9af4a) +---
- source3/smbd/vfs.c | 23 +++++++++++++++++++++++
- 1 file changed, 23 insertions(+)
+--- samba-3.6.6.orig/source3/smbd/vfs.c ++++ samba-3.6.6/source3/smbd/vfs.c +@@ -894,11 +894,20 @@
- /*******************************************************************
- Reduce a file name, removing .. elements and checking that
- it is below dir in the heirachy. This uses realpath.
++ ++ If cwd_name == NULL then fname is a client given path relative ++ to the root path of the share. ++ ++ If cwd_name != NULL then fname is a client given path relative ++ to cwd_name. cwd_name is relative to the root path of the share.
- ********************************************************************/
+-NTSTATUS check_reduced_name(connection_struct *conn, const char *fname) ++NTSTATUS check_reduced_name(connection_struct *conn, ++ const char *cwd_name, ++ const char *fname)
- {
- char *resolved_name = NULL;
++ char *new_fname = NULL;
- bool allow_symlinks = true;
- bool allow_widelinks = false;
+@@ -1026,8 +1035,11 @@
/* fname can't have changed in resolved_path. */
const char *p = &resolved_name[rootdir_len];
+- /* *p can be '\0' if fname was "." */ +- if (*p == '\0' && ISDOT(fname)) { ++ /* ++ * UNIX filesystem semantics, names consisting ++ * only of "." or ".." CANNOT be symlinks. ++ */ ++ if (ISDOT(fname) || ISDOTDOT(fname)) {
goto out;
}
+@@ -1041,11 +1053,32 @@
}
p++;
++ ++ /* ++ * If cwd_name is present and not ".", ++ * then fname is relative to that, not ++ * the root of the share. Make sure the ++ * path we check is the one the client ++ * sent (cwd_name+fname). ++ */ ++ if (cwd_name != NULL && !ISDOT(cwd_name)) { ++ new_fname = talloc_asprintf(talloc_tos(), ++ "%s/%s", ++ cwd_name, ++ fname); ++ if (new_fname == NULL) { ++ SAFE_FREE(resolved_name); ++ return NT_STATUS_NO_MEMORY; ++ } ++ fname = new_fname; ++ } ++
if (strcmp(fname, p)!=0) {
DEBUG(2, ("check_reduced_name: Bad access "
"attempt: %s is a symlink\n",
fname));
SAFE_FREE(resolved_name);
++ TALLOC_FREE(new_fname);
return NT_STATUS_ACCESS_DENIED;
}
}
+@@ -1056,6 +1089,7 @@
- DEBUG(3,("check_reduced_name: %s reduced to %s\n", fname,
resolved_name));
- SAFE_FREE(resolved_name);
++ TALLOC_FREE(new_fname);
- return NT_STATUS_OK;
- }
+--- samba-3.6.6.orig/source3/smbd/filename.c ++++ samba-3.6.6/source3/smbd/filename.c +@@ -1009,7 +1009,7 @@
- }
- if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
+- status = check_reduced_name(conn,name); ++ status = check_reduced_name(conn, NULL, name);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("check_name: name %s failed with
%s\n",name,
nt_errstr(status)));
+--- samba-3.6.6.orig/source3/smbd/open.c ++++ samba-3.6.6/source3/smbd/open.c +@@ -381,7 +381,7 @@
- }
- /* Ensure the relative path is below the share. */
+- status = check_reduced_name(conn, final_component); ++ status = check_reduced_name(conn, parent_dir, final_component);
- if (!NT_STATUS_IS_OK(status)) {
saved_errno = map_errno_from_nt_status(status);
goto out;
+--- samba-3.6.6.orig/source3/smbd/proto.h ++++ samba-3.6.6/source3/smbd/proto.h +@@ -1179,7 +1179,9 @@
SMB_STRUCT_STAT *sbuf, char **talloced);
- int vfs_ChDir(connection_struct *conn, const char *path);
- char *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
+-NTSTATUS check_reduced_name(connection_struct *conn, const char *fname); ++NTSTATUS check_reduced_name(connection_struct *conn, ++ const char *cwd_name, ++ const char *fname);
- int vfs_stat_smb_fname(struct connection_struct *conn, const char *fname,
SMB_STRUCT_STAT *psbuf);
- int vfs_lstat_smb_fname(struct connection_struct *conn, const char *fname,
diff --git a/src/patches/samba/CVE-2017-2619-tests.patch b/src/patches/samba/CVE-2017-2619-tests.patch new file mode 100644 index 000000000..41c84610e --- /dev/null +++ b/src/patches/samba/CVE-2017-2619-tests.patch @@ -0,0 +1,296 @@ +Description: Patches to unit tests associated with CVE-2017-2619 regression +origin: https://attachments.samba.org/attachment.cgi?id=13130
+From 2c6de8584779e413f1e6ff9c933f9281693bfbc0 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 27 Mar 2017 11:48:25 -0700 +Subject: [PATCH 2/6] s3: Test for CVE-2017-2619 regression with "follow
- symlinks = no".
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+Signed-off-by: Jeremy Allison jra@samba.org +Reviewed-by: Uri Simchoni uri@samba.org
+Back-ported from commit 782172a9bef0040981d20e49519b13dd744df6a0 +---
- selftest/target/Samba3.pm | 7 +++
- source3/script/tests/test_smbclient_s3.sh | 73
+++++++++++++++++++++++++++++++
- 2 files changed, 80 insertions(+)
+diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm +index 01a1c470af0..7765b9efbb2 100644 +--- a/selftest/target/Samba3.pm ++++ b/selftest/target/Samba3.pm +@@ -481,6 +481,9 @@ sub provision($$$$$$)
- my $msdfs_deeppath="$msdfs_shrdir/deeppath";
- push(@dirs,$msdfs_deeppath);
++ my $nosymlinks_shrdir="$shrdir/nosymlinks"; ++ push(@dirs,$nosymlinks_shrdir); ++
- # this gets autocreated by winbindd
- my $wbsockdir="$prefix_abs/winbindd";
- my $wbsockprivdir="$lockdir/winbindd_privileged";
+@@ -695,6 +698,10 @@ sub provision($$$$$$)
- copy = print1
- [print$]
- copy = tmp
++[nosymlinks] ++ copy = tmp ++ path = $nosymlinks_shrdir ++ follow symlinks = no
- ";
- close(CONF);
+diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh +index 772802f77b1..57ef87e4949 100755 +--- a/source3/script/tests/test_smbclient_s3.sh ++++ b/source3/script/tests/test_smbclient_s3.sh +@@ -401,6 +401,75 @@ done
- LOGDIR=$(mktemp -d ${PREFIX}/${LOGDIR_PREFIX}_XXXXXX)
++# Test follow symlinks can't access symlinks ++test_nosymlinks() ++{ ++# Setup test dirs. ++ slink_name="$LOCAL_PATH/nosymlinks/source" ++ slink_target="$LOCAL_PATH/nosymlinks/target" ++ mkdir_target="$LOCAL_PATH/nosymlinks/a" ++ ++ rm -f $slink_target ++ rm -f $slink_name ++ rm -rf $mkdir_target ++ ++ touch $slink_target ++ ln -s $slink_target $slink_name ++ ++# Getting a file through a symlink name should fail. ++ tmpfile=$PREFIX/smbclient_interactive_prompt_commands ++ cat > $tmpfile <<EOF ++get source ++quit ++EOF ++ cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' ++ eval echo "$cmd" ++ out=`eval $cmd` ++ ret=$? ++ rm -f $tmpfile ++ ++ if [ $ret != 0 ] ; then ++ echo "$out" ++ echo "failed accessing nosymlinks with error $ret" ++ false ++ return ++ fi ++ ++ echo "$out" | grep 'NT_STATUS_ACCESS_DENIED' ++ ret=$? ++ if [ $ret != 0 ] ; then ++ echo "$out" ++ echo "failed - should get NT_STATUS_ACCESS_DENIED getting \nosymlinks\source" ++ false ++ fi ++ ++# But we should be able to create and delete directories. ++ cat > $tmpfile <<EOF ++mkdir a ++mkdir a\b ++quit ++EOF ++ cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' ++ eval echo "$cmd" ++ out=`eval $cmd` ++ ret=$? ++ rm -f $tmpfile ++ ++ if [ $ret != 0 ] ; then ++ echo "$out" ++ echo "failed accessing nosymlinks with error $ret" ++ false ++ return ++ fi ++ ++ echo "$out" | grep 'NT_STATUS' ++ ret=$? ++ if [ $ret == 0 ] ; then ++ echo "$out" ++ echo "failed - NT_STATUS_XXXX doing mkdir a; mkdir a\b on \nosymlinks" ++ false ++ fi ++}
- testit "smbclient -L $SERVER_IP" $SMBCLIENT -L $SERVER_IP -N -p 139 ||
failed=`expr $failed + 1`
- testit "smbclient -L $SERVER -I $SERVER_IP" $SMBCLIENT -L $SERVER -I
$SERVER_IP -N -p 139 -c quit || failed=`expr $failed + 1` +@@ -445,6 +514,10 @@ testit "ccache access works for smbclient" \
test_ccache_access || \
failed=`expr $failed + 1`
++testit "follow symlinks = no" \ ++ test_nosymlinks || \ ++ failed=`expr $failed + 1` ++
- testit "rm -rf $LOGDIR" \
rm -rf $LOGDIR || \
failed=`expr $failed + 1`
+-- +2.12.0
+From 17865cf188f42850f18f46514643a5b3a43e5707 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 27 Mar 2017 22:07:50 -0700 +Subject: [PATCH 3/6] s3: Fixup test for CVE-2017-2619 regression with "follow
- symlinks = no"
+Use correct bash operators (not string operators). +Add missing "return".
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+Signed-off-by: Jeremy Allison jra@samba.org +Reviewed-by: Ralph Boehme slow@samba.org +(cherry picked from commit 037297a1c50e90a0092e3b94f472623f41ccc015) +---
- source3/script/tests/test_smbclient_s3.sh | 9 +++++----
- 1 file changed, 5 insertions(+), 4 deletions(-)
+diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh +index 57ef87e4949..bd5714fca6e 100755 +--- a/source3/script/tests/test_smbclient_s3.sh ++++ b/source3/script/tests/test_smbclient_s3.sh +@@ -428,7 +428,7 @@ EOF
ret=$?
rm -f $tmpfile
+- if [ $ret != 0 ] ; then ++ if [ $ret -ne 0 ] ; then
echo "$out"
echo "failed accessing nosymlinks with error $ret"
false
+@@ -437,10 +437,11 @@ EOF
echo "$out" | grep 'NT_STATUS_ACCESS_DENIED'
ret=$?
+- if [ $ret != 0 ] ; then ++ if [ $ret -ne 0 ] ; then
echo "$out"
echo "failed - should get NT_STATUS_ACCESS_DENIED getting
\nosymlinks\source"
false
++ return
fi
- # But we should be able to create and delete directories.
+@@ -455,7 +456,7 @@ EOF
ret=$?
rm -f $tmpfile
+- if [ $ret != 0 ] ; then ++ if [ $ret -ne 0 ] ; then
echo "$out"
echo "failed accessing nosymlinks with error $ret"
false
+@@ -464,7 +465,7 @@ EOF
echo "$out" | grep 'NT_STATUS'
ret=$?
+- if [ $ret == 0 ] ; then ++ if [ $ret -eq 0 ] ; then
- echo "$out"
- echo "failed - NT_STATUS_XXXX doing mkdir a; mkdir a\b on
\nosymlinks"
- false
+-- +2.12.0
+From 9b573af39f3d4995464e30771fa06e0709b5e57b Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Mon, 27 Mar 2017 22:10:29 -0700 +Subject: [PATCH 6/6] s3: Test for CVE-2017-2619 regression with "follow
- symlinks = no" - part 2
+MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit
+Add tests for regular access.
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12721
+Signed-off-by: Jeremy Allison jra@samba.org +Reviewed-by: Ralph Boehme slow@samba.org
+Autobuild-User(master): Ralph Böhme slow@samba.org +Autobuild-Date(master): Tue Mar 28 17:05:27 CEST 2017 on sn-devel-144
+(cherry picked from commit 4e734fcd1bf82c08aa303ce44e9735acccffcf06) +---
- source3/script/tests/test_smbclient_s3.sh | 37
+++++++++++++++++++++++++++++++
- 1 file changed, 37 insertions(+)
+diff --git a/source3/script/tests/test_smbclient_s3.sh b/source3/script/tests/test_smbclient_s3.sh +index bd5714fca6e..885766f6c16 100755 +--- a/source3/script/tests/test_smbclient_s3.sh ++++ b/source3/script/tests/test_smbclient_s3.sh +@@ -408,14 +408,22 @@ test_nosymlinks()
slink_name="$LOCAL_PATH/nosymlinks/source"
slink_target="$LOCAL_PATH/nosymlinks/target"
mkdir_target="$LOCAL_PATH/nosymlinks/a"
++ dir1="$LOCAL_PATH/nosymlinks/foo" ++ dir2="$LOCAL_PATH/nosymlinks/foo/bar" ++ get_target="$LOCAL_PATH/nosymlinks/foo/bar/testfile"
rm -f $slink_target
rm -f $slink_name
rm -rf $mkdir_target
++ rm -rf $dir1
touch $slink_target
ln -s $slink_target $slink_name
++ mkdir $dir1 ++ mkdir $dir2 ++ touch $get_target ++
- # Getting a file through a symlink name should fail.
tmpfile=$PREFIX/smbclient_interactive_prompt_commands
cat > $tmpfile <<EOF
+@@ -470,6 +478,35 @@ EOF
- echo "failed - NT_STATUS_XXXX doing mkdir a; mkdir a\b on
\nosymlinks"
- false
fi
++ ++# Ensure regular file/directory access also works. ++ cat > $tmpfile <<EOF ++cd foo\bar ++ls ++get testfile - ++quit ++EOF ++ cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT "$@" -U$USERNAME%$PASSWORD //$SERVER/nosymlinks -I $SERVER_IP $ADDARGS < $tmpfile 2>&1' ++ eval echo "$cmd" ++ out=`eval $cmd` ++ ret=$? ++ rm -f $tmpfile ++ ++ if [ $ret -ne 0 ] ; then ++ echo "$out" ++ echo "failed accessing nosymlinks with error $ret" ++ false ++ return ++ fi ++ ++ echo "$out" | grep 'NT_STATUS' ++ ret=$? ++ if [ $ret -eq 0 ] ; then ++ echo "$out" ++ echo "failed - NT_STATUS_XXXX doing cd foo\bar; get testfile on \nosymlinks" ++ false ++ return ++ fi
- }
- testit "smbclient -L $SERVER_IP" $SMBCLIENT -L $SERVER_IP -N -p 139 ||
failed=`expr $failed + 1` +-- +2.12.0
diff --git a/src/patches/samba/samba-3.6.25-CVE-2017-7494.patch b/src/patches/samba/samba-3.6.25-CVE-2017-7494.patch new file mode 100644 index 000000000..54bb1841b --- /dev/null +++ b/src/patches/samba/samba-3.6.25-CVE-2017-7494.patch @@ -0,0 +1,14 @@ +--- source3/rpc_server/srv_pipe.c Sun Feb 22 16:11:32 2015 ++++ source3/rpc_server/srv_pipe.c Fri May 26 17:28:40 2017 +@@ -465,6 +465,11 @@
- const char *pipename = cli_filename;
- NTSTATUS status;
++ if (strchr(pipename, '/')) { ++ DEBUG(1, ("Refusing open on pipe %s\n", pipename)); ++ return false; ++ } ++
- if (strnequal(pipename, "\PIPE\", 6)) {
pipename += 5;
- }
diff --git a/src/patches/samba/samba-3.6.25-security-2015-12-16.patch b/src/patches/samba/samba-3.6.25-security-2015-12-16.patch new file mode 100644 index 000000000..df1057fea --- /dev/null +++ b/src/patches/samba/samba-3.6.25-security-2015-12-16.patch @@ -0,0 +1,255 @@ +From 2e94b6ec10f1d15e24867bab3063bb85f173406a Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Thu, 9 Jul 2015 10:58:11 -0700 +Subject: [PATCH] CVE-2015-5252: s3: smbd: Fix symlink verification (file
- access outside the share).
+Ensure matching component ends in '/' or '\0'.
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=11395
+Signed-off-by: Jeremy Allison jra@samba.org +Reviewed-by: Volker Lendecke vl@samba.org +---
- source3/smbd/vfs.c | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
+diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c +index 6c56964..bd93b7f 100644 +--- a/source3/smbd/vfs.c ++++ b/source3/smbd/vfs.c +@@ -982,6 +982,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
- if (!allow_widelinks || !allow_symlinks) {
const char *conn_rootdir;
size_t rootdir_len;
++ bool matched;
conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
if (conn_rootdir == NULL) {
+@@ -992,8 +993,10 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
}
rootdir_len = strlen(conn_rootdir);
+- if (strncmp(conn_rootdir, resolved_name, +- rootdir_len) != 0) { ++ matched = (strncmp(conn_rootdir, resolved_name, ++ rootdir_len) == 0); ++ if (!matched || (resolved_name[rootdir_len] != '/' && ++ resolved_name[rootdir_len] != '\0')) {
DEBUG(2, ("check_reduced_name: Bad access "
"attempt: %s is a symlink outside the "
"share path\n", fname));
+-- +2.5.0
+From 25139116756cc285a3a5534834cc276ef1b7baaa Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher metze@samba.org +Date: Wed, 30 Sep 2015 21:17:02 +0200 +Subject: [PATCH 1/2] CVE-2015-5296: s3:libsmb: force signing when requiring
- encryption in do_connect()
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=11536
+Signed-off-by: Stefan Metzmacher metze@samba.org +Reviewed-by: Jeremy Allison jra@samba.org +---
- source3/libsmb/clidfs.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
+diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c +index 23e1471..f153b6b 100644 +--- a/source3/libsmb/clidfs.c ++++ b/source3/libsmb/clidfs.c +@@ -98,6 +98,11 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
- const char *username;
- const char *password;
- NTSTATUS status;
++ int signing_state = get_cmdline_auth_info_signing_state(auth_info); ++ ++ if (force_encrypt) { ++ signing_state = Required; ++ }
- /* make a copy so we don't modify the global string 'service' */
- servicename = talloc_strdup(ctx,share);
+@@ -132,7 +137,7 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
- zero_sockaddr(&ss);
- /* have to open a new connection */
+- c = cli_initialise_ex(get_cmdline_auth_info_signing_state(auth_info)); ++ c = cli_initialise_ex(signing_state);
- if (c == NULL) {
d_printf("Connection to %s failed\n", server_n);
return NULL;
+-- +2.5.0
+From 060adb0abdeda51b8b622c6020b5dea0c8dde1cf Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher metze@samba.org +Date: Wed, 30 Sep 2015 21:17:02 +0200 +Subject: [PATCH 2/2] CVE-2015-5296: s3:libsmb: force signing when requiring
- encryption in SMBC_server_internal()
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=11536
+Signed-off-by: Stefan Metzmacher metze@samba.org +Reviewed-by: Jeremy Allison jra@samba.org +---
- source3/libsmb/libsmb_server.c | 13 +++++++++++--
- 1 file changed, 11 insertions(+), 2 deletions(-)
+diff --git a/source3/libsmb/libsmb_server.c b/source3/libsmb/libsmb_server.c +index 45be660..167f2c9 100644 +--- a/source3/libsmb/libsmb_server.c ++++ b/source3/libsmb/libsmb_server.c +@@ -258,6 +258,7 @@ SMBC_server_internal(TALLOC_CTX *ctx,
const char *username_used;
- NTSTATUS status;
- char *newserver, *newshare;
++ int signing_state = Undefined;
- zero_sockaddr(&ss);
- ZERO_STRUCT(c);
+@@ -404,8 +405,12 @@ again:
- zero_sockaddr(&ss);
++ if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) { ++ signing_state = Required; ++ } ++
- /* have to open a new connection */
+- if ((c = cli_initialise()) == NULL) { ++ if ((c = cli_initialise_ex(signing_state)) == NULL) {
errno = ENOMEM;
return NULL;
- }
+@@ -750,6 +755,7 @@ SMBC_attr_server(TALLOC_CTX *ctx,
ipc_srv = SMBC_find_server(ctx, context, server, "*IPC$",
pp_workgroup, pp_username, pp_password);
if (!ipc_srv) {
++ int signing_state = Undefined;
/* We didn't find a cached connection. Get the password */
if (!*pp_password || (*pp_password)[0] == '\0') {
+@@ -771,6 +777,9 @@ SMBC_attr_server(TALLOC_CTX *ctx,
if (smbc_getOptionUseCCache(context)) {
flags |= CLI_FULL_CONNECTION_USE_CCACHE;
}
++ if (context->internal->smb_encryption_level != SMBC_ENCRYPTLEVEL_NONE) { ++ signing_state = Required; ++ }
zero_sockaddr(&ss);
nt_status = cli_full_connection(&ipc_cli,
+@@ -780,7 +789,7 @@ SMBC_attr_server(TALLOC_CTX *ctx,
*pp_workgroup,
*pp_password,
flags,
+- Undefined); ++ signing_state);
if (! NT_STATUS_IS_OK(nt_status)) {
DEBUG(1,("cli_full_connection failed! (%s)\n",
nt_errstr(nt_status)));
+-- +2.5.0
+From 8e49de7754f7171a58a1f94dee0f1138dbee3c60 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison jra@samba.org +Date: Fri, 23 Oct 2015 14:54:31 -0700 +Subject: [PATCH] CVE-2015-5299: s3-shadow-copy2: fix missing access check on
- snapdir
+Fix originally from partha@exablox.com
+https://bugzilla.samba.org/show_bug.cgi?id=11529
+Signed-off-by: Jeremy Allison jra@samba.org +Reviewed-by: David Disseldorp ddiss@samba.org +---
- source3/modules/vfs_shadow_copy2.c | 47
++++++++++++++++++++++++++++++++++++++
- 1 file changed, 47 insertions(+)
+diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c +index fedfb53..16c1ed7 100644 +--- a/source3/modules/vfs_shadow_copy2.c ++++ b/source3/modules/vfs_shadow_copy2.c +@@ -21,6 +21,8 @@
- #include "includes.h"
- #include "smbd/smbd.h"
++#include "smbd/globals.h" ++#include "../libcli/security/security.h"
- #include "system/filesys.h"
- #include "ntioctl.h"
+@@ -764,6 +766,43 @@ static int shadow_copy2_mkdir(vfs_handle_struct *handle, const char *fname, mod
SHADOW2_NEXT(MKDIR, (handle, name, mode), int, -1);
- }
++static bool check_access_snapdir(struct vfs_handle_struct *handle, ++ const char *path) ++{ ++ struct smb_filename smb_fname; ++ int ret; ++ NTSTATUS status; ++ uint32_t access_granted = 0; ++ ++ ZERO_STRUCT(smb_fname); ++ smb_fname.base_name = talloc_asprintf(talloc_tos(), ++ "%s", ++ path); ++ if (smb_fname.base_name == NULL) { ++ return false; ++ } ++ ++ ret = SMB_VFS_NEXT_STAT(handle, &smb_fname); ++ if (ret != 0 || !S_ISDIR(smb_fname.st.st_ex_mode)) { ++ TALLOC_FREE(smb_fname.base_name); ++ return false; ++ } ++ ++ status = smbd_check_open_rights(handle->conn, ++ &smb_fname, ++ SEC_DIR_LIST, ++ &access_granted); ++ if (!NT_STATUS_IS_OK(status)) { ++ DEBUG(0,("user does not have list permission " ++ "on snapdir %s\n", ++ smb_fname.base_name)); ++ TALLOC_FREE(smb_fname.base_name); ++ return false; ++ } ++ TALLOC_FREE(smb_fname.base_name); ++ return true; ++} ++
- static int shadow_copy2_rmdir(vfs_handle_struct *handle, const char *fname)
- {
SHADOW2_NEXT(RMDIR, (handle, name), int, -1);
+@@ -877,6 +916,7 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
- SMB_STRUCT_DIRENT *d;
- TALLOC_CTX *tmp_ctx = talloc_new(handle->data);
- char *snapshot;
++ bool ret;
- snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle);
- if (snapdir == NULL) {
+@@ -886,6 +926,13 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
talloc_free(tmp_ctx);
return -1;
- }
++ ret = check_access_snapdir(handle, snapdir); ++ if (!ret) { ++ DEBUG(0,("access denied on listing snapdir %s\n", snapdir)); ++ errno = EACCES; ++ talloc_free(tmp_ctx); ++ return -1; ++ }
- p = SMB_VFS_NEXT_OPENDIR(handle, snapdir, NULL, 0);
+-- +2.5.0