From 85b413e4a9474ea976821fa31a4b2855ef2a5d07 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Mon, 31 Jan 2022 10:42:28 -0500 Subject: [PATCH] import samba-4.14.5-9.el8_5 --- SOURCES/CVE-2021-44142-v4.14.patch | 759 ++++++++++++ ...-4.14-del-dir-with-dangling-symlinks.patch | 1023 +++++++++++++++++ .../samba-4.14-fix-domain-join-segfault.patch | 39 + .../samba-4.14-fix-username-map-script.patch | 227 ++++ ...-4.14-recursive-delete-of-veto-files.patch | 295 +++++ SPECS/samba.spec | 15 +- 6 files changed, 2357 insertions(+), 1 deletion(-) create mode 100644 SOURCES/CVE-2021-44142-v4.14.patch create mode 100644 SOURCES/samba-4.14-del-dir-with-dangling-symlinks.patch create mode 100644 SOURCES/samba-4.14-fix-domain-join-segfault.patch create mode 100644 SOURCES/samba-4.14-fix-username-map-script.patch create mode 100644 SOURCES/samba-4.14-recursive-delete-of-veto-files.patch diff --git a/SOURCES/CVE-2021-44142-v4.14.patch b/SOURCES/CVE-2021-44142-v4.14.patch new file mode 100644 index 0000000..1f76f7c --- /dev/null +++ b/SOURCES/CVE-2021-44142-v4.14.patch @@ -0,0 +1,759 @@ +From 2f7332f6c283fbedbd859c79a3f74ca6e07aad46 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 13 Jan 2022 16:48:01 +0100 +Subject: [PATCH 1/5] CVE-2021-44142: libadouble: add defines for icon lengths + +From https://www.ietf.org/rfc/rfc1740.txt + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914 + +Signed-off-by: Ralph Boehme +--- + source3/lib/adouble.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/source3/lib/adouble.h b/source3/lib/adouble.h +index 90a825c502e0..e3b9263a1f9a 100644 +--- a/source3/lib/adouble.h ++++ b/source3/lib/adouble.h +@@ -101,6 +101,8 @@ typedef enum {ADOUBLE_META, ADOUBLE_RSRC} adouble_type_t; + #define ADEDLEN_MACFILEI 4 + #define ADEDLEN_PRODOSFILEI 8 + #define ADEDLEN_MSDOSFILEI 2 ++#define ADEDLEN_ICONBW 128 ++#define ADEDLEN_ICONCOL 1024 + #define ADEDLEN_DID 4 + #define ADEDLEN_PRIVDEV 8 + #define ADEDLEN_PRIVINO 8 +-- +2.34.1 + + +From fc20cb8268af1203a331ba142b630d4dfb613478 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Sat, 20 Nov 2021 16:36:42 +0100 +Subject: [PATCH 2/5] CVE-2021-44142: smbd: add Netatalk xattr used by + vfs_fruit to the list of private Samba xattrs + +This is an internal xattr that should not be user visible. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914 + +Signed-off-by: Ralph Boehme +[slow@samba.org: conflict due to changed includes in source3/smbd/trans2.c] +--- + source3/smbd/trans2.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c +index 70a492a96a8a..a200656b76cf 100644 +--- a/source3/smbd/trans2.c ++++ b/source3/smbd/trans2.c +@@ -45,6 +45,7 @@ + #include "smb1_utils.h" + #include "libcli/smb/smb2_posix.h" + #include "lib/util/string_wrappers.h" ++#include "source3/lib/adouble.h" + + #define DIR_ENTRY_SAFETY_MARGIN 4096 + +@@ -218,6 +219,7 @@ bool samba_private_attr_name(const char *unix_ea_name) + SAMBA_XATTR_DOS_ATTRIB, + SAMBA_XATTR_MARKER, + XATTR_NTACL_NAME, ++ AFPINFO_EA_NETATALK, + NULL + }; + +-- +2.34.1 + + +From 73302708170a71afce09ff42640ea4fceff4d08a Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 26 Nov 2021 07:19:32 +0100 +Subject: [PATCH 3/5] CVE-2021-44142: libadouble: harden ad_unpack_xattrs() + +This ensures ad_unpack_xattrs() is only called for an ad_type of ADOUBLE_RSRC, +which is used for parsing ._ AppleDouble sidecar files, and the buffer +ad->ad_data is AD_XATTR_MAX_HDR_SIZE bytes large which is a prerequisite for all +buffer out-of-bounds access checks in ad_unpack_xattrs(). + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914 + +Signed-off-by: Ralph Boehme +--- + source3/lib/adouble.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +diff --git a/source3/lib/adouble.c b/source3/lib/adouble.c +index 0ab9019cfb59..7875dd6f0df8 100644 +--- a/source3/lib/adouble.c ++++ b/source3/lib/adouble.c +@@ -707,14 +707,27 @@ static bool ad_pack(struct vfs_handle_struct *handle, + static bool ad_unpack_xattrs(struct adouble *ad) + { + struct ad_xattr_header *h = &ad->adx_header; ++ size_t bufsize = talloc_get_size(ad->ad_data); + const char *p = ad->ad_data; + uint32_t hoff; + uint32_t i; + ++ if (ad->ad_type != ADOUBLE_RSRC) { ++ return false; ++ } ++ + if (ad_getentrylen(ad, ADEID_FINDERI) <= ADEDLEN_FINDERI) { + return true; + } + ++ /* ++ * Ensure the buffer ad->ad_data was allocated by ad_alloc() for an ++ * ADOUBLE_RSRC type (._ AppleDouble file on-disk). ++ */ ++ if (bufsize != AD_XATTR_MAX_HDR_SIZE) { ++ return false; ++ } ++ + /* 2 bytes padding */ + hoff = ad_getentryoff(ad, ADEID_FINDERI) + ADEDLEN_FINDERI + 2; + +@@ -964,9 +977,11 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries, + ad->ad_eid[eid].ade_len = len; + } + +- ok = ad_unpack_xattrs(ad); +- if (!ok) { +- return false; ++ if (ad->ad_type == ADOUBLE_RSRC) { ++ ok = ad_unpack_xattrs(ad); ++ if (!ok) { ++ return false; ++ } + } + + return true; +-- +2.34.1 + + +From 0cfe02ac7ad197ea9fb4b19f296b73e5e7baf0af Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 25 Nov 2021 15:04:03 +0100 +Subject: [PATCH 4/5] CVE-2021-44142: libadouble: add basic cmocka tests + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914 + +Signed-off-by: Ralph Boehme +[slow@samba.org: conflict due to missing test in selftest/tests.py] +--- + selftest/knownfail.d/samba.unittests.adouble | 3 + + selftest/tests.py | 2 + + source3/lib/test_adouble.c | 389 +++++++++++++++++++ + source3/wscript_build | 5 + + 4 files changed, 399 insertions(+) + create mode 100644 selftest/knownfail.d/samba.unittests.adouble + create mode 100644 source3/lib/test_adouble.c + +diff --git a/selftest/knownfail.d/samba.unittests.adouble b/selftest/knownfail.d/samba.unittests.adouble +new file mode 100644 +index 000000000000..8b0314f2faec +--- /dev/null ++++ b/selftest/knownfail.d/samba.unittests.adouble +@@ -0,0 +1,3 @@ ++^samba.unittests.adouble.parse_abouble_finderinfo2\(none\) ++^samba.unittests.adouble.parse_abouble_finderinfo3\(none\) ++^samba.unittests.adouble.parse_abouble_date2\(none\) +diff --git a/selftest/tests.py b/selftest/tests.py +index af1e46061852..f4a1056f1dc8 100644 +--- a/selftest/tests.py ++++ b/selftest/tests.py +@@ -427,3 +427,5 @@ plantestsuite("samba.unittests.test_oLschema2ldif", "none", + [os.path.join(bindir(), "default/source3/test_mdsparser_es")] + [configuration]) + plantestsuite("samba.unittests.credentials", "none", + [os.path.join(bindir(), "default/auth/credentials/test_creds")]) ++plantestsuite("samba.unittests.adouble", "none", ++ [os.path.join(bindir(), "test_adouble")]) +diff --git a/source3/lib/test_adouble.c b/source3/lib/test_adouble.c +new file mode 100644 +index 000000000000..615c22469c91 +--- /dev/null ++++ b/source3/lib/test_adouble.c +@@ -0,0 +1,389 @@ ++/* ++ * Unix SMB/CIFS implementation. ++ * ++ * Copyright (C) 2021 Ralph Boehme ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 3 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++#include "adouble.c" ++#include ++ ++static int setup_talloc_context(void **state) ++{ ++ TALLOC_CTX *frame = talloc_stackframe(); ++ ++ *state = frame; ++ return 0; ++} ++ ++static int teardown_talloc_context(void **state) ++{ ++ TALLOC_CTX *frame = *state; ++ ++ TALLOC_FREE(frame); ++ return 0; ++} ++ ++/* ++ * Basic and sane buffer. ++ */ ++static uint8_t ad_basic[] = { ++ 0x00, 0x05, 0x16, 0x07, /* Magic */ ++ 0x00, 0x02, 0x00, 0x00, /* Version */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x02, /* Count */ ++ /* adentry 1: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x09, /* eid: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x32, /* offset */ ++ 0x00, 0x00, 0x00, 0x20, /* length */ ++ /* adentry 2: Resourcefork */ ++ 0x00, 0x00, 0x00, 0x02, /* eid: Resourcefork */ ++ 0x00, 0x00, 0x00, 0x52, /* offset */ ++ 0xff, 0xff, 0xff, 0x00, /* length */ ++ /* FinderInfo data: 32 bytes */ ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++}; ++ ++/* ++ * An empty FinderInfo entry. ++ */ ++static uint8_t ad_finderinfo1[] = { ++ 0x00, 0x05, 0x16, 0x07, /* Magic */ ++ 0x00, 0x02, 0x00, 0x00, /* Version */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x02, /* Count */ ++ /* adentry 1: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x09, /* eid: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x52, /* off: points at end of buffer */ ++ 0x00, 0x00, 0x00, 0x00, /* len: 0, so off+len don't exceed bufferlen */ ++ /* adentry 2: Resourcefork */ ++ 0x00, 0x00, 0x00, 0x02, /* eid: Resourcefork */ ++ 0x00, 0x00, 0x00, 0x52, /* offset */ ++ 0xff, 0xff, 0xff, 0x00, /* length */ ++ /* FinderInfo data: 32 bytes */ ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++}; ++ ++/* ++ * A dangerous FinderInfo with correct length exceeding buffer by one byte. ++ */ ++static uint8_t ad_finderinfo2[] = { ++ 0x00, 0x05, 0x16, 0x07, /* Magic */ ++ 0x00, 0x02, 0x00, 0x00, /* Version */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x02, /* Count */ ++ /* adentry 1: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x09, /* eid: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x33, /* off: points at beginng of data + 1 */ ++ 0x00, 0x00, 0x00, 0x20, /* len: 32, so off+len exceeds bufferlen by 1 */ ++ /* adentry 2: Resourcefork */ ++ 0x00, 0x00, 0x00, 0x02, /* eid: Resourcefork */ ++ 0x00, 0x00, 0x00, 0x52, /* offset */ ++ 0xff, 0xff, 0xff, 0x00, /* length */ ++ /* FinderInfo data: 32 bytes */ ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++}; ++ ++static uint8_t ad_finderinfo3[] = { ++ 0x00, 0x05, 0x16, 0x07, /* Magic */ ++ 0x00, 0x02, 0x00, 0x00, /* Version */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x02, /* Count */ ++ /* adentry 1: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x09, /* eid: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x33, /* off: points at beginng of data + 1 */ ++ 0x00, 0x00, 0x00, 0x1f, /* len: 31, so off+len don't exceed buf */ ++ /* adentry 2: Resourcefork */ ++ 0x00, 0x00, 0x00, 0x02, /* eid: Resourcefork */ ++ 0x00, 0x00, 0x00, 0x52, /* offset */ ++ 0xff, 0xff, 0xff, 0x00, /* length */ ++ /* FinderInfo data: 32 bytes */ ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++}; ++ ++/* ++ * A dangerous name entry. ++ */ ++static uint8_t ad_name[] = { ++ 0x00, 0x05, 0x16, 0x07, /* Magic */ ++ 0x00, 0x02, 0x00, 0x00, /* Version */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x02, /* Count */ ++ /* adentry 1: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x09, /* eid: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x32, /* offset */ ++ 0x00, 0x00, 0x00, 0x20, /* length */ ++ /* adentry 2: Name */ ++ 0x00, 0x00, 0x00, 0x03, /* eid: Name */ ++ 0x00, 0x00, 0x00, 0x52, /* off: points at end of buffer */ ++ 0x00, 0x00, 0x00, 0x01, /* len: 1, so off+len exceeds bufferlen */ ++ /* FinderInfo data: 32 bytes */ ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++}; ++ ++/* ++ * A empty ADEID_FILEDATESI entry. ++ */ ++static uint8_t ad_date1[] = { ++ 0x00, 0x05, 0x16, 0x07, /* Magic */ ++ 0x00, 0x02, 0x00, 0x00, /* Version */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x02, /* Count */ ++ /* adentry 1: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x09, /* eid: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x32, /* offset */ ++ 0x00, 0x00, 0x00, 0x20, /* length */ ++ /* adentry 2: Dates */ ++ 0x00, 0x00, 0x00, 0x08, /* eid: dates */ ++ 0x00, 0x00, 0x00, 0x52, /* off: end of buffer */ ++ 0x00, 0x00, 0x00, 0x00, /* len: 0, empty entry, valid */ ++ /* FinderInfo data: 32 bytes */ ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++}; ++ ++/* ++ * A dangerous ADEID_FILEDATESI entry, invalid length. ++ */ ++static uint8_t ad_date2[] = { ++ 0x00, 0x05, 0x16, 0x07, /* Magic */ ++ 0x00, 0x02, 0x00, 0x00, /* Version */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x00, 0x00, 0x00, /* Filler */ ++ 0x00, 0x02, /* Count */ ++ /* adentry 1: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x09, /* eid: FinderInfo */ ++ 0x00, 0x00, 0x00, 0x32, /* offset */ ++ 0x00, 0x00, 0x00, 0x20, /* length */ ++ /* adentry 2: Dates */ ++ 0x00, 0x00, 0x00, 0x08, /* eid: dates */ ++ 0x00, 0x00, 0x00, 0x43, /* off: FinderInfo buf but one byte short */ ++ 0x00, 0x00, 0x00, 0x0f, /* len: 15, so off+len don't exceed bufferlen */ ++ /* FinderInfo data: 32 bytes */ ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, ++}; ++ ++static struct adouble *parse_adouble(TALLOC_CTX *mem_ctx, ++ uint8_t *adbuf, ++ size_t adsize, ++ off_t filesize) ++{ ++ struct adouble *ad = NULL; ++ bool ok; ++ ++ ad = talloc_zero(mem_ctx, struct adouble); ++ ad->ad_data = talloc_zero_size(ad, adsize); ++ assert_non_null(ad); ++ ++ memcpy(ad->ad_data, adbuf, adsize); ++ ++ ok = ad_unpack(ad, 2, filesize); ++ if (!ok) { ++ return NULL; ++ } ++ ++ return ad; ++} ++ ++static void parse_abouble_basic(void **state) ++{ ++ TALLOC_CTX *frame = *state; ++ struct adouble *ad = NULL; ++ char *p = NULL; ++ ++ ad = parse_adouble(frame, ad_basic, sizeof(ad_basic), 0xffffff52); ++ assert_non_null(ad); ++ ++ p = ad_get_entry(ad, ADEID_FINDERI); ++ assert_non_null(p); ++ ++ return; ++} ++ ++static void parse_abouble_finderinfo1(void **state) ++{ ++ TALLOC_CTX *frame = *state; ++ struct adouble *ad = NULL; ++ char *p = NULL; ++ ++ ad = parse_adouble(frame, ++ ad_finderinfo1, ++ sizeof(ad_finderinfo1), ++ 0xffffff52); ++ assert_non_null(ad); ++ ++ p = ad_get_entry(ad, ADEID_FINDERI); ++ assert_null(p); ++ ++ return; ++} ++ ++static void parse_abouble_finderinfo2(void **state) ++{ ++ TALLOC_CTX *frame = *state; ++ struct adouble *ad = NULL; ++ ++ ad = parse_adouble(frame, ++ ad_finderinfo2, ++ sizeof(ad_finderinfo2), ++ 0xffffff52); ++ assert_null(ad); ++ ++ return; ++} ++ ++static void parse_abouble_finderinfo3(void **state) ++{ ++ TALLOC_CTX *frame = *state; ++ struct adouble *ad = NULL; ++ ++ ad = parse_adouble(frame, ++ ad_finderinfo3, ++ sizeof(ad_finderinfo3), ++ 0xffffff52); ++ assert_null(ad); ++ ++ return; ++} ++ ++static void parse_abouble_name(void **state) ++{ ++ TALLOC_CTX *frame = *state; ++ struct adouble *ad = NULL; ++ ++ ad = parse_adouble(frame, ad_name, sizeof(ad_name), 0x52); ++ assert_null(ad); ++ ++ return; ++} ++ ++static void parse_abouble_date1(void **state) ++{ ++ TALLOC_CTX *frame = *state; ++ struct adouble *ad = NULL; ++ char *p = NULL; ++ ++ ad = parse_adouble(frame, ad_date1, sizeof(ad_date1), 0x52); ++ assert_non_null(ad); ++ ++ p = ad_get_entry(ad, ADEID_FILEDATESI); ++ assert_null(p); ++ ++ return; ++} ++ ++static void parse_abouble_date2(void **state) ++{ ++ TALLOC_CTX *frame = *state; ++ struct adouble *ad = NULL; ++ ++ ad = parse_adouble(frame, ad_date2, sizeof(ad_date2), 0x52); ++ assert_null(ad); ++ ++ return; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int rc; ++ const struct CMUnitTest tests[] = { ++ cmocka_unit_test(parse_abouble_basic), ++ cmocka_unit_test(parse_abouble_finderinfo1), ++ cmocka_unit_test(parse_abouble_finderinfo2), ++ cmocka_unit_test(parse_abouble_finderinfo3), ++ cmocka_unit_test(parse_abouble_name), ++ cmocka_unit_test(parse_abouble_date1), ++ cmocka_unit_test(parse_abouble_date2), ++ }; ++ ++ if (argc == 2) { ++ cmocka_set_test_filter(argv[1]); ++ } ++ cmocka_set_message_output(CM_OUTPUT_SUBUNIT); ++ ++ rc = cmocka_run_group_tests(tests, ++ setup_talloc_context, ++ teardown_talloc_context); ++ ++ return rc; ++} +diff --git a/source3/wscript_build b/source3/wscript_build +index a143477a5064..95e589cfc734 100644 +--- a/source3/wscript_build ++++ b/source3/wscript_build +@@ -1088,6 +1088,11 @@ bld.SAMBA3_SUBSYSTEM('ADOUBLE', + source='lib/adouble.c', + deps='STRING_REPLACE') + ++bld.SAMBA3_BINARY('test_adouble', ++ source='lib/test_adouble.c', ++ deps='smbd_base STRING_REPLACE cmocka', ++ for_selftest=True) ++ + bld.SAMBA3_SUBSYSTEM('STRING_REPLACE', + source='lib/string_replace.c') + +-- +2.34.1 + + +From 793ca8c474a74f82745a266f4a4bf9e20443ad53 Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Thu, 13 Jan 2022 17:03:02 +0100 +Subject: [PATCH 5/5] CVE-2021-44142: libadouble: harden parsing code + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14914 + +Signed-off-by: Ralph Boehme +--- + selftest/knownfail.d/samba.unittests.adouble | 3 - + source3/lib/adouble.c | 115 ++++++++++++++++--- + 2 files changed, 101 insertions(+), 17 deletions(-) + delete mode 100644 selftest/knownfail.d/samba.unittests.adouble + +diff --git a/selftest/knownfail.d/samba.unittests.adouble b/selftest/knownfail.d/samba.unittests.adouble +deleted file mode 100644 +index 8b0314f2faec..000000000000 +--- a/selftest/knownfail.d/samba.unittests.adouble ++++ /dev/null +@@ -1,3 +0,0 @@ +-^samba.unittests.adouble.parse_abouble_finderinfo2\(none\) +-^samba.unittests.adouble.parse_abouble_finderinfo3\(none\) +-^samba.unittests.adouble.parse_abouble_date2\(none\) +diff --git a/source3/lib/adouble.c b/source3/lib/adouble.c +index 7875dd6f0df8..48cc0007c23c 100644 +--- a/source3/lib/adouble.c ++++ b/source3/lib/adouble.c +@@ -269,6 +269,95 @@ size_t ad_setentryoff(struct adouble *ad, int eid, size_t off) + return ad->ad_eid[eid].ade_off = off; + } + ++/* ++ * All entries besides FinderInfo and resource fork must fit into the ++ * buffer. FinderInfo is special as it may be larger then the default 32 bytes ++ * if it contains marshalled xattrs, which we will fixup that in ++ * ad_convert(). The first 32 bytes however must also be part of the buffer. ++ * ++ * The resource fork is never accessed directly by the ad_data buf. ++ */ ++static bool ad_entry_check_size(uint32_t eid, ++ size_t bufsize, ++ uint32_t off, ++ uint32_t got_len) ++{ ++ struct { ++ off_t expected_len; ++ bool fixed_size; ++ bool minimum_size; ++ } ad_checks[] = { ++ [ADEID_DFORK] = {-1, false, false}, /* not applicable */ ++ [ADEID_RFORK] = {-1, false, false}, /* no limit */ ++ [ADEID_NAME] = {ADEDLEN_NAME, false, false}, ++ [ADEID_COMMENT] = {ADEDLEN_COMMENT, false, false}, ++ [ADEID_ICONBW] = {ADEDLEN_ICONBW, true, false}, ++ [ADEID_ICONCOL] = {ADEDLEN_ICONCOL, false, false}, ++ [ADEID_FILEI] = {ADEDLEN_FILEI, true, false}, ++ [ADEID_FILEDATESI] = {ADEDLEN_FILEDATESI, true, false}, ++ [ADEID_FINDERI] = {ADEDLEN_FINDERI, false, true}, ++ [ADEID_MACFILEI] = {ADEDLEN_MACFILEI, true, false}, ++ [ADEID_PRODOSFILEI] = {ADEDLEN_PRODOSFILEI, true, false}, ++ [ADEID_MSDOSFILEI] = {ADEDLEN_MSDOSFILEI, true, false}, ++ [ADEID_SHORTNAME] = {ADEDLEN_SHORTNAME, false, false}, ++ [ADEID_AFPFILEI] = {ADEDLEN_AFPFILEI, true, false}, ++ [ADEID_DID] = {ADEDLEN_DID, true, false}, ++ [ADEID_PRIVDEV] = {ADEDLEN_PRIVDEV, true, false}, ++ [ADEID_PRIVINO] = {ADEDLEN_PRIVINO, true, false}, ++ [ADEID_PRIVSYN] = {ADEDLEN_PRIVSYN, true, false}, ++ [ADEID_PRIVID] = {ADEDLEN_PRIVID, true, false}, ++ }; ++ ++ if (eid >= ADEID_MAX) { ++ return false; ++ } ++ if (got_len == 0) { ++ /* Entry present, but empty, allow */ ++ return true; ++ } ++ if (ad_checks[eid].expected_len == 0) { ++ /* ++ * Shouldn't happen: implicitly initialized to zero because ++ * explicit initializer missing. ++ */ ++ return false; ++ } ++ if (ad_checks[eid].expected_len == -1) { ++ /* Unused or no limit */ ++ return true; ++ } ++ if (ad_checks[eid].fixed_size) { ++ if (ad_checks[eid].expected_len != got_len) { ++ /* Wrong size fo fixed size entry. */ ++ return false; ++ } ++ } else { ++ if (ad_checks[eid].minimum_size) { ++ if (got_len < ad_checks[eid].expected_len) { ++ /* ++ * Too small for variable sized entry with ++ * minimum size. ++ */ ++ return false; ++ } ++ } else { ++ if (got_len > ad_checks[eid].expected_len) { ++ /* Too big for variable sized entry. */ ++ return false; ++ } ++ } ++ } ++ if (off + got_len < off) { ++ /* wrap around */ ++ return false; ++ } ++ if (off + got_len > bufsize) { ++ /* overflow */ ++ return false; ++ } ++ return true; ++} ++ + /** + * Return a pointer to an AppleDouble entry + * +@@ -276,8 +365,15 @@ size_t ad_setentryoff(struct adouble *ad, int eid, size_t off) + **/ + char *ad_get_entry(const struct adouble *ad, int eid) + { ++ size_t bufsize = talloc_get_size(ad->ad_data); + off_t off = ad_getentryoff(ad, eid); + size_t len = ad_getentrylen(ad, eid); ++ bool valid; ++ ++ valid = ad_entry_check_size(eid, bufsize, off, len); ++ if (!valid) { ++ return NULL; ++ } + + if (off == 0 || len == 0) { + return NULL; +@@ -914,20 +1010,11 @@ static bool ad_unpack(struct adouble *ad, const size_t nentries, + return false; + } + +- /* +- * All entries besides FinderInfo and resource fork +- * must fit into the buffer. FinderInfo is special as +- * it may be larger then the default 32 bytes (if it +- * contains marshalled xattrs), but we will fixup that +- * in ad_convert(). And the resource fork is never +- * accessed directly by the ad_data buf (also see +- * comment above) anyway. +- */ +- if ((eid != ADEID_RFORK) && +- (eid != ADEID_FINDERI) && +- ((off + len) > bufsize)) { +- DEBUG(1, ("bogus eid %d: off: %" PRIu32 ", len: %" PRIu32 "\n", +- eid, off, len)); ++ ok = ad_entry_check_size(eid, bufsize, off, len); ++ if (!ok) { ++ DBG_ERR("bogus eid [%"PRIu32"] bufsize [%zu] " ++ "off [%"PRIu32"] len [%"PRIu32"]\n", ++ eid, bufsize, off, len); + return false; + } + +-- +2.34.1 + diff --git a/SOURCES/samba-4.14-del-dir-with-dangling-symlinks.patch b/SOURCES/samba-4.14-del-dir-with-dangling-symlinks.patch new file mode 100644 index 0000000..ca9dd8e --- /dev/null +++ b/SOURCES/samba-4.14-del-dir-with-dangling-symlinks.patch @@ -0,0 +1,1023 @@ +From a0618e0eda69d31d090f776a9217a6a3cf76e5da Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Thu, 21 Oct 2021 16:37:27 -0700 +Subject: [PATCH 1/7] s3: smbd: Add two tests showing the ability to delete a + directory containing a dangling symlink over SMB2 depends on "delete veto + files" setting. + +Add knownfail. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +(cherry picked from commit 942123b95923f35a32df4196a072a3ed3468396a) +(cherry picked from commit 359517877d6462ff4398401748f921c8b79357a6) +--- + selftest/knownfail.d/rmdir_dangle_symlink | 1 + + selftest/target/Samba3.pm | 4 + + .../test_delete_veto_files_only_rmdir.sh | 183 ++++++++++++++++++ + source3/selftest/tests.py | 3 + + 4 files changed, 191 insertions(+) + create mode 100644 selftest/knownfail.d/rmdir_dangle_symlink + create mode 100755 source3/script/tests/test_delete_veto_files_only_rmdir.sh + +diff --git a/selftest/knownfail.d/rmdir_dangle_symlink b/selftest/knownfail.d/rmdir_dangle_symlink +new file mode 100644 +index 00000000000..c775dc5fe15 +--- /dev/null ++++ b/selftest/knownfail.d/rmdir_dangle_symlink +@@ -0,0 +1 @@ ++^samba3.blackbox.test_dangle_rmdir.rmdir can delete directory containing dangling symlink\(fileserver\) +diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm +index bbff9d74817..588d7779dd4 100755 +--- a/selftest/target/Samba3.pm ++++ b/selftest/target/Samba3.pm +@@ -1584,6 +1584,10 @@ sub setup_fileserver + veto files = /veto_name*/ + delete veto files = yes + ++[delete_veto_files_only] ++ path = $veto_sharedir ++ delete veto files = yes ++ + [homes] + comment = Home directories + browseable = No +diff --git a/source3/script/tests/test_delete_veto_files_only_rmdir.sh b/source3/script/tests/test_delete_veto_files_only_rmdir.sh +new file mode 100755 +index 00000000000..d2c3b2198f7 +--- /dev/null ++++ b/source3/script/tests/test_delete_veto_files_only_rmdir.sh +@@ -0,0 +1,183 @@ ++#!/bin/sh ++# ++# Check smbclient can (or cannot) delete a directory containing dangling symlinks. ++# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 ++# ++ ++if [ $# -lt 6 ]; then ++cat < "$tmpfile" < "$tmpfile" < "$tmpfile" < "$tmpfile" < +Date: Mon, 25 Oct 2021 12:01:58 -0700 +Subject: [PATCH 2/7] s3: VFS: streams_depot. Allow unlinkat to cope with + dangling symlinks. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +(cherry picked from commit 295d7d026babe3cd5123d0f53adcb16868907f05) +(backported from commit 7a4173809a87350bc3580240232978042ec2ceca) +[pfilipen@redhat.com: code in 4.15 uses different variable name] +--- + source3/modules/vfs_streams_depot.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c +index a5e02d5a069..dd6376e5fd0 100644 +--- a/source3/modules/vfs_streams_depot.c ++++ b/source3/modules/vfs_streams_depot.c +@@ -739,6 +739,16 @@ static int streams_depot_unlink_internal(vfs_handle_struct *handle, + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base); + } else { + ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base); ++ if (ret == -1 && (errno == ENOENT || errno == ELOOP)) { ++ if (VALID_STAT(smb_fname->st) && ++ S_ISLNK(smb_fname->st.st_ex_mode)) { ++ /* ++ * Original name was a link - Could be ++ * trying to remove a dangling symlink. ++ */ ++ ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base); ++ } ++ } + } + + if (ret == -1) { +-- +2.33.1 + + +From 474a91d03527a15f7655be3866a9e5eaa405118f Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 25 Oct 2021 12:02:43 -0700 +Subject: [PATCH 3/7] s3: VFS: xattr_tdb. Allow unlinkat to cope with dangling + symlinks. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +(cherry picked from commit f254be19d6501a4f573843af97963e350a9ee2ed) +(backported from commit 0dba0917fd97e975d1daab5b0828644d026c2bc5) +[pfilipen@redhat.com: code in 4.15 uses different variable name] +--- + source3/modules/vfs_xattr_tdb.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c +index d89a1dd0d7d..e06ff9639f1 100644 +--- a/source3/modules/vfs_xattr_tdb.c ++++ b/source3/modules/vfs_xattr_tdb.c +@@ -639,6 +639,16 @@ static int xattr_tdb_unlinkat(vfs_handle_struct *handle, + ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp); + } else { + ret = SMB_VFS_NEXT_STAT(handle, smb_fname_tmp); ++ if (ret == -1 && (errno == ENOENT || errno == ELOOP)) { ++ if (VALID_STAT(smb_fname->st) && ++ S_ISLNK(smb_fname->st.st_ex_mode)) { ++ /* ++ * Original name was a link - Could be ++ * trying to remove a dangling symlink. ++ */ ++ ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp); ++ } ++ } + } + if (ret == -1) { + goto out; +-- +2.33.1 + + +From 298a8dac1160ebba56cd84b7e25908e160b88f85 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 25 Oct 2021 12:21:37 -0700 +Subject: [PATCH 4/7] s3: smbd: Fix rmdir_internals() to do an early return if + lp_delete_veto_files() is not set. + +Fix the comments to match what the code actually does. The +exit at the end of the scan directory loop if we find a client +visible filename is a change in behavior, but the previous +behavior (not exist on visible filename, but delete it) was +a bug and in non-tested code. Now it's testd. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +(cherry picked from commit a37d16e7c55f85e3f2c9c8614755ea6307092d5f) +(backported from commit e00fe095e8cf7ab54bc82870b913762d2fdddbad) +[pfilipen@redhat.com: rmdir_internals() got refactored in 4.15] +--- + source3/smbd/close.c | 247 ++++++++++++++++++++++--------------------- + 1 file changed, 128 insertions(+), 119 deletions(-) + +diff --git a/source3/smbd/close.c b/source3/smbd/close.c +index f05619d1886..0c102b9533b 100644 +--- a/source3/smbd/close.c ++++ b/source3/smbd/close.c +@@ -938,8 +938,11 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) + { + connection_struct *conn = fsp->conn; + struct smb_filename *smb_dname = fsp->fsp_name; +- const struct loadparm_substitution *lp_sub = +- loadparm_s3_global_substitution(); ++ SMB_STRUCT_STAT st; ++ const char *dname = NULL; ++ char *talloced = NULL; ++ long dirpos = 0; ++ struct smb_Dir *dir_hnd = NULL; + int ret; + + SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname)); +@@ -974,143 +977,149 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) + return NT_STATUS_OK; + } + +- if(((errno == ENOTEMPTY)||(errno == EEXIST)) && *lp_veto_files(talloc_tos(), lp_sub, SNUM(conn))) { +- /* +- * Check to see if the only thing in this directory are +- * vetoed files/directories. If so then delete them and +- * retry. If we fail to delete any of them (and we *don't* +- * do a recursive delete) then fail the rmdir. +- */ +- SMB_STRUCT_STAT st; +- const char *dname = NULL; +- char *talloced = NULL; +- long dirpos = 0; +- struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, +- smb_dname, NULL, +- 0); +- +- if(dir_hnd == NULL) { ++ if (!((errno == ENOTEMPTY) || (errno == EEXIST))) { ++ DEBUG(3,("rmdir_internals: couldn't remove directory %s : " ++ "%s\n", smb_fname_str_dbg(smb_dname), ++ strerror(errno))); ++ return map_nt_error_from_unix(errno); ++ } ++ ++ /* ++ * Here we know the initial directory unlink failed with ++ * ENOTEMPTY or EEXIST so we know there are objects within. ++ * If we don't have permission to delete files non ++ * visible to the client just fail the directory delete. ++ */ ++ ++ if (!lp_delete_veto_files(SNUM(conn))) { ++ errno = ENOTEMPTY; ++ goto err; ++ } ++ ++ /* ++ * Check to see if the only thing in this directory are ++ * files non-visible to the client. If not, fail the delete. ++ */ ++ ++ dir_hnd = OpenDir(talloc_tos(), conn, smb_dname, NULL, 0); ++ if (dir_hnd == NULL) { ++ errno = ENOTEMPTY; ++ goto err; ++ } ++ ++ while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) { ++ if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) { ++ TALLOC_FREE(talloced); ++ continue; ++ } ++ if (!is_visible_file(conn, ++ dir_hnd, ++ dname, ++ &st, ++ false)) { ++ TALLOC_FREE(talloced); ++ continue; ++ } ++ if(!IS_VETO_PATH(conn, dname)) { ++ /* ++ * We found a client visible name. ++ * We cannot delete this directory. ++ */ ++ DBG_DEBUG("got name %s - " ++ "can't delete directory %s\n", ++ dname, ++ fsp_str_dbg(fsp)); ++ TALLOC_FREE(dir_hnd); ++ TALLOC_FREE(talloced); + errno = ENOTEMPTY; + goto err; + } ++ TALLOC_FREE(talloced); ++ } + +- while ((dname = ReadDirName(dir_hnd, &dirpos, &st, +- &talloced)) != NULL) { +- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) { +- TALLOC_FREE(talloced); +- continue; +- } +- if (!is_visible_file(conn, +- dir_hnd, +- dname, +- &st, +- false)) { +- TALLOC_FREE(talloced); +- continue; +- } +- if(!IS_VETO_PATH(conn, dname)) { +- TALLOC_FREE(dir_hnd); +- TALLOC_FREE(talloced); +- errno = ENOTEMPTY; +- goto err; +- } ++ /* Do a recursive delete. */ ++ RewindDir(dir_hnd,&dirpos); ++ while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) { ++ struct smb_filename *smb_dname_full = NULL; ++ char *fullname = NULL; ++ bool do_break = true; ++ ++ if (ISDOT(dname) || ISDOTDOT(dname)) { ++ TALLOC_FREE(talloced); ++ continue; ++ } ++ if (!is_visible_file(conn, ++ dir_hnd, ++ dname, ++ &st, ++ false)) { + TALLOC_FREE(talloced); ++ continue; + } + +- /* We only have veto files/directories. +- * Are we allowed to delete them ? */ ++ fullname = talloc_asprintf(ctx, ++ "%s/%s", ++ smb_dname->base_name, ++ dname); + +- if(!lp_delete_veto_files(SNUM(conn))) { +- TALLOC_FREE(dir_hnd); +- errno = ENOTEMPTY; +- goto err; ++ if (fullname == NULL) { ++ errno = ENOMEM; ++ goto err_break; + } + +- /* Do a recursive delete. */ +- RewindDir(dir_hnd,&dirpos); +- while ((dname = ReadDirName(dir_hnd, &dirpos, &st, +- &talloced)) != NULL) { +- struct smb_filename *smb_dname_full = NULL; +- char *fullname = NULL; +- bool do_break = true; +- +- if (ISDOT(dname) || ISDOTDOT(dname)) { +- TALLOC_FREE(talloced); +- continue; +- } +- if (!is_visible_file(conn, +- dir_hnd, +- dname, +- &st, +- false)) { +- TALLOC_FREE(talloced); +- continue; +- } +- +- fullname = talloc_asprintf(ctx, +- "%s/%s", +- smb_dname->base_name, +- dname); ++ smb_dname_full = synthetic_smb_fname(talloc_tos(), ++ fullname, ++ NULL, ++ NULL, ++ smb_dname->twrp, ++ smb_dname->flags); ++ if (smb_dname_full == NULL) { ++ errno = ENOMEM; ++ goto err_break; ++ } + +- if(!fullname) { +- errno = ENOMEM; ++ if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) { ++ goto err_break; ++ } ++ if(smb_dname_full->st.st_ex_mode & S_IFDIR) { ++ int retval; ++ if(!recursive_rmdir(ctx, conn, ++ smb_dname_full)) { + goto err_break; + } +- +- smb_dname_full = synthetic_smb_fname(talloc_tos(), +- fullname, +- NULL, +- NULL, +- smb_dname->twrp, +- smb_dname->flags); +- if (smb_dname_full == NULL) { +- errno = ENOMEM; ++ retval = SMB_VFS_UNLINKAT(conn, ++ conn->cwd_fsp, ++ smb_dname_full, ++ AT_REMOVEDIR); ++ if(retval != 0) { + goto err_break; + } +- +- if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) { ++ } else { ++ int retval = SMB_VFS_UNLINKAT(conn, ++ conn->cwd_fsp, ++ smb_dname_full, ++ 0); ++ if(retval != 0) { + goto err_break; + } +- if(smb_dname_full->st.st_ex_mode & S_IFDIR) { +- int retval; +- if(!recursive_rmdir(ctx, conn, +- smb_dname_full)) { +- goto err_break; +- } +- retval = SMB_VFS_UNLINKAT(conn, +- conn->cwd_fsp, +- smb_dname_full, +- AT_REMOVEDIR); +- if(retval != 0) { +- goto err_break; +- } +- } else { +- int retval = SMB_VFS_UNLINKAT(conn, +- conn->cwd_fsp, +- smb_dname_full, +- 0); +- if(retval != 0) { +- goto err_break; +- } +- } ++ } + +- /* Successful iteration. */ +- do_break = false; ++ /* Successful iteration. */ ++ do_break = false; + +- err_break: +- TALLOC_FREE(fullname); +- TALLOC_FREE(smb_dname_full); +- TALLOC_FREE(talloced); +- if (do_break) +- break; +- } +- TALLOC_FREE(dir_hnd); +- /* Retry the rmdir */ +- ret = SMB_VFS_UNLINKAT(conn, +- conn->cwd_fsp, +- smb_dname, +- AT_REMOVEDIR); ++ err_break: ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ TALLOC_FREE(talloced); ++ if (do_break) ++ break; + } ++ TALLOC_FREE(dir_hnd); ++ /* Retry the rmdir */ ++ ret = SMB_VFS_UNLINKAT(conn, ++ conn->cwd_fsp, ++ smb_dname, ++ AT_REMOVEDIR); + + err: + +-- +2.33.1 + + +From a7075aeedd078c68b57556678fa40907cd66cd08 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 25 Oct 2021 12:32:29 -0700 +Subject: [PATCH 5/7] s3: smbd: Fix logic in rmdir_internals() to cope with + dangling symlinks. + +Still need to add the same logic in can_delete_directory_fsp() +before we can delete the knownfail. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +(cherry picked from commit 26fecad2e66e91a3913d88ee2e0889f266e91d89) +(backported from commit 4793c4d5307472f0eb72f70f7dbf7324744e3f91) +[pfilipen@redhat.com: rmdir_internals() got refactored in 4.15] +--- + source3/smbd/close.c | 103 ++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 101 insertions(+), 2 deletions(-) + +diff --git a/source3/smbd/close.c b/source3/smbd/close.c +index 0c102b9533b..81811f703b0 100644 +--- a/source3/smbd/close.c ++++ b/source3/smbd/close.c +@@ -1008,10 +1008,14 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) + } + + while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced)) != NULL) { ++ struct smb_filename *smb_dname_full = NULL; ++ char *fullname = NULL; ++ + if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) { + TALLOC_FREE(talloced); + continue; + } ++ + if (!is_visible_file(conn, + dir_hnd, + dname, +@@ -1020,6 +1024,98 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) + TALLOC_FREE(talloced); + continue; + } ++ ++ fullname = talloc_asprintf(talloc_tos(), ++ "%s/%s", ++ smb_dname->base_name, ++ dname); ++ ++ if (fullname == NULL) { ++ TALLOC_FREE(talloced); ++ errno = ENOMEM; ++ goto err; ++ } ++ ++ smb_dname_full = synthetic_smb_fname(talloc_tos(), ++ fullname, ++ NULL, ++ NULL, ++ smb_dname->twrp, ++ smb_dname->flags); ++ if (smb_dname_full == NULL) { ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ errno = ENOMEM; ++ goto err; ++ } ++ ++ ret = SMB_VFS_LSTAT(conn, smb_dname_full); ++ if (ret != 0) { ++ int saved_errno = errno; ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ errno = saved_errno; ++ goto err; ++ } ++ ++ if (S_ISLNK(smb_dname_full->st.st_ex_mode)) { ++ /* Could it be an msdfs link ? */ ++ if (lp_host_msdfs() && ++ lp_msdfs_root(SNUM(conn))) { ++ struct smb_filename *smb_atname; ++ smb_atname = synthetic_smb_fname(talloc_tos(), ++ dname, ++ NULL, ++ &smb_dname_full->st, ++ fsp->fsp_name->twrp, ++ fsp->fsp_name->flags); ++ if (smb_atname == NULL) { ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ errno = ENOMEM; ++ goto err; ++ } ++ if (is_msdfs_link(conn, smb_atname)) { ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ TALLOC_FREE(smb_atname); ++ DBG_DEBUG("got msdfs link name %s " ++ "- can't delete directory %s\n", ++ dname, ++ fsp_str_dbg(fsp)); ++ errno = ENOTEMPTY; ++ goto err; ++ } ++ TALLOC_FREE(smb_atname); ++ } ++ ++ /* Not a DFS link - could it be a dangling symlink ? */ ++ ret = SMB_VFS_STAT(conn, smb_dname_full); ++ if (ret == -1 && (errno == ENOENT || errno == ELOOP)) { ++ /* ++ * Dangling symlink. ++ * Allow delete as "delete veto files = yes" ++ */ ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ continue; ++ } ++ ++ DBG_DEBUG("got symlink name %s - " ++ "can't delete directory %s\n", ++ dname, ++ fsp_str_dbg(fsp)); ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ errno = ENOTEMPTY; ++ goto err; ++ } ++ + if(!IS_VETO_PATH(conn, dname)) { + /* + * We found a client visible name. +@@ -1029,12 +1125,15 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) + "can't delete directory %s\n", + dname, + fsp_str_dbg(fsp)); +- TALLOC_FREE(dir_hnd); + TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); + errno = ENOTEMPTY; + goto err; + } + TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); + } + + /* Do a recursive delete. */ +@@ -1114,7 +1213,6 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) + if (do_break) + break; + } +- TALLOC_FREE(dir_hnd); + /* Retry the rmdir */ + ret = SMB_VFS_UNLINKAT(conn, + conn->cwd_fsp, +@@ -1123,6 +1221,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp) + + err: + ++ TALLOC_FREE(dir_hnd); + if (ret != 0) { + DEBUG(3,("rmdir_internals: couldn't remove directory %s : " + "%s\n", smb_fname_str_dbg(smb_dname), +-- +2.33.1 + + +From 843fc3b857cdfd6c7e902acef933d17690815e7e Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 25 Oct 2021 12:36:57 -0700 +Subject: [PATCH 6/7] s3: smbd: Fix logic in can_delete_directory_fsp() to cope + with dangling symlinks. + +Remove knownfail. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +(cherry picked from commit e9ef970eee5eca8ab3720279c54098e91d2dfda9) +(backported from commit 5023dbc04bfad7cc39e8c4de96f40c82e7a0288e) +[pfilipen@redhat.com: can_delete_directory_fsp() got refactored in 4.15] +--- + selftest/knownfail.d/rmdir_dangle_symlink | 1 - + source3/smbd/dir.c | 97 +++++++++++++++++++++++ + 2 files changed, 97 insertions(+), 1 deletion(-) + delete mode 100644 selftest/knownfail.d/rmdir_dangle_symlink + +diff --git a/selftest/knownfail.d/rmdir_dangle_symlink b/selftest/knownfail.d/rmdir_dangle_symlink +deleted file mode 100644 +index c775dc5fe15..00000000000 +--- a/selftest/knownfail.d/rmdir_dangle_symlink ++++ /dev/null +@@ -1 +0,0 @@ +-^samba3.blackbox.test_dangle_rmdir.rmdir can delete directory containing dangling symlink\(fileserver\) +diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c +index 545c7499f28..96edc8678e5 100644 +--- a/source3/smbd/dir.c ++++ b/source3/smbd/dir.c +@@ -1876,6 +1876,8 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp) + char *talloced = NULL; + SMB_STRUCT_STAT st; + struct connection_struct *conn = fsp->conn; ++ struct smb_filename *smb_dname = fsp->fsp_name; ++ int ret; + struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), + conn, + fsp->fsp_name, +@@ -1887,6 +1889,9 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp) + } + + while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) { ++ struct smb_filename *smb_dname_full = NULL; ++ char *fullname = NULL; ++ + if (ISDOT(dname) || (ISDOTDOT(dname))) { + TALLOC_FREE(talloced); + continue; +@@ -1901,6 +1906,98 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp) + continue; + } + ++ fullname = talloc_asprintf(talloc_tos(), ++ "%s/%s", ++ smb_dname->base_name, ++ dname); ++ ++ if (fullname == NULL) { ++ TALLOC_FREE(dir_hnd); ++ TALLOC_FREE(talloced); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ smb_dname_full = synthetic_smb_fname(talloc_tos(), ++ fullname, ++ NULL, ++ NULL, ++ smb_dname->twrp, ++ smb_dname->flags); ++ if (smb_dname_full == NULL) { ++ TALLOC_FREE(dir_hnd); ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ return NT_STATUS_NO_MEMORY; ++ } ++ ++ ret = SMB_VFS_LSTAT(conn, smb_dname_full); ++ if (ret != 0) { ++ TALLOC_FREE(dir_hnd); ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ return map_nt_error_from_unix(errno); ++ } ++ ++ if (S_ISLNK(smb_dname_full->st.st_ex_mode)) { ++ /* Could it be an msdfs link ? */ ++ if (lp_host_msdfs() && ++ lp_msdfs_root(SNUM(conn))) { ++ struct smb_filename *smb_atname; ++ smb_atname = synthetic_smb_fname(talloc_tos(), ++ dname, ++ NULL, ++ &smb_dname_full->st, ++ fsp->fsp_name->twrp, ++ fsp->fsp_name->flags); ++ if (smb_atname == NULL) { ++ TALLOC_FREE(dir_hnd); ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ return NT_STATUS_NO_MEMORY; ++ } ++ if (is_msdfs_link(conn, smb_atname)) { ++ TALLOC_FREE(dir_hnd); ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ TALLOC_FREE(smb_atname); ++ DBG_DEBUG("got msdfs link name %s " ++ "- can't delete directory %s\n", ++ dname, ++ fsp_str_dbg(fsp)); ++ return NT_STATUS_DIRECTORY_NOT_EMPTY; ++ } ++ TALLOC_FREE(smb_atname); ++ } ++ ++ /* Not a DFS link - could it be a dangling symlink ? */ ++ ret = SMB_VFS_STAT(conn, smb_dname_full); ++ if (ret == -1 && (errno == ENOENT || errno == ELOOP)) { ++ /* ++ * Dangling symlink. ++ * Allow if "delete veto files = yes" ++ */ ++ if (lp_delete_veto_files(SNUM(conn))) { ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ continue; ++ } ++ } ++ ++ DBG_DEBUG("got symlink name %s - " ++ "can't delete directory %s\n", ++ dname, ++ fsp_str_dbg(fsp)); ++ TALLOC_FREE(dir_hnd); ++ TALLOC_FREE(talloced); ++ TALLOC_FREE(fullname); ++ TALLOC_FREE(smb_dname_full); ++ return NT_STATUS_DIRECTORY_NOT_EMPTY; ++ } ++ + DEBUG(10,("got name %s - can't delete\n", + dname )); + status = NT_STATUS_DIRECTORY_NOT_EMPTY; +-- +2.33.1 + + +From 7189ea825d8c9e4777dba737227ead602ad9b651 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Mon, 25 Oct 2021 12:42:02 -0700 +Subject: [PATCH 7/7] s3: docs-xml: Clarify the "delete veto files" paramter. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879 + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme + +Autobuild-User(master): Ralph Böhme +Autobuild-Date(master): Fri Oct 29 14:57:14 UTC 2021 on sn-devel-184 + +(cherry picked from commit 0b818c6b77e972626d0b071bebcf4ce55619fb84) +(cherry picked from commit a549dc219cba5bd61969e4919ae4142f52c133ea) +--- + docs-xml/smbdotconf/filename/deletevetofiles.xml | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/docs-xml/smbdotconf/filename/deletevetofiles.xml b/docs-xml/smbdotconf/filename/deletevetofiles.xml +index 581dc05396d..570d4ac60a0 100644 +--- a/docs-xml/smbdotconf/filename/deletevetofiles.xml ++++ b/docs-xml/smbdotconf/filename/deletevetofiles.xml +@@ -4,9 +4,12 @@ + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> + + This option is used when Samba is attempting to +- delete a directory that contains one or more vetoed directories +- (see the +- option). If this option is set to no (the default) then if a vetoed ++ delete a directory that contains one or more vetoed files ++ or directories or non-visible files or directories (such ++ as dangling symlinks that point nowhere). ++ (see the , , ++ , ++ options). If this option is set to no (the default) then if a vetoed + directory contains any non-vetoed files or directories then the + directory delete will fail. This is usually what you want. + +-- +2.33.1 + diff --git a/SOURCES/samba-4.14-fix-domain-join-segfault.patch b/SOURCES/samba-4.14-fix-domain-join-segfault.patch new file mode 100644 index 0000000..0521c27 --- /dev/null +++ b/SOURCES/samba-4.14-fix-domain-join-segfault.patch @@ -0,0 +1,39 @@ +From 0ef9fe22f56ef3ff202f88426c3ee48c15e4a71e Mon Sep 17 00:00:00 2001 +From: Ralph Boehme +Date: Fri, 26 Nov 2021 11:59:45 +0100 +Subject: [PATCH] smbd: s3-dsgetdcname: handle num_ips == 0 + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14923 + +Pair-Programmed-With: Stefan Metzmacher +Signed-off-by: Ralph Boehme +Signed-off-by: Stefan Metzmacher +Reviewed-by: Guenther Deschner +Reviewed-by: Jeremy Allison + +Autobuild-User(master): Stefan Metzmacher +Autobuild-Date(master): Fri Dec 3 12:54:04 UTC 2021 on sn-devel-184 + +(cherry picked from commit 5e3df5f9ee64a80898f73585b19113354f463c44) +--- + source3/libsmb/dsgetdcname.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c +index f8ae96109b71..5954e48d747b 100644 +--- a/source3/libsmb/dsgetdcname.c ++++ b/source3/libsmb/dsgetdcname.c +@@ -572,6 +572,10 @@ static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx, + for (i = 0; i < numdcs; i++) { + size_t j; + ++ if (dcs[i].num_ips == 0) { ++ continue; ++ } ++ + dclist[ret_count].hostname = + talloc_move(dclist, &dcs[i].hostname); + +-- +2.33.1 + diff --git a/SOURCES/samba-4.14-fix-username-map-script.patch b/SOURCES/samba-4.14-fix-username-map-script.patch new file mode 100644 index 0000000..8d7dcc8 --- /dev/null +++ b/SOURCES/samba-4.14-fix-username-map-script.patch @@ -0,0 +1,227 @@ +From 0e179b5f06988c576a1fff505c06920d51fe8ed4 Mon Sep 17 00:00:00 2001 +From: Stefan Metzmacher +Date: Fri, 12 Nov 2021 15:27:58 +0100 +Subject: [PATCH 1/3] CVE-2020-25727: idmap_nss: verify that the name of the + sid belongs to the configured domain + +We already check the sid belongs to the domain, but checking the name +too feels better and make it easier to understand. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901 + +Signed-off-by: Stefan Metzmacher +Reviewed-by: Ralph Boehme +(cherry picked from commit bfd093648b4af51d104096c0cb3535e8706671e5) +--- + source3/winbindd/idmap_nss.c | 26 +++++++++++++++++++++----- + 1 file changed, 21 insertions(+), 5 deletions(-) + +diff --git a/source3/winbindd/idmap_nss.c b/source3/winbindd/idmap_nss.c +index da50e2b4aa7..2729a0de3f3 100644 +--- a/source3/winbindd/idmap_nss.c ++++ b/source3/winbindd/idmap_nss.c +@@ -139,18 +139,21 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma + for (i = 0; ids[i]; i++) { + struct group *gr; + enum lsa_SidType type; +- const char *p = NULL; ++ const char *_domain = NULL; ++ const char *_name = NULL; ++ char *domain = NULL; + char *name = NULL; + bool ret; + + /* by default calls to winbindd are disabled + the following call will not recurse so this is safe */ + (void)winbind_on(); +- ret = winbind_lookup_sid(talloc_tos(), ids[i]->sid, NULL, +- &p, &type); ++ ret = winbind_lookup_sid(talloc_tos(), ++ ids[i]->sid, ++ &_domain, ++ &_name, ++ &type); + (void)winbind_off(); +- name = discard_const_p(char, p); +- + if (!ret) { + /* TODO: how do we know if the name is really not mapped, + * or something just failed ? */ +@@ -158,6 +161,18 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma + continue; + } + ++ domain = discard_const_p(char, _domain); ++ name = discard_const_p(char, _name); ++ ++ if (!strequal(domain, dom->name)) { ++ struct dom_sid_buf buf; ++ DBG_ERR("DOMAIN[%s] ignoring SID[%s] belongs to %s [%s\\%s]\n", ++ dom->name, dom_sid_str_buf(ids[i]->sid, &buf), ++ sid_type_lookup(type), domain, name); ++ ids[i]->status = ID_UNMAPPED; ++ continue; ++ } ++ + switch (type) { + case SID_NAME_USER: { + struct passwd *pw; +@@ -190,6 +205,7 @@ static NTSTATUS idmap_nss_sids_to_unixids(struct idmap_domain *dom, struct id_ma + ids[i]->status = ID_UNKNOWN; + break; + } ++ TALLOC_FREE(domain); + TALLOC_FREE(name); + } + return NT_STATUS_OK; +-- +2.34.1 + + +From 704ae4b8308e9ae6c50e3548f98de65e97ab6aa6 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Fri, 12 Nov 2021 20:53:30 +1300 +Subject: [PATCH 2/3] CVE-2020-25717: nsswitch/nsstest.c: Lower 'non existent + uid' to make room for new accounts + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901 + +Signed-off-by: Joseph Sutton +Reviewed-by: Stefan Metzmacher +Reviewed-by: Ralph Boehme +(cherry picked from commit fdbee5e074ebd76d659613b8b7114d70f938c38a) +--- + nsswitch/nsstest.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/nsswitch/nsstest.c b/nsswitch/nsstest.c +index e2ee9fbf3af..45270cdc459 100644 +--- a/nsswitch/nsstest.c ++++ b/nsswitch/nsstest.c +@@ -466,7 +466,7 @@ static void nss_test_errors(void) + printf("ERROR Non existent user gave error %d\n", last_error); + } + +- pwd = getpwuid(0xFFF0); ++ pwd = getpwuid(0xFF00); + if (pwd || last_error != NSS_STATUS_NOTFOUND) { + total_errors++; + printf("ERROR Non existent uid gave error %d\n", last_error); +-- +2.34.1 + + +From 844723aa82cec67fd863fc327bde9fb04eab438d Mon Sep 17 00:00:00 2001 +From: Andrew Bartlett +Date: Fri, 12 Nov 2021 16:10:31 +1300 +Subject: [PATCH 3/3] CVE-2020-25717: s3:auth: Fallback to a SID/UID based + mapping if the named based lookup fails +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Before the CVE-2020-25717 fixes we had a fallback from +getpwnam('DOMAIN\user') to getpwnam('user') which was very dangerous and +unpredictable. + +Now we do the fallback based on sid_to_uid() followed by +getpwuid() on the returned uid. + +This obsoletes 'username map [script]' based workaround adviced +for CVE-2020-25717, when nss_winbindd is not used or +idmap_nss is actually used. + +In future we may decide to prefer or only do the SID/UID based +lookup, but for now we want to keep this unchanged as much as possible. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14901 + +Pair-Programmed-With: Stefan Metzmacher + +Signed-off-by: Andrew Bartlett +Signed-off-by: Stefan Metzmacher + +[metze@samba.org moved the new logic into the fallback codepath only + in order to avoid behavior changes as much as possible] +Reviewed-by: Ralph Boehme + +Autobuild-User(master): Ralph Böhme +Autobuild-Date(master): Mon Nov 15 19:01:56 UTC 2021 on sn-devel-184 + +(cherry picked from commit 0a546be05295a7e4a552f9f4f0c74aeb2e9a0d6e) +--- + source3/auth/auth_util.c | 34 +++++++++++++++++++++++++++++++++- + 1 file changed, 33 insertions(+), 1 deletion(-) + +diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c +index 065b525500f..7a97dd45f11 100644 +--- a/source3/auth/auth_util.c ++++ b/source3/auth/auth_util.c +@@ -1862,7 +1862,9 @@ const struct auth_session_info *get_session_info_system(void) + ***************************************************************************/ + + static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain, +- const char *username, char **found_username, ++ const char *username, ++ const struct dom_sid *sid, ++ char **found_username, + struct passwd **pwd, + bool *username_was_mapped) + { +@@ -1897,6 +1899,31 @@ static NTSTATUS check_account(TALLOC_CTX *mem_ctx, const char *domain, + } + + passwd = smb_getpwnam(mem_ctx, dom_user, &real_username, false); ++ if (!passwd && !*username_was_mapped) { ++ struct dom_sid_buf buf; ++ uid_t uid; ++ bool ok; ++ ++ DBG_DEBUG("Failed to find authenticated user %s via " ++ "getpwnam(), fallback to sid_to_uid(%s).\n", ++ dom_user, dom_sid_str_buf(sid, &buf)); ++ ++ ok = sid_to_uid(sid, &uid); ++ if (!ok) { ++ DBG_ERR("Failed to convert SID %s to a UID (dom_user[%s])\n", ++ dom_sid_str_buf(sid, &buf), dom_user); ++ return NT_STATUS_NO_SUCH_USER; ++ } ++ passwd = getpwuid_alloc(mem_ctx, uid); ++ if (!passwd) { ++ DBG_ERR("Failed to find local account with UID %lld for SID %s (dom_user[%s])\n", ++ (long long)uid, ++ dom_sid_str_buf(sid, &buf), ++ dom_user); ++ return NT_STATUS_NO_SUCH_USER; ++ } ++ real_username = talloc_strdup(mem_ctx, passwd->pw_name); ++ } + if (!passwd) { + DEBUG(3, ("Failed to find authenticated user %s via " + "getpwnam(), denying access.\n", dom_user)); +@@ -2042,6 +2069,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, + bool username_was_mapped; + struct passwd *pwd; + struct auth_serversupplied_info *result; ++ struct dom_sid sid; + TALLOC_CTX *tmp_ctx = talloc_stackframe(); + + /* +@@ -2088,9 +2116,13 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, + + /* this call will try to create the user if necessary */ + ++ sid_copy(&sid, info3->base.domain_sid); ++ sid_append_rid(&sid, info3->base.rid); ++ + nt_status = check_account(tmp_ctx, + nt_domain, + nt_username, ++ &sid, + &found_username, + &pwd, + &username_was_mapped); +-- +2.34.1 + diff --git a/SOURCES/samba-4.14-recursive-delete-of-veto-files.patch b/SOURCES/samba-4.14-recursive-delete-of-veto-files.patch new file mode 100644 index 0000000..62525e7 --- /dev/null +++ b/SOURCES/samba-4.14-recursive-delete-of-veto-files.patch @@ -0,0 +1,295 @@ +From 505e48439364c4027aa11aeda467bbd2060b89f4 Mon Sep 17 00:00:00 2001 +From: Jeremy Allison +Date: Thu, 21 Oct 2021 15:06:20 -0700 +Subject: [PATCH] s3: smbd: Add two tests showing recursive directory delete of + a directory containing veto file and msdfs links over SMB2. + +Add knownfail. + +BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878 + +Signed-off-by: Jeremy Allison +Reviewed-by: Ralph Boehme +(cherry picked from commit ad0082d79a681b981154747dcde5713e1933b88f) +(cherry picked from commit dab3fa1d8c27e696afa15e071331f646e06d9706) +--- + selftest/target/Samba3.pm | 16 ++ + source3/script/tests/test_veto_rmdir.sh | 217 ++++++++++++++++++++++++ + source3/selftest/tests.py | 3 + + 3 files changed, 236 insertions(+) + create mode 100755 source3/script/tests/test_veto_rmdir.sh + +diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm +index 14a1f1223b1..bbff9d74817 100755 +--- a/selftest/target/Samba3.pm ++++ b/selftest/target/Samba3.pm +@@ -1460,6 +1460,9 @@ sub setup_fileserver + my $bad_iconv_sharedir="$share_dir/bad_iconv"; + push(@dirs, $bad_iconv_sharedir); + ++ my $veto_sharedir="$share_dir/veto"; ++ push(@dirs,$veto_sharedir); ++ + my $ip4 = Samba::get_ipv4_addr("FILESERVER"); + my $fileserver_options = " + kernel change notify = yes +@@ -1568,6 +1571,19 @@ sub setup_fileserver + comment = smb username is [%U] + vfs objects = + ++[veto_files_nodelete] ++ path = $veto_sharedir ++ read only = no ++ msdfs root = yes ++ veto files = /veto_name*/ ++ delete veto files = no ++ ++[veto_files_delete] ++ path = $veto_sharedir ++ msdfs root = yes ++ veto files = /veto_name*/ ++ delete veto files = yes ++ + [homes] + comment = Home directories + browseable = No +diff --git a/source3/script/tests/test_veto_rmdir.sh b/source3/script/tests/test_veto_rmdir.sh +new file mode 100755 +index 00000000000..d3df8f1bba0 +--- /dev/null ++++ b/source3/script/tests/test_veto_rmdir.sh +@@ -0,0 +1,217 @@ ++#!/bin/sh ++# ++# Check smbclient can (or cannot) delete a directory containing veto files. ++# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878 ++# ++ ++if [ $# -lt 6 ]; then ++cat < "$tmpfile" < "$tmpfile" < "$tmpfile" < "$tmpfile" < "$tmpfile" < - 4.14.5-9 +- resolves: rhbz#2046174 - Fix username map script regression of CVE-2020-25717 +- resolves: rhbz#2046160 - Fix possible segfault while joining a domain +- resolves: rhbz#2046152 - Fix CVE-2021-44142 + +* Thu Dec 02 2021 Pavel Filipenský - 4.14.5-8 +- resolves: rhbz#2026717 - Dir containing dangling symlinks cannot be deleted + * Mon Nov 22 2021 Andreas Schneider - 4.14.5-7 - related: rhbz#2021171 - Fix CVE-2020-25717 - Fix running ktest (selftest)