Jeremie Courreges-Anglas <[email protected]> writes:
> Hi,
>
> the last security update introduced a regression.
>
> -->8--
> This is a bug fix release to address a regression introduced by the security
> fixes for CVE-2017-2619 (Symlink race allows access outside share definition).
> Please see https://bugzilla.samba.org/show_bug.cgi?id=12721 for details.
>
>
> Changes since 4.5.7:
> --------------------
>
> o Jeremy Allison <[email protected]>
> * BUG 12721: Fix regression with "follow symlinks = no".
> --8<--
>
> The actual changes are just:
>
> http://autogeree.net/~jca/tmp/samba-4.5.8-code-changes.txt
>
> This should go in 6.1. ok?
>
> I'll try to cook a patch for 6.0 soonish.
Here's the diff, fixes from samba-4.4.13 backported to 4.4.5.
Build-tested only, test reports welcome.
Index: Makefile
===================================================================
RCS file: /d/cvs/ports/net/samba/Makefile,v
retrieving revision 1.227.2.3
diff -u -p -r1.227.2.3 Makefile
--- Makefile 27 Mar 2017 23:26:23 -0000 1.227.2.3
+++ Makefile 31 Mar 2017 23:53:44 -0000
@@ -15,7 +15,7 @@ PKGNAME-tevent = tevent-${TEVENT_V}
PKGNAME-util = samba-util-${VERSION}
PKGNAME-docs = samba-docs-${VERSION}
-REVISION-main = 2
+REVISION-main = 3
REVISION-ldb = 0
REVISION-tevent = 0
Index: patches/patch-source3_smbd_filename_c
===================================================================
RCS file: patches/patch-source3_smbd_filename_c
diff -N patches/patch-source3_smbd_filename_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-source3_smbd_filename_c 1 Apr 2017 11:46:06 -0000
@@ -0,0 +1,12 @@
+$OpenBSD$
+--- source3/smbd/filename.c.orig Sat Apr 1 13:43:13 2017
++++ source3/smbd/filename.c Sat Apr 1 13:45:32 2017
+@@ -1067,7 +1067,7 @@ NTSTATUS check_name(connection_struct *conn, const cha
+ }
+
+ if (!lp_widelinks(SNUM(conn)) || !lp_follow_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)));
Index: patches/patch-source3_smbd_open_c
===================================================================
RCS file: /d/cvs/ports/net/samba/patches/Attic/patch-source3_smbd_open_c,v
retrieving revision 1.2.2.1
diff -u -p -r1.2.2.1 patch-source3_smbd_open_c
--- patches/patch-source3_smbd_open_c 27 Mar 2017 23:26:23 -0000 1.2.2.1
+++ patches/patch-source3_smbd_open_c 1 Apr 2017 11:51:46 -0000
@@ -2,8 +2,8 @@ $OpenBSD: patch-source3_smbd_open_c,v 1.
CVE-2017-2619 (Symlink race allows access outside share definition)
---- source3/smbd/open.c.orig Sat Mar 25 17:19:25 2017
-+++ source3/smbd/open.c Sat Mar 25 17:19:50 2017
+--- source3/smbd/open.c.orig Sat Apr 1 13:49:49 2017
++++ source3/smbd/open.c Sat Apr 1 13:51:43 2017
@@ -345,6 +345,268 @@ static NTSTATUS check_base_file_access(struct connecti
}
@@ -202,7 +202,7 @@ CVE-2017-2619 (Symlink race allows acces
+ }
+
+ /* 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;
Index: patches/patch-source3_smbd_proto_h
===================================================================
RCS file: patches/patch-source3_smbd_proto_h
diff -N patches/patch-source3_smbd_proto_h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-source3_smbd_proto_h 1 Apr 2017 11:46:06 -0000
@@ -0,0 +1,14 @@
+$OpenBSD$
+--- source3/smbd/proto.h.orig Sat Apr 1 13:43:13 2017
++++ source3/smbd/proto.h Sat Apr 1 13:45:32 2017
+@@ -1197,7 +1197,9 @@ const char *vfs_readdirname(connection_struct *conn, v
+ 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);
+ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
+ const char *fname,
+ struct smb_request *smbreq);
Index: patches/patch-source3_smbd_vfs_c
===================================================================
RCS file: patches/patch-source3_smbd_vfs_c
diff -N patches/patch-source3_smbd_vfs_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-source3_smbd_vfs_c 1 Apr 2017 11:46:06 -0000
@@ -0,0 +1,80 @@
+$OpenBSD$
+--- source3/smbd/vfs.c.orig Sat Apr 1 13:43:13 2017
++++ source3/smbd/vfs.c Sat Apr 1 13:45:32 2017
+@@ -1149,11 +1149,20 @@ NTSTATUS check_reduced_name_with_privilege(connection_
+ /*******************************************************************
+ 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;
+
+@@ -1277,8 +1286,11 @@ NTSTATUS check_reduced_name(connection_struct *conn, c
+ /* 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;
+ }
+
+@@ -1292,11 +1304,32 @@ NTSTATUS check_reduced_name(connection_struct *conn, c
+ }
+
+ 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 to %s\n",
+ fname, p));
+ SAFE_FREE(resolved_name);
++ TALLOC_FREE(new_fname);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ }
+@@ -1306,6 +1339,7 @@ NTSTATUS check_reduced_name(connection_struct *conn, c
+
+ DBG_INFO("%s reduced to %s\n", fname, resolved_name);
+ SAFE_FREE(resolved_name);
++ TALLOC_FREE(new_fname);
+ return NT_STATUS_OK;
+ }
+
--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE