samba: import security updates from redhead
authorArne Fitzenreiter <arne_f@ipfire.org>
Mon, 27 Nov 2017 17:20:59 +0000 (18:20 +0100)
committerArne Fitzenreiter <arne_f@ipfire.org>
Mon, 27 Nov 2017 17:20:59 +0000 (18:20 +0100)
Signed-off-by: Arne Fitzenreiter <arne_f@ipfire.org>
lfs/samba
src/patches/samba/CVE-2017-12150-v3-6.patch [new file with mode: 0644]
src/patches/samba/CVE-2017-12163.patch [new file with mode: 0644]
src/patches/samba/CVE-2017-15275.patch [new file with mode: 0644]
src/patches/samba/CVE-2017-2619.patch [new file with mode: 0644]
src/patches/samba/samba-3.6.99-winbind_fix_trusted_domain_handling.patch [new file with mode: 0644]

index d54d507..6842e18 100644 (file)
--- a/lfs/samba
+++ b/lfs/samba
@@ -32,7 +32,7 @@ DL_FROM    = $(URL_IPFIRE)
 DIR_APP    = $(DIR_SRC)/$(THISAPP)
 TARGET     = $(DIR_INFO)/$(THISAPP)
 PROG       = samba
-PAK_VER    = 67
+PAK_VER    = 68
 
 DEPS       = "cups krb5"
 
@@ -152,9 +152,12 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
        cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/samba-3.6.99-fix_member_auth_after_changed_secret.patch
        cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/samba-3.6.99-fix_dirsort_ea-support.patch
        cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2017-7494-v3-6.patch
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/samba-3.6.99-winbind_fix_trusted_domain_handling.patch
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2017-2619.patch
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2017-12150-v3-6.patch
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2017-12163.patch
+       cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/CVE-2017-15275.patch
        cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/doc-update.patch
-#      cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/samba/samba-3.6.x-winbind_tevent_poll.patch
-
 
        cd $(DIR_APP)/source3 && ./autogen.sh
        cd $(DIR_APP)/source3 && ./configure \
