From d895399850ed6507fb550e80084732d1d7a8fde8 Mon Sep 17 00:00:00 2001 From: Arne Fitzenreiter Date: Mon, 27 Nov 2017 18:20:59 +0100 Subject: [PATCH] samba: import security updates from redhead Signed-off-by: Arne Fitzenreiter --- lfs/samba | 9 +- src/patches/samba/CVE-2017-12150-v3-6.patch | 102 ++ src/patches/samba/CVE-2017-12163.patch | 141 ++ src/patches/samba/CVE-2017-15275.patch | 45 + src/patches/samba/CVE-2017-2619.patch | 1328 +++++++++++++++++ ...-winbind_fix_trusted_domain_handling.patch | 432 ++++++ 6 files changed, 2054 insertions(+), 3 deletions(-) create mode 100644 src/patches/samba/CVE-2017-12150-v3-6.patch create mode 100644 src/patches/samba/CVE-2017-12163.patch create mode 100644 src/patches/samba/CVE-2017-15275.patch create mode 100644 src/patches/samba/CVE-2017-2619.patch create mode 100644 src/patches/samba/samba-3.6.99-winbind_fix_trusted_domain_handling.patch diff --git a/lfs/samba b/lfs/samba index d54d507af7..6842e1840b 100644 --- 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 index 0000000000..b221a840ce --- /dev/null +++ b/src/patches/samba/CVE-2017-12150-v3-6.patch @@ -0,0 +1,102 @@ +From d3198caa7a8910a9ce1eb4104d5b410ef29ac2bb Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +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 +Backported-by: Andreas Schneider +--- + 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 +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 +Backported-by: Andreas Schneider +--- + 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 +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 +Backported-by: Andreas Schneider +--- + 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 index 0000000000..93fe2cec24 --- /dev/null +++ b/src/patches/samba/CVE-2017-12163.patch @@ -0,0 +1,141 @@ +From 9f1a51917649795123bedbefdea678317d392b48 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +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 +Signed-off-by: Stefan Metzmacher +--- + 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 index 0000000000..758672e02f --- /dev/null +++ b/src/patches/samba/CVE-2017-15275.patch @@ -0,0 +1,45 @@ +From c1a22e59f87783d88dfbaeeb132b89be166b2754 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +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 +--- + 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 index 0000000000..149e085fe1 --- /dev/null +++ b/src/patches/samba/CVE-2017-2619.patch @@ -0,0 +1,1328 @@ +From a398754c9bb1639f762979765de6c540c714b5cb Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +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 +Signed-off-by: Jeremy Allison +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 index 0000000000..e58f7146a3 --- /dev/null +++ b/src/patches/samba/samba-3.6.99-winbind_fix_trusted_domain_handling.patch @@ -0,0 +1,432 @@ +From a280f61d71d5ea7e2212d253b84ac5b25810b88e Mon Sep 17 00:00:00 2001 +From: Uri Simchoni +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 +Reviewed-by: Ralph Boehme +--- + 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 +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 +Reviewed-by: Guenther Deschner +--- + 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 +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 +Reviewed-by: Ralph Boehme +--- + 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 +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 +Reviewed-by: Ralph Boehme + +Autobuild-User(master): Ralph Böhme +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; imem_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 + -- 2.39.2