diff --git a/src/patches/samba/CVE-2017-12150-v3-6.patch b/src/patches/samba/CVE-2017-12150-v3-6.patch
new file mode 100644 (file)
index 0000000..b221a84
--- /dev/null
@@ -0,0 +1,102 @@
+From d3198caa7a8910a9ce1eb4104d5b410ef29ac2bb Mon Sep 17 00:00:00 2001
+From: Stefan Metzmacher <metze@samba.org>
+Date: Thu, 3 Nov 2016 17:16:43 +0100
+Subject: [PATCH 1/3] CVE-2017-12150: s3:lib:
+ get_cmdline_auth_info_signing_state use Required for smb_encrypt
+
+This is an addition to the fixes for CVE-2015-5296.
+
+It applies to smb2mount -e, smbcacls -e and smbcquotas -e.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12997
+
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+Backported-by: Andreas Schneider <asn@samba.org>
+---
+ source3/lib/util_cmdline.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/source3/lib/util_cmdline.c b/source3/lib/util_cmdline.c
+index cb0b79a5d30..3178c848b63 100644
+--- a/source3/lib/util_cmdline.c
++++ b/source3/lib/util_cmdline.c
+@@ -122,6 +122,9 @@ bool set_cmdline_auth_info_signing_state(struct user_auth_info *auth_info,
+ int get_cmdline_auth_info_signing_state(const struct user_auth_info *auth_info)
+ {
++      if (auth_info->smb_encrypt) {
++              return Required;
++      }
+       return auth_info->signing_state;
+ }
+-- 
+2.14.1
+
+
+From bb762a74c81159633f904f8fb67b49bab74a0b9c Mon Sep 17 00:00:00 2001
+From: Stefan Metzmacher <metze@samba.org>
+Date: Mon, 12 Dec 2016 05:49:46 +0100
+Subject: [PATCH 2/3] CVE-2017-12150: libgpo: make use of Required for SMB
+ signing in gpo_connect_server()
+
+It's important that we use a signed connection to get the GPOs!
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12997
+
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+Backported-by: Andreas Schneider <asn@samba.org>
+---
+ libgpo/gpo_fetch.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/libgpo/gpo_fetch.c b/libgpo/gpo_fetch.c
+index 3cfe1d5b942..af012e01336 100644
+--- a/libgpo/gpo_fetch.c
++++ b/libgpo/gpo_fetch.c
+@@ -151,7 +151,7 @@ static NTSTATUS gpo_connect_server(ADS_STRUCT *ads, struct loadparm_context *lp_
+                       ads->auth.password,
+                       CLI_FULL_CONNECTION_USE_KERBEROS |
+                       CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS,
+-                      Undefined);
++                      Required);
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10,("check_refresh_gpo: "
+                               "failed to connect: %s\n",
+-- 
+2.14.1
+
+
+From 070b0fb9ebb57cdbc2b82e335de021fb46bc543c Mon Sep 17 00:00:00 2001
+From: Stefan Metzmacher <metze@samba.org>
+Date: Mon, 12 Dec 2016 06:07:56 +0100
+Subject: [PATCH 3/3] CVE-2017-12150: s3:libsmb: only fallback to anonymous if
+ authentication was not requested
+
+With forced encryption or required signing we should also don't fallback.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=12997
+
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+Backported-by: Andreas Schneider <asn@samba.org>
+---
+ source3/libsmb/clidfs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
+index 23e147120f1..120a2c999ce 100644
+--- a/source3/libsmb/clidfs.c
++++ b/source3/libsmb/clidfs.c
+@@ -197,7 +197,9 @@ static struct cli_state *do_connect(TALLOC_CTX *ctx,
+               /* If a password was not supplied then
+                * try again with a null username. */
+               if (password[0] || !username[0] ||
++                      force_encrypt || client_is_signing_mandatory(c) ||
+                       get_cmdline_auth_info_use_kerberos(auth_info) ||
++                      get_cmdline_auth_info_use_ccache(auth_info) ||
+                       !NT_STATUS_IS_OK(cli_session_setup(c, "",
+                                               "", 0,
+                                               "", 0,
+-- 
+2.14.1
+
diff --git a/src/patches/samba/CVE-2017-12163.patch b/src/patches/samba/CVE-2017-12163.patch
new file mode 100644 (file)
index 0000000..93fe2ce
--- /dev/null
@@ -0,0 +1,141 @@
+From 9f1a51917649795123bedbefdea678317d392b48 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Fri, 8 Sep 2017 10:13:14 -0700
+Subject: [PATCH] CVE-2017-12163: s3:smbd: Prevent client short SMB1 write from
+ writing server memory to file.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=13020
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+---
+ source3/smbd/reply.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 50 insertions(+)
+
+diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
+index 1583c2358bb..9625670d653 100644
+--- a/source3/smbd/reply.c
++++ b/source3/smbd/reply.c
+@@ -3977,6 +3977,9 @@ void reply_writebraw(struct smb_request *req)
+       }
+       /* Ensure we don't write bytes past the end of this packet. */
++      /*
++       * This already protects us against CVE-2017-12163.
++       */
+       if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               error_to_writebrawerr(req);
+@@ -4078,6 +4081,11 @@ void reply_writebraw(struct smb_request *req)
+                       exit_server_cleanly("secondary writebraw failed");
+               }
++              /*
++               * We are not vulnerable to CVE-2017-12163
++               * here as we are guarenteed to have numtowrite
++               * bytes available - we just read from the client.
++               */
+               nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
+               if (nwritten == -1) {
+                       TALLOC_FREE(buf);
+@@ -4159,6 +4167,7 @@ void reply_writeunlock(struct smb_request *req)
+       connection_struct *conn = req->conn;
+       ssize_t nwritten = -1;
+       size_t numtowrite;
++      size_t remaining;
+       SMB_OFF_T startpos;
+       const char *data;
+       NTSTATUS status = NT_STATUS_OK;
+@@ -4191,6 +4200,17 @@ void reply_writeunlock(struct smb_request *req)
+       startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
+       data = (const char *)req->buf + 3;
++      /*
++       * Ensure client isn't asking us to write more than
++       * they sent. CVE-2017-12163.
++       */
++      remaining = smbreq_bufrem(req, data);
++      if (numtowrite > remaining) {
++              reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
++              END_PROFILE(SMBwriteunlock);
++              return;
++      }
++
+       if (!fsp->print_file && numtowrite > 0) {
+               init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
+                   (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
+@@ -4272,6 +4292,7 @@ void reply_write(struct smb_request *req)
+ {
+       connection_struct *conn = req->conn;
+       size_t numtowrite;
++      size_t remaining;
+       ssize_t nwritten = -1;
+       SMB_OFF_T startpos;
+       const char *data;
+@@ -4312,6 +4333,17 @@ void reply_write(struct smb_request *req)
+       startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
+       data = (const char *)req->buf + 3;
++      /*
++       * Ensure client isn't asking us to write more than
++       * they sent. CVE-2017-12163.
++       */
++      remaining = smbreq_bufrem(req, data);
++      if (numtowrite > remaining) {
++              reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
++              END_PROFILE(SMBwrite);
++              return;
++      }
++
+       if (!fsp->print_file) {
+               init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
+                       (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
+@@ -4523,6 +4555,9 @@ void reply_write_and_X(struct smb_request *req)
+                       return;
+               }
+       } else {
++              /*
++               * This already protects us against CVE-2017-12163.
++               */
+               if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
+                               smb_doff + numtowrite > smblen) {
+                       reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+@@ -4892,6 +4927,7 @@ void reply_writeclose(struct smb_request *req)
+ {
+       connection_struct *conn = req->conn;
+       size_t numtowrite;
++      size_t remaining;
+       ssize_t nwritten = -1;
+       NTSTATUS close_status = NT_STATUS_OK;
+       SMB_OFF_T startpos;
+@@ -4925,6 +4961,17 @@ void reply_writeclose(struct smb_request *req)
+       mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
+       data = (const char *)req->buf + 1;
++      /*
++       * Ensure client isn't asking us to write more than
++       * they sent. CVE-2017-12163.
++       */
++      remaining = smbreq_bufrem(req, data);
++      if (numtowrite > remaining) {
++              reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
++              END_PROFILE(SMBwriteclose);
++              return;
++      }
++
+       if (!fsp->print_file) {
+               init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
+                   (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
+@@ -5495,6 +5542,9 @@ void reply_printwrite(struct smb_request *req)
+       numtowrite = SVAL(req->buf, 1);
++      /*
++       * This already protects us against CVE-2017-12163.
++       */
+       if (req->buflen < numtowrite + 3) {
+               reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               END_PROFILE(SMBsplwr);
+-- 
+2.13.5
+
diff --git a/src/patches/samba/CVE-2017-15275.patch b/src/patches/samba/CVE-2017-15275.patch
new file mode 100644 (file)
index 0000000..758672e
--- /dev/null
@@ -0,0 +1,45 @@
+From c1a22e59f87783d88dfbaeeb132b89be166b2754 Mon Sep 17 00:00:00 2001
+From: Jeremy Allison <jra@samba.org>
+Date: Wed, 20 Sep 2017 11:04:50 -0700
+Subject: [PATCH 2/2] s3: smbd: Chain code can return uninitialized memory when
+ talloc buffer is grown.
+
+Ensure we zero out unused grown area.
+
+CVE-2017-15275
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=13077
+
+Signed-off-by: Jeremy Allison <jra@samba.org>
+---
+ source3/smbd/srvstr.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/source3/smbd/srvstr.c b/source3/smbd/srvstr.c
+index 56dceba8c6c..c2d70b32c32 100644
+--- a/source3/smbd/srvstr.c
++++ b/source3/smbd/srvstr.c
+@@ -110,6 +110,20 @@ ssize_t message_push_string(uint8_t **outbuf, const char *str, int flags)
+               DEBUG(0, ("srvstr_push failed\n"));
+               return -1;
+       }
++
++      /*
++       * Ensure we clear out the extra data we have
++       * grown the buffer by, but not written to.
++       */
++      if (buf_size + result < buf_size) {
++              return -1;
++      }
++      if (grow_size < result) {
++              return -1;
++      }
++
++      memset(tmp + buf_size + result, '\0', grow_size - result);
++
+       set_message_bcc((char *)tmp, smb_buflen(tmp) + result);
+       *outbuf = tmp;
+-- 
+2.11.0
+
diff --git a/src/patches/samba/CVE-2017-2619.patch b/src/patches/samba/CVE-2017-2619.patch
new file mode 100644 (file)
index 0000000..149e085
--- /dev/null
@@ -0,0 +1,1328 @@
+From a398754c9bb1639f762979765de6c540c714b5cb 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(-)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index 441b8cd4362..35eee0a1485 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -197,7 +197,7 @@ static NTSTATUS check_base_file_access(struct connection_struct *conn,
+  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)
+diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
+index f5fad2bbb50..594edfa1e98 100644
+--- a/source3/smbd/proto.h
++++ b/source3/smbd/proto.h
+@@ -603,6 +603,8 @@ NTSTATUS smb1_file_se_access_check(connection_struct *conn,
+                               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,
+diff --git a/source3/smbd/smb2_find.c b/source3/smbd/smb2_find.c
+index 6fe6545c128..9dd3176497b 100644
+--- a/source3/smbd/smb2_find.c
++++ b/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,
+@@ -301,7 +302,23 @@ static struct tevent_req *smbd_smb2_find_send(TALLOC_CTX *mem_ctx,
+       }
+       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);
++              }
+       }
+       wcard_has_wild = ms_has_wild(in_file_name);
+-- 
+2.13.5
+
+
+From a35fa98b99aa60132eb2c083d6393c28905e2045 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(+)
+
+diff --git a/source3/modules/vfs_dirsort.c b/source3/modules/vfs_dirsort.c
+index 66582e67890..dbcf0b16ed3 100644
+--- a/source3/modules/vfs_dirsort.c
++++ b/source3/modules/vfs_dirsort.c
+@@ -153,6 +153,10 @@ static SMB_STRUCT_DIR *dirsort_opendir(vfs_handle_struct *handle,
+               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);
+-- 
+2.13.5
+
+
+From 23d2849d724a0f5bdf51dc7d7db438ed9fb4c2a9 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(-)
+
+diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
+index 731c813f4d7..be46f8dc1e6 100644
+--- a/source3/modules/vfs_streams_xattr.c
++++ b/source3/modules/vfs_streams_xattr.c
+@@ -511,8 +511,15 @@ static int streams_xattr_open(vfs_handle_struct *handle,
+         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;
+-- 
+2.13.5
+
+
+From 91935aaf77c70e3e2436af1d6e4a538d29fd4276 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(-)
+
+diff --git a/source3/modules/vfs_streams_xattr.c b/source3/modules/vfs_streams_xattr.c
+index be46f8dc1e6..a4ab84bba71 100644
+--- a/source3/modules/vfs_streams_xattr.c
++++ b/source3/modules/vfs_streams_xattr.c
+@@ -229,7 +229,7 @@ static int streams_xattr_fstat(vfs_handle_struct *handle, files_struct *fsp,
+               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 @@ static int streams_xattr_open(vfs_handle_struct *handle,
+       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 @@ static int streams_xattr_open(vfs_handle_struct *handle,
+       /* 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;
++              /* 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;
++              }
+-        hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
+-                            baseflags, mode);
++              /*
++               * 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;
+-      TALLOC_FREE(smb_fname_base);
++              hostfd = SMB_VFS_OPEN(handle->conn, smb_fname_base, fsp,
++                                    baseflags, mode);
+-        /* 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);
+-        }
++              TALLOC_FREE(smb_fname_base);
+-        if (hostfd == -1) {
+-              goto fail;
+-        }
++              /* 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);
++              }
+-      status = get_ea_value(talloc_tos(), handle->conn, NULL,
+-                            smb_fname->base_name, xattr_name, &ea);
++              if (hostfd == -1) {
++                      goto fail;
++              }
+-      DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
++              status = get_ea_value(talloc_tos(), handle->conn, NULL,
++                                    smb_fname->base_name, xattr_name, &ea);
+-      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.
+-               */
+-              DEBUG(10, ("streams_xattr_open: base file %s not around, "
+-                         "returning ENOENT\n", smb_fname->base_name));
+-              errno = ENOENT;
+-              goto fail;
+-      }
++              DEBUG(10, ("get_ea_value returned %s\n", nt_errstr(status)));
+-      if (!NT_STATUS_IS_OK(status)) {
+-              /*
+-               * The attribute does not exist
+-               */
++              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.
++                       */
++                      DEBUG(10, ("streams_xattr_open: base file %s not around, "
++                                 "returning ENOENT\n", smb_fname->base_name));
++                      errno = ENOENT;
++                      goto fail;
++              }
+-                if (flags & O_CREAT) {
++              if (!NT_STATUS_IS_OK(status)) {
+                       /*
+-                       * Darn, xattrs need at least 1 byte
++                       * The attribute does not exist
+                        */
+-                        char null = '\0';
+-                      DEBUG(10, ("creating attribute %s on file %s\n",
+-                                 xattr_name, smb_fname->base_name));
++                      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) {
+@@ -868,7 +861,7 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
+               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;
+@@ -892,13 +885,13 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
+         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);
+       }
+@@ -932,7 +925,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
+               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;
+@@ -977,7 +970,7 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
+               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;
+@@ -1002,13 +995,13 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
+       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);
+       }
+-- 
+2.13.5
+
+
+From 3f3c731faaa59f4d3ce7e49c12795c40e048d29f 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(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 18ecf066824..ebe2641f813 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1367,7 +1367,8 @@ static int smb_Dir_destructor(struct smb_Dir *dirp)
+  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)
+@@ -1407,6 +1408,18 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
+       return NULL;
+ }
++struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
++                      const char *name,
++                      const char *mask,
++                      uint32_t attr)
++{
++      return OpenDir_internal(mem_ctx,
++                              conn,
++                              name,
++                              mask,
++                              attr);
++}
++
+ /*******************************************************************
+  Open a directory from an fsp.
+ ********************************************************************/
+-- 
+2.13.5
+
+
+From 7efeb067c1586e0f1cfbb775b1efcb3b92005140 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(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index ebe2641f813..65327dd0dd1 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1380,6 +1380,13 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
+               return NULL;
+       }
++      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));
+@@ -1394,13 +1401,6 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
+       }
+       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:
+-- 
+2.13.5
+
+
+From 49d22a0c51ef1f78f0488a7c35131887704e987b 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(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 65327dd0dd1..2d168c3ba9f 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1390,12 +1390,6 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
+       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;
+-              goto fail;
+-      }
+-
+       if (sconn && !sconn->using_smb2) {
+               sconn->searches.dirhandles_open++;
+       }
+@@ -1408,12 +1402,70 @@ static struct smb_Dir *OpenDir_internal(TALLOC_CTX *mem_ctx,
+       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 OpenDir_internal(mem_ctx,
++      return open_dir_safely(mem_ctx,
+                               conn,
+                               name,
+                               mask,
+-- 
+2.13.5
+
+
+From 6426ae1f9ef53158a6fbe1912dfec40d834115fe 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(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 2d168c3ba9f..6aed4a6da46 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1485,7 +1485,17 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+       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;
+@@ -1502,18 +1512,16 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+       }
+       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) {
++                      return NULL;
+               }
+       }
+-- 
+2.13.5
+
+
+From f6581858ce665b880c5fea465ec61b1b0c504d89 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(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 6aed4a6da46..efd1a73aab6 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1521,7 +1521,7 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+                       dirp->dir_path,
+                       strerror(errno)));
+               if (errno != ENOSYS) {
+-                      return NULL;
++                      goto fail;
+               }
+       }
+-- 
+2.13.5
+
+
+From bacba6987e58d44886d04b1dd5e36f7781dcd9b0 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(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index efd1a73aab6..5eca128c033 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1507,11 +1507,6 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+               goto fail;
+       }
+-      if (sconn && !sconn->using_smb2) {
+-              sconn->searches.dirhandles_open++;
+-      }
+-      talloc_set_destructor(dirp, smb_Dir_destructor);
+-
+       dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
+       if (dirp->dir != NULL) {
+               dirp->fsp = fsp;
+@@ -1536,6 +1531,11 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+               goto fail;
+       }
++      if (sconn && !sconn->using_smb2) {
++              sconn->searches.dirhandles_open++;
++      }
++      talloc_set_destructor(dirp, smb_Dir_destructor);
++
+       return dirp;
+   fail:
+-- 
+2.13.5
+
+
+From 34b3d05b55f5c40de76ba65d6b028818518a519f 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(-)
+
+diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
+index 5eca128c033..7690cb18c1a 100644
+--- a/source3/smbd/dir.c
++++ b/source3/smbd/dir.c
+@@ -1521,14 +1521,13 @@ static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
+       }
+       if (dirp->dir == NULL) {
+-              /* FDOPENDIR didn't work. Use OPENDIR instead. */
+-              dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
+-      }
+-
+-      if (!dirp->dir) {
+-              DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path,
+-                       strerror(errno) ));
+-              goto fail;
++              /* 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 (sconn && !sconn->using_smb2) {
+-- 
+2.13.5
+
+
+From 84bc8b232a4495bff270b7800833ef6785937576 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(-)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index 35eee0a1485..8417f8aca4a 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -205,8 +205,7 @@ NTSTATUS fd_open(struct connection_struct *conn,
+       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.
+        */
+@@ -214,7 +213,6 @@ NTSTATUS fd_open(struct connection_struct *conn,
+       if (fsp->posix_open || !lp_symlinks(SNUM(conn))) {
+               flags |= O_NOFOLLOW;
+       }
+-#endif
+       fsp->fh->fd = SMB_VFS_OPEN(conn, smb_fname, fsp, flags, mode);
+       if (fsp->fh->fd == -1) {
+-- 
+2.13.5
+
+
+From af0c5a266ae65ad2a638fe48a7ad7d77417f97d7 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(-)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index 8417f8aca4a..e727e89e9d8 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -194,6 +194,31 @@ static NTSTATUS check_base_file_access(struct connection_struct *conn,
+ }
+ /****************************************************************************
++ 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;
++}
++
++/****************************************************************************
+  fd support routines - attempt to do a dos_open.
+ ****************************************************************************/
+@@ -216,8 +241,9 @@ NTSTATUS fd_open(struct connection_struct *conn,
+       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) {
+-- 
+2.13.5
+
+
+From c3bc4ff0367d7a3ebfd64db6defddea0bc3a5f4a 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(+)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index e727e89e9d8..0998adc416a 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -218,6 +218,248 @@ static int link_errno_convert(int err)
+       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.
+ ****************************************************************************/
+-- 
+2.13.5
+
+
+From 6a88d1cf3deb54a784f50c8eba3b9a24a65c1b34 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(-)
+
+diff --git a/source3/smbd/open.c b/source3/smbd/open.c
+index 0998adc416a..65ca14ec8b8 100644
+--- a/source3/smbd/open.c
++++ b/source3/smbd/open.c
+@@ -481,7 +481,28 @@ NTSTATUS fd_open(struct connection_struct *conn,
+               flags |= O_NOFOLLOW;
+       }
+-      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) {
+               int posix_errno = link_errno_convert(errno);
+               status = map_nt_error_from_unix(posix_errno);
+-- 
+2.13.5
+
diff --git a/src/patches/samba/samba-3.6.99-winbind_fix_trusted_domain_handling.patch b/src/patches/samba/samba-3.6.99-winbind_fix_trusted_domain_handling.patch
new file mode 100644 (file)
index 0000000..e58f714
--- /dev/null
@@ -0,0 +1,432 @@
+From a280f61d71d5ea7e2212d253b84ac5b25810b88e Mon Sep 17 00:00:00 2001
+From: Uri Simchoni <uri@samba.org>
+Date: Wed, 10 Feb 2016 00:26:45 +0200
+Subject: [PATCH 1/4] winbindd: introduce add_trusted_domain_from_tdc()
+
+This is purely a refactoring patch -
+Add a routine that adds a winbindd domain object based on
+domain trust cache entry. add_trusted_domain() becomes
+a wrapper for this new routine.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=11691
+
+Signed-off-by: Uri Simchoni <uri@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+---
+ source3/winbindd/winbindd_util.c | 76 +++++++++++++++++++++++++---------------
+ 1 file changed, 48 insertions(+), 28 deletions(-)
+
+diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
+index 353722e..70a9041 100644
+--- a/source3/winbindd/winbindd_util.c
++++ b/source3/winbindd/winbindd_util.c
+@@ -30,6 +30,10 @@
+ #undef DBGC_CLASS
+ #define DBGC_CLASS DBGC_WINBIND
++static struct winbindd_domain *
++add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
++                          struct winbindd_methods *methods);
++
+ extern struct winbindd_methods cache_methods;
+ /**
+@@ -91,11 +95,31 @@ static bool is_in_internal_domain(const struct dom_sid *sid)
+ /* Add a trusted domain to our list of domains.
+    If the domain already exists in the list,
+-   return it and don't re-initialize.
+- */
+-static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
+-                                                struct winbindd_methods *methods,
+-                                                const struct dom_sid *sid)
++   return it and don't re-initialize.  */
++
++static struct winbindd_domain *
++add_trusted_domain(const char *domain_name, const char *alt_name,
++                 struct winbindd_methods *methods, const struct dom_sid *sid)
++{
++      struct winbindd_tdc_domain tdc;
++
++      ZERO_STRUCT(tdc);
++
++      tdc.domain_name = domain_name;
++      tdc.dns_name = alt_name;
++      if (sid) {
++              sid_copy(&tdc.sid, sid);
++      }
++
++      return add_trusted_domain_from_tdc(&tdc, methods);
++}
++
++/* Add a trusted domain out of a trusted domain cache
++   entry
++*/
++static struct winbindd_domain *
++add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
++                          struct winbindd_methods *methods)
+ {
+       struct winbindd_domain *domain;
+       const char *alternative_name = NULL;
+@@ -103,6 +127,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
+       const char *param;
+       const char **ignored_domains, **dom;
+       int role = lp_server_role();
++      const char *domain_name = tdc->domain_name;
++      const struct dom_sid *sid = &tdc->sid;
++
++      if (is_null_sid(sid)) {
++              sid = NULL;
++      }
+       ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
+       for (dom=ignored_domains; dom && *dom; dom++) {
+@@ -114,8 +144,8 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
+       /* ignore alt_name if we are not in an AD domain */
+-      if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) {
+-              alternative_name = alt_name;
++      if (tdc->dns_name && *tdc->dns_name) {
++              alternative_name = tdc->dns_name;
+       }
+       /* We can't call domain_list() as this function is called from
+@@ -127,8 +157,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
+                       break;
+               }
+-              if (alternative_name && *alternative_name)
+-              {
++              if (alternative_name) {
+                       if (strequal(alternative_name, domain->name) ||
+                           strequal(alternative_name, domain->alt_name))
+                       {
+@@ -136,12 +165,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
+                       }
+               }
+-              if (sid)
+-              {
+-                      if (is_null_sid(sid)) {
+-                              continue;
+-                      }
+-
++              if (sid != NULL) {
+                       if (dom_sid_equal(sid, &domain->sid)) {
+                               break;
+                       }
+@@ -191,11 +215,11 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
+       domain->internal = is_internal_domain(sid);
+       domain->sequence_number = DOM_SEQUENCE_NONE;
+       domain->last_seq_check = 0;
+-      domain->initialized = False;
++      domain->initialized = false;
+       domain->online = is_internal_domain(sid);
+       domain->check_online_timeout = 0;
+       domain->dc_probe_pid = (pid_t)-1;
+-      if (sid) {
++      if (sid != NULL) {
+               sid_copy(&domain->sid, sid);
+       }
+@@ -246,9 +270,9 @@ done:
+       setup_domain_child(domain);
+-      DEBUG(2,("Added domain %s %s %s\n",
+-               domain->name, domain->alt_name,
+-               &domain->sid?sid_string_dbg(&domain->sid):""));
++      DEBUG(2,
++            ("Added domain %s %s %s\n", domain->name, domain->alt_name,
++             !is_null_sid(&domain->sid) ? sid_string_dbg(&domain->sid) : ""));
+       return domain;
+ }
+@@ -432,10 +456,8 @@ static void rescan_forest_root_trusts( void )
+               d = find_domain_from_name_noinit( dom_list[i].domain_name );
+               if ( !d ) {
+-                      (void)add_trusted_domain( dom_list[i].domain_name,
+-                                              dom_list[i].dns_name,
+-                                              &cache_methods,
+-                                              &dom_list[i].sid);
++                      d = add_trusted_domain_from_tdc(&dom_list[i],
++                                                      &cache_methods);
+               }
+               if (d == NULL) {
+@@ -501,10 +523,8 @@ static void rescan_forest_trusts( void )
+                          about it */
+                       if ( !d ) {
+-                              (void)add_trusted_domain( dom_list[i].domain_name,
+-                                                      dom_list[i].dns_name,
+-                                                      &cache_methods,
+-                                                      &dom_list[i].sid);
++                              d = add_trusted_domain_from_tdc(&dom_list[i],
++                                                              &cache_methods);
+                       }
+                       if (d == NULL) {
+-- 
+2.9.4
+
+
+From 153f173eea81ffa1caa4768589a08bb20a6a1950 Mon Sep 17 00:00:00 2001
+From: Stefan Metzmacher <metze@samba.org>
+Date: Tue, 23 Dec 2014 09:43:03 +0000
+Subject: [PATCH 2/4] s3:winbindd: mark our primary as active_directory if
+ possible
+
+Signed-off-by: Stefan Metzmacher <metze@samba.org>
+Reviewed-by: Guenther Deschner <gd@samba.org>
+---
+ source3/winbindd/winbindd_util.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
+index 70a9041..700076a 100644
+--- a/source3/winbindd/winbindd_util.c
++++ b/source3/winbindd/winbindd_util.c
+@@ -232,6 +232,12 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
+               domain->primary = true;
+       }
++      if (domain->primary) {
++              if (lp_security() == SEC_ADS) {
++                      domain->active_directory = true;
++              }
++      }
++
+       /* Link to domain list */
+       DLIST_ADD_END(_domain_list, domain, struct winbindd_domain *);
+-- 
+2.9.4
+
+
+From 5d741ee3d1dafbb32c106fed817840892b69598d Mon Sep 17 00:00:00 2001
+From: Uri Simchoni <uri@samba.org>
+Date: Wed, 10 Feb 2016 00:32:23 +0200
+Subject: [PATCH 3/4] winbindd: initialize foreign domain as AD based on trust
+
+Based on trust parameters, initialize the active_directory
+member of domain object to true.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=11691
+
+Signed-off-by: Uri Simchoni <uri@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+---
+ source3/winbindd/winbindd_util.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
+index 700076a..aaa9ee8 100644
+--- a/source3/winbindd/winbindd_util.c
++++ b/source3/winbindd/winbindd_util.c
+@@ -222,6 +222,9 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
+       if (sid != NULL) {
+               sid_copy(&domain->sid, sid);
+       }
++      domain->domain_flags = tdc->trust_flags;
++      domain->domain_type = tdc->trust_type;
++      domain->domain_trust_attribs = tdc->trust_attribs;
+       /* Is this our primary domain ? */
+       if (strequal(domain_name, get_global_sam_name()) &&
+@@ -236,6 +239,10 @@ add_trusted_domain_from_tdc(const struct winbindd_tdc_domain *tdc,
+               if (lp_security() == SEC_ADS) {
+                       domain->active_directory = true;
+               }
++      } else if (!domain->internal) {
++              if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
++                      domain->active_directory = true;
++              }
+       }
+       /* Link to domain list */
+-- 
+2.9.4
+
+
+From a8ac7dcae2e3b00362ea9d91b5ef7f149bc734a0 Mon Sep 17 00:00:00 2001
+From: Uri Simchoni <uri@samba.org>
+Date: Wed, 10 Feb 2016 00:38:11 +0200
+Subject: [PATCH 4/4] winbindd: return trust parameters when listing trusts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When asking a child domain process to list trusts on that domain,
+return (along with trust domain names and SID) the trust properties -
+flags, type, and attributes.
+
+Use those attributes to initialize domain object.
+
+BUG: https://bugzilla.samba.org/show_bug.cgi?id=11691
+
+Signed-off-by: Uri Simchoni <uri@samba.org>
+Reviewed-by: Ralph Boehme <slow@samba.org>
+
+Autobuild-User(master): Ralph B√∂hme <slow@samba.org>
+Autobuild-Date(master): Tue Feb 23 22:02:16 CET 2016 on sn-devel-144
+---
+ source3/winbindd/winbindd_misc.c | 11 +++---
+ source3/winbindd/winbindd_util.c | 82 +++++++++++++++++++++++++++++-----------
+ 2 files changed, 65 insertions(+), 28 deletions(-)
+
+diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
+index 7d25167..5335ad9 100644
+--- a/source3/winbindd/winbindd_misc.c
++++ b/source3/winbindd/winbindd_misc.c
+@@ -172,11 +172,12 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
+       for (i=0; i<trusts.count; i++) {
+               extra_data = talloc_asprintf_append_buffer(
+-                      extra_data, "%s\\%s\\%s\n",
+-                      trusts.array[i].netbios_name,
+-                      trusts.array[i].dns_name,
+-                      sid_string_talloc(state->mem_ctx,
+-                                        trusts.array[i].sid));
++                  extra_data, "%s\\%s\\%s\\%u\\%u\\%u\n",
++                  trusts.array[i].netbios_name, trusts.array[i].dns_name,
++                  sid_string_talloc(state->mem_ctx, trusts.array[i].sid),
++                  trusts.array[i].trust_flags,
++                  (uint32_t)trusts.array[i].trust_type,
++                  trusts.array[i].trust_attributes);
+       }
+       /* add our primary domain */
+diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c
+index aaa9ee8..b99fac4 100644
+--- a/source3/winbindd/winbindd_util.c
++++ b/source3/winbindd/winbindd_util.c
+@@ -343,6 +343,8 @@ static void trustdom_list_done(struct tevent_req *req)
+       struct winbindd_response *response;
+       int res, err;
+       char *p;
++      struct winbindd_tdc_domain trust_params = {0};
++      ptrdiff_t extra_len;
+       res = wb_domain_request_recv(req, state, &response, &err);
+       if ((res == -1) || (response->result != WINBINDD_OK)) {
+@@ -351,17 +353,27 @@ static void trustdom_list_done(struct tevent_req *req)
+               return;
+       }
++      if (response->length < sizeof(struct winbindd_response)) {
++              DEBUG(0, ("ill-formed trustdom response - short length\n"));
++              TALLOC_FREE(state);
++              return;
++      }
++
++      extra_len = response->length - sizeof(struct winbindd_response);
++
+       p = (char *)response->extra_data.data;
+-      while ((p != NULL) && (*p != '\0')) {
++      while ((p - (char *)response->extra_data.data) < extra_len) {
+               char *q, *sidstr, *alt_name;
+-              struct dom_sid sid;
+-              struct winbindd_domain *domain;
+-              char *alternate_name = NULL;
++
++              DEBUG(10, ("parsing response line '%s'\n", p));
++
++              ZERO_STRUCT(trust_params);
++              trust_params.domain_name = p;
+               alt_name = strchr(p, '\\');
+               if (alt_name == NULL) {
+-                      DEBUG(0, ("Got invalid trustdom response\n"));
++                      DEBUG(10, ("Got invalid trustdom response\n"));
+                       break;
+               }
+@@ -370,39 +382,63 @@ static void trustdom_list_done(struct tevent_req *req)
+               sidstr = strchr(alt_name, '\\');
+               if (sidstr == NULL) {
+-                      DEBUG(0, ("Got invalid trustdom response\n"));
++                      DEBUG(10, ("Got invalid trustdom response\n"));
+                       break;
+               }
+               *sidstr = '\0';
+               sidstr += 1;
+-              q = strchr(sidstr, '\n');
+-              if (q != NULL)
+-                      *q = '\0';
++              /* use the real alt_name if we have one, else pass in NULL */
++              if (!strequal(alt_name, "(null)")) {
++                      trust_params.dns_name = alt_name;
++              }
++
++              q = strtok(sidstr, "\\");
++              if (q == NULL) {
++                      DEBUG(10, ("Got invalid trustdom response\n"));
++                      break;
++              }
++
++              if (!string_to_sid(&trust_params.sid, sidstr)) {
++                      DEBUG(0, ("Got invalid trustdom response\n"));
++                      break;
++              }
+-              if (!string_to_sid(&sid, sidstr)) {
++              q = strtok(NULL, "\\");
++              if (q == NULL) {
+                       DEBUG(0, ("Got invalid trustdom response\n"));
+                       break;
+               }
+-              /* use the real alt_name if we have one, else pass in NULL */
++              trust_params.trust_flags = (uint32_t)strtoul(q, NULL, 10);
+-              if ( !strequal( alt_name, "(null)" ) )
+-                      alternate_name = alt_name;
++              q = strtok(NULL, "\\");
++              if (q == NULL) {
++                      DEBUG(0, ("Got invalid trustdom response\n"));
++                      break;
++              }
++
++              trust_params.trust_type = (uint32_t)strtoul(q, NULL, 10);
+-              /* If we have an existing domain structure, calling
+-                 add_trusted_domain() will update the SID if
+-                 necessary.  This is important because we need the
+-                 SID for sibling domains */
++              q = strtok(NULL, "\n");
++              if (q == NULL) {
++                      DEBUG(10, ("Got invalid trustdom response\n"));
++                      break;
++              }
+-              (void)add_trusted_domain(p, alternate_name,
+-                                          &cache_methods,
+-                                          &sid);
++              trust_params.trust_attribs = (uint32_t)strtoul(q, NULL, 10);
++
++              /*
++               * We always call add_trusted_domain() cause on an existing
++               * domain structure, it will update the SID if necessary.
++               * This is important because we need the SID for sibling
++               * domains.
++               */
++              (void)add_trusted_domain_from_tdc(&trust_params,
++                                                &cache_methods);
+-              p=q;
+-              if (p != NULL)
+-                      p += 1;
++              p = q + strlen(q) + 1;
+       }
+       /*
+-- 
+2.9.4
+