[SCM] Samba Shared Repository - branch v4-17-stable updated

Jule Anger janger at samba.org
Tue Oct 25 09:12:44 UTC 2022


The branch, v4-17-stable has been updated
       via  21f995104c8 VERSION: Disable GIT_SNAPSHOT for the 4.17.2 release.
       via  37fa752e978 WHATSNEW: Add release notes for Samba 4.17.2.
       via  e96d28093ae CVE-2022-3592 smbd: Slightly simplify filename_convert_dirfsp()
       via  ace0ebde325 CVE-2022-3592 lib: add subdir_of() to source3/lib/util_path.c
       via  4e3e3f9c4fe CVE-2022-3592 torture3: Show that our symlink traversal checks are insecure
       via  4fbcfb285a9 CVE-2022-3592 smbd: No empty path components in openat_pathref_dirfsp_nosymlink()
       via  3007e32072f CVE-2022-3437 third_party/heimdal: Pass correct length to _gssapi_verify_pad()
       via  f33f8a515b0 CVE-2022-3437 third_party/heimdal: Check for overflow in _gsskrb5_get_mech()
       via  0de566954ec CVE-2022-3437 third_party/heimdal: Check buffer length against overflow for DES{,3} unwrap
       via  a0cd16f084d CVE-2022-3437 third_party/heimdal: Check the result of _gsskrb5_get_mech()
       via  c06f2e9ce24 CVE-2022-3437 third_party/heimdal: Avoid undefined behaviour in _gssapi_verify_pad()
       via  24099e34819 CVE-2022-3437 third_party/heimdal: Don't pass NULL pointers to memcpy() in DES unwrap
       via  abb3f7f1e3e CVE-2022-3437 third_party/heimdal: Use constant-time memcmp() in unwrap_des3()
       via  2ee62a7c9ff CVE-2022-3437 third_party/heimdal: Use constant-time memcmp() for arcfour unwrap
       via  846fbd0456a CVE-2022-3437 s4/auth/tests: Add unit tests for unwrap_des3()
       via  d5a06cd54e0 CVE-2022-3437 third_party/heimdal_build: Add gssapi-subsystem subsystem
       via  16ea178f162 CVE-2022-3437 third_party/heimdal: Remove __func__ compatibility workaround
       via  96e8adf7ae9 VERSION: Bump version up to Samba 4.17.2...
      from  ed12d43518f VERSION: Disable GIT_SNAPSHOT for the 4.17.1 release.

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-17-stable


- Log -----------------------------------------------------------------
commit 21f995104c870cdfbdb0db61e290b2da8bc87ee1
Author: Jule Anger <janger at samba.org>
Date:   Mon Oct 24 12:50:24 2022 +0200

    VERSION: Disable GIT_SNAPSHOT for the 4.17.2 release.
    
    Signed-off-by: Jule Anger <janger at samba.org>

commit 37fa752e9780aba2102c40e8a256c0d6e3338a93
Author: Jule Anger <janger at samba.org>
Date:   Mon Oct 24 12:32:18 2022 +0200

    WHATSNEW: Add release notes for Samba 4.17.2.
    
    Signed-off-by: Jule Anger <janger at samba.org>

commit e96d28093ae1b7749a7d7c67133dbd12dc25290b
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Oct 15 13:37:17 2022 +0200

    CVE-2022-3592 smbd: Slightly simplify filename_convert_dirfsp()
    
    subdir_of() calculates the share-relative rest for us, don't do the
    strlen(connectpath) calculation twice. subdir_of() also checks that
    the target properly ends on a directory. With just strncmp a symlink
    to x->/aa/etc would qualify as in share /a, so a "get x/passwd" leads to a
    pretty unfortunate result. This is the proper fix for bug 15207, so we
    need to change the expected error code to OBJECT_PATH_NOT_FOUND
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=15207
    Signed-off-by: Volker Lendecke <vl at samba.org>

commit ace0ebde325958995672bb3d476e072ba1358356
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Oct 15 13:26:48 2022 +0200

    CVE-2022-3592 lib: add subdir_of() to source3/lib/util_path.c
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=15207
    Signed-off-by: Volker Lendecke <vl at samba.org>

commit 4e3e3f9c4fe24b49c714b1b90f6bf0ba63bf85b0
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Oct 15 14:09:55 2022 +0200

    CVE-2022-3592 torture3: Show that our symlink traversal checks are insecure
    
    This test shows that we don't properly check whether symlink targets
    are inside the exported share. Linking to <share-root>a/etc makes us
    loop back into filename_convert_dirfsp_nosymlink() with /etc as a
    directory name.
    
    On Linux systems with openat2(RESOLVE_NO_SYMLINKS) we pass "/etc"
    directly into that call after some checks for "."/".." as invalid file
    name components. "/etc" is okay for openat2(), but this test must also
    succeed on systems without RESOLVE_NO_SYMLINKS (sn-devel-184 for
    example). On systems without RESOLVE_NO_SYMLINKS split up the path
    "/etc" into path components, in this case "" and "etc". So we pass ""
    down to openat(), which correctly fails with ENOENT.
    
    Summary: Only with RESOLVE_NO_SYMLINKS we're hit by bug 15207, and
    this test shows by expecting CONNECTION_DISCONNECTED that we violate
    the internal assumption of empty path components with an unexpected
    symlink target, making it testable on systems with and without
    RESOLVE_NO_SYMLINKS.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=15207
    Signed-off-by: Volker Lendecke <vl at samba.org>

commit 4fbcfb285a923b3d9dbcb4a7c891167628201067
Author: Volker Lendecke <vl at samba.org>
Date:   Mon Oct 17 18:06:02 2022 +0200

    CVE-2022-3592 smbd: No empty path components in openat_pathref_dirfsp_nosymlink()
    
    Upper layers must have filtered this, everything else is a bug
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=15207
    Signed-off-by: Volker Lendecke <vl at samba.org>

commit 3007e32072f5b34b4ca403b9d52100627c3a74d2
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Oct 12 13:57:33 2022 +1300

    CVE-2022-3437 third_party/heimdal: Pass correct length to _gssapi_verify_pad()
    
    We later subtract 8 when calculating the length of the output message
    buffer. If padlength is excessively high, this calculation can underflow
    and result in a very large positive value.
    
    Now we properly constrain the value of padlength so underflow shouldn't
    be possible.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f33f8a515b0f44db58ebeb7274a3118277143a4f
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon Oct 10 20:33:09 2022 +1300

    CVE-2022-3437 third_party/heimdal: Check for overflow in _gsskrb5_get_mech()
    
    If len_len is equal to total_len - 1 (i.e. the input consists only of a
    0x60 byte and a length), the expression 'total_len - 1 - len_len - 1',
    used as the 'len' parameter to der_get_length(), will overflow to
    SIZE_MAX. Then der_get_length() will proceed to read, unconstrained,
    whatever data follows in memory. Add a check to ensure that doesn't
    happen.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 0de566954eccc44c5892e62005a8bd4e725ea7d3
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon Aug 15 16:54:23 2022 +1200

    CVE-2022-3437 third_party/heimdal: Check buffer length against overflow for DES{,3} unwrap
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a0cd16f084d70185b0de9151d0d259a634a31e96
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon Aug 15 16:53:55 2022 +1200

    CVE-2022-3437 third_party/heimdal: Check the result of _gsskrb5_get_mech()
    
    We should make sure that the result of 'total_len - mech_len' won't
    overflow, and that we don't memcmp() past the end of the buffer.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c06f2e9ce24c0d945eb597e71fb286df92d23415
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Mon Aug 15 16:53:45 2022 +1200

    CVE-2022-3437 third_party/heimdal: Avoid undefined behaviour in _gssapi_verify_pad()
    
    By decrementing 'pad' only when we know it's safe, we ensure we can't
    stray backwards past the start of a buffer, which would be undefined
    behaviour.
    
    In the previous version of the loop, 'i' is the number of bytes left to
    check, and 'pad' is the current byte we're checking. 'pad' was
    decremented at the end of each loop iteration. If 'i' was 1 (so we
    checked the final byte), 'pad' could potentially be pointing to the
    first byte of the input buffer, and the decrement would put it one
    byte behind the buffer.
    
    That would be undefined behaviour.
    
    The patch changes it so that 'pad' is the byte we previously checked,
    which allows us to ensure that we only decrement it when we know we
    have a byte to check.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 24099e348199c8e34f18c40e5ee42838a6e4529f
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Oct 12 13:57:42 2022 +1300

    CVE-2022-3437 third_party/heimdal: Don't pass NULL pointers to memcpy() in DES unwrap
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit abb3f7f1e3ec90146f4f805886cbbaf8ac38a5de
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Oct 12 13:57:55 2022 +1300

    CVE-2022-3437 third_party/heimdal: Use constant-time memcmp() in unwrap_des3()
    
    The surrounding checks all use ct_memcmp(), so this one was presumably
    meant to as well.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2ee62a7c9ff96fd09efa87161a09a8539a99900f
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Oct 12 13:57:13 2022 +1300

    CVE-2022-3437 third_party/heimdal: Use constant-time memcmp() for arcfour unwrap
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 846fbd0456ab7eb435dd7438cf6c5a288f6f8fbd
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Oct 12 13:55:39 2022 +1300

    CVE-2022-3437 s4/auth/tests: Add unit tests for unwrap_des3()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d5a06cd54e015573769efc6aeb3327454b7de7ac
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Oct 12 13:55:51 2022 +1300

    CVE-2022-3437 third_party/heimdal_build: Add gssapi-subsystem subsystem
    
    This allows us to access (and so test) functions internal to GSSAPI by
    depending on this subsystem.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 16ea178f162368741666b990b4f26751310e0ac6
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Wed Oct 12 13:56:08 2022 +1300

    CVE-2022-3437 third_party/heimdal: Remove __func__ compatibility workaround
    
    As described by the C standard, __func__ is a variable, not a macro.
    Hence this #ifndef check does not work as intended, and only serves to
    unconditionally disable __func__. A nonoperating __func__ prevents
    cmocka operating correctly, so remove this definition.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 VERSION                                            |    2 +-
 WHATSNEW.txt                                       |   53 +-
 selftest/tests.py                                  |    5 +
 source3/lib/util_path.c                            |   51 +
 source3/lib/util_path.h                            |    4 +
 .../script/tests/test_symlink_traversal_smb2.sh    |    4 +
 source3/smbd/filename.c                            |   11 +-
 source3/smbd/files.c                               |    6 +
 source4/auth/tests/heimdal_unwrap_des.c            | 1244 ++++++++++++++++++++
 source4/auth/wscript_build                         |   21 +
 third_party/heimdal/lib/gssapi/krb5/arcfour.c      |   14 +-
 third_party/heimdal/lib/gssapi/krb5/decapsulate.c  |   12 +-
 third_party/heimdal/lib/gssapi/krb5/unwrap.c       |   34 +-
 third_party/heimdal/lib/krb5/krb5_locl.h           |    4 -
 third_party/heimdal_build/wscript_build            |   18 +-
 15 files changed, 1446 insertions(+), 37 deletions(-)
 create mode 100644 source4/auth/tests/heimdal_unwrap_des.c


Changeset truncated at 500 lines:

diff --git a/VERSION b/VERSION
index ef2a40f07e8..4af2e6e0518 100644
--- a/VERSION
+++ b/VERSION
@@ -25,7 +25,7 @@
 ########################################################
 SAMBA_VERSION_MAJOR=4
 SAMBA_VERSION_MINOR=17
-SAMBA_VERSION_RELEASE=1
+SAMBA_VERSION_RELEASE=2
 
 ########################################################
 # If a official release has a serious bug              #
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 307c166a98e..9b9d644694d 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,3 +1,53 @@
+                   ==============================
+                   Release Notes for Samba 4.17.2
+                          October 25, 2022
+                   ==============================
+
+
+This is a security release in order to address the following defects:
+
+o CVE-2022-3437:  There is a limited write heap buffer overflow in the GSSAPI
+                  unwrap_des() and unwrap_des3() routines of Heimdal (included
+                  in Samba).
+                  https://www.samba.org/samba/security/CVE-2022-3437.html
+
+o CVE-2022-3592:  A malicious client can use a symlink to escape the exported
+                  directory.
+                  https://www.samba.org/samba/security/CVE-2022-3592.html
+
+Changes since 4.17.1
+--------------------
+
+o  Volker Lendecke <vl at samba.org>
+   * BUG 15207: CVE-2022-3592.
+
+o  Joseph Sutton <josephsutton at catalyst.net.nz>
+   * BUG 15134: CVE-2022-3437.
+
+
+#######################################
+Reporting bugs & Development Discussion
+#######################################
+
+Please discuss this release on the samba-technical mailing list or by
+joining the #samba-technical:matrix.org matrix room, or
+#samba-technical IRC channel on irc.libera.chat.
+
+If you do report problems then please try to send high quality
+feedback. If you don't provide vital information to help us track down
+the problem then you will probably be ignored.  All bug reports should
+be filed under the Samba 4.1 and newer product in the project's Bugzilla
+database (https://bugzilla.samba.org/).
+
+
+======================================================================
+== Our Code, Our Bugs, Our Responsibility.
+== The Samba Team
+======================================================================
+
+
+Release notes for older releases follow:
+----------------------------------------
                    ==============================
                    Release Notes for Samba 4.17.1
                           October 19, 2022
@@ -83,8 +133,7 @@ database (https://bugzilla.samba.org/).
 ======================================================================
 
 
-Release notes for older releases follow:
-----------------------------------------
+----------------------------------------------------------------------
                    ==============================
                    Release Notes for Samba 4.17.0
                          September 13, 2022
diff --git a/selftest/tests.py b/selftest/tests.py
index b5e418cca3b..0b6ceb5fbb9 100644
--- a/selftest/tests.py
+++ b/selftest/tests.py
@@ -47,6 +47,8 @@ with_pam = ("WITH_PAM" in config_hash)
 with_elasticsearch_backend = ("HAVE_SPOTLIGHT_BACKEND_ES" in config_hash)
 pam_wrapper_so_path = config_hash.get("LIBPAM_WRAPPER_SO_PATH")
 pam_set_items_so_path = config_hash.get("PAM_SET_ITEMS_SO_PATH")
+have_heimdal_support = "SAMBA4_USES_HEIMDAL" in config_hash
+using_system_gssapi = "USING_SYSTEM_GSSAPI" in config_hash
 
 planpythontestsuite("none", "samba.tests.source")
 planpythontestsuite("none", "samba.tests.source_chars")
@@ -448,6 +450,9 @@ plantestsuite("samba.unittests.test_oLschema2ldif", "none",
               [os.path.join(bindir(), "default/source4/utils/oLschema2ldif/test_oLschema2ldif")])
 plantestsuite("samba.unittests.auth.sam", "none",
               [os.path.join(bindir(), "test_auth_sam")])
+if have_heimdal_support and not using_system_gssapi:
+    plantestsuite("samba.unittests.auth.heimdal_gensec_unwrap_des", "none",
+                  [valgrindify(os.path.join(bindir(), "test_heimdal_gensec_unwrap_des"))])
 if with_elasticsearch_backend:
     plantestsuite("samba.unittests.mdsparser_es", "none",
                   [os.path.join(bindir(), "default/source3/test_mdsparser_es")] + [configuration])
diff --git a/source3/lib/util_path.c b/source3/lib/util_path.c
index 3591589cb8e..b8dfec40b03 100644
--- a/source3/lib/util_path.c
+++ b/source3/lib/util_path.c
@@ -23,6 +23,7 @@
 
 #include "replace.h"
 #include <talloc.h>
+#include "lib/util/debug.h"
 #include "lib/util/samba_util.h"
 #include "lib/util_path.h"
 
@@ -204,3 +205,53 @@ char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *pathname_in)
 	*p++ = '\0';
 	return pathname;
 }
+
+/*
+ * Take two absolute paths, figure out if "subdir" is a proper
+ * subdirectory of "parent". Return the component relative to the
+ * "parent" without the potential "/". Take care of "parent"
+ * possibly ending in "/".
+ */
+bool subdir_of(const char *parent,
+	       size_t parent_len,
+	       const char *subdir,
+	       const char **_relative)
+{
+	const char *relative = NULL;
+	bool matched;
+
+	SMB_ASSERT(parent[0] == '/');
+	SMB_ASSERT(subdir[0] == '/');
+
+	if (parent_len == 1) {
+		/*
+		 * Everything is below "/"
+		 */
+		*_relative = subdir+1;
+		return true;
+	}
+
+	if (parent[parent_len-1] == '/') {
+		parent_len -= 1;
+	}
+
+	matched = (strncmp(subdir, parent, parent_len) == 0);
+	if (!matched) {
+		return false;
+	}
+
+	relative = &subdir[parent_len];
+
+	if (relative[0] == '\0') {
+		*_relative = relative; /* nothing left */
+		return true;
+	}
+
+	if (relative[0] == '/') {
+		/* End of parent must match a '/' in subdir. */
+		*_relative = relative+1;
+		return true;
+	}
+
+	return false;
+}
diff --git a/source3/lib/util_path.h b/source3/lib/util_path.h
index 3e7d04de550..0ea508bf5bb 100644
--- a/source3/lib/util_path.h
+++ b/source3/lib/util_path.h
@@ -31,5 +31,9 @@ char *lock_path(TALLOC_CTX *mem_ctx, const char *name);
 char *state_path(TALLOC_CTX *mem_ctx, const char *name);
 char *cache_path(TALLOC_CTX *mem_ctx, const char *name);
 char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *abs_path);
+bool subdir_of(const char *parent,
+	       size_t parent_len,
+	       const char *subdir,
+	       const char **_relative);
 
 #endif
diff --git a/source3/script/tests/test_symlink_traversal_smb2.sh b/source3/script/tests/test_symlink_traversal_smb2.sh
index 971d5344216..1fb9c67420d 100755
--- a/source3/script/tests/test_symlink_traversal_smb2.sh
+++ b/source3/script/tests/test_symlink_traversal_smb2.sh
@@ -144,6 +144,9 @@ chmod 0 "$dir_outside_share_noperms"
 	ln -s "dir_inside_share_noperms" "symlink_dir_inside_share_noperms"
 	mkdir "dir_inside_share_noperms/noperm_subdir_exists"
 	touch "dir_inside_share_noperms/noperm_subdir_exists/noperm_subdir_file_exists"
+
+	# Symlink pointing out of the share
+	ln -s "$share_test_dir"a"/etc" x
 )
 
 #
@@ -345,6 +348,7 @@ test_symlink_traversal_SMB2()
 	smbclient_expect_error "get" "symlink_to_dir_exists/subdir_exists" "" "NT_STATUS_FILE_IS_A_DIRECTORY" || return 1
 	smbclient_expect_error "get" "symlink_to_dir_exists/subdir_exists/noexist1" "" "NT_STATUS_OBJECT_NAME_NOT_FOUND" || return 1
 	smbclient_expect_error "get" "symlink_to_dir_exists/subdir_exists/noexist1/noexist2" "" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
+	smbclient_expect_error "get" "x/passwd" "passwd" "NT_STATUS_OBJECT_PATH_NOT_FOUND" || return 1
 
 	#
 	# Test paths within share with no permissions.
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index 0be8e320ffa..e7873eb124f 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -1440,6 +1440,7 @@ NTSTATUS filename_convert_dirfsp(
 	struct smb_filename **_smb_fname)
 {
 	char *substitute = NULL;
+	const char *relative = NULL;
 	size_t unparsed = 0;
 	NTSTATUS status;
 	char *target = NULL;
@@ -1512,17 +1513,17 @@ next:
 
 	DBG_DEBUG("abs_target_canon=%s\n", abs_target_canon);
 
-	in_share = strncmp(
-		abs_target_canon,
+	in_share = subdir_of(
 		conn->connectpath,
-		strlen(conn->connectpath)) == 0;
+		strlen(conn->connectpath),
+		abs_target_canon,
+		&relative);
 	if (!in_share) {
 		DBG_DEBUG("wide link to %s\n", abs_target_canon);
 		return NT_STATUS_OBJECT_PATH_NOT_FOUND;
 	}
 
-	name_in = talloc_strdup(
-		mem_ctx, abs_target_canon + strlen(conn->connectpath) + 1);
+	name_in = talloc_strdup(mem_ctx, relative);
 
 	symlink_redirects += 1;
 
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 179c3e11a76..9b0c902c0d4 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -817,6 +817,12 @@ NTSTATUS openat_pathref_dirfsp_nosymlink(
 
 		next = strv_next(path, rel_fname.base_name);
 
+		/*
+		 * Path sanitizing further up has cleaned or rejected
+		 * empty path components. Assert this here.
+		 */
+		SMB_ASSERT(rel_fname.base_name[0] != '\0');
+
 		if (ISDOT(rel_fname.base_name) || ISDOTDOT(rel_fname.base_name)) {
 			DBG_DEBUG("%s contains a dot\n", path_in);
 			status = NT_STATUS_OBJECT_NAME_INVALID;
diff --git a/source4/auth/tests/heimdal_unwrap_des.c b/source4/auth/tests/heimdal_unwrap_des.c
new file mode 100644
index 00000000000..fbfe7782e7e
--- /dev/null
+++ b/source4/auth/tests/heimdal_unwrap_des.c
@@ -0,0 +1,1244 @@
+/*
+ * Unit tests for third_party/heimdal/lib/gssapi/krb5/unwrap.c
+ *
+ * Copyright (C) Catalyst.NET Ltd 2022
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * from cmocka.c:
+ * These headers or their equivalents should be included prior to
+ * including
+ * this header file.
+ *
+ * #include <stdarg.h>
+ * #include <stddef.h>
+ * #include <setjmp.h>
+ *
+ * This allows test applications to use custom definitions of C standard
+ * library functions and types.
+ *
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+
+#include <cmocka.h>
+
+#include "includes.h"
+#include "replace.h"
+
+#include "../../../third_party/heimdal/lib/gssapi/gssapi/gssapi.h"
+#include "gsskrb5_locl.h"
+
+/******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+
+const uint8_t *valid_range_begin;
+const uint8_t *valid_range_end;
+const uint8_t *invalid_range_end;
+
+/*
+ * 'array_len' is the size of the passed in array. 'buffer_len' is the size to
+ * report in the resulting buffer.
+ */
+static const gss_buffer_desc get_input_buffer(TALLOC_CTX *mem_ctx,
+					      const uint8_t array[],
+					      const size_t array_len,
+					      const size_t buffer_len)
+{
+	gss_buffer_desc buf;
+
+	/* Add some padding to catch invalid memory accesses. */
+	const size_t padding = 0x100;
+	const size_t padded_len = array_len + padding;
+
+	uint8_t *data = talloc_size(mem_ctx, padded_len);
+	assert_non_null(data);
+
+	memcpy(data, array, array_len);
+	memset(data + array_len, 0, padding);
+
+	assert_in_range(buffer_len, 0, array_len);
+
+	buf.value = data;
+	buf.length = buffer_len;
+
+	valid_range_begin = buf.value;
+	valid_range_end = valid_range_begin + buf.length;
+	invalid_range_end = valid_range_begin + padded_len;
+
+	return buf;
+}
+
+static void assert_mem_in_valid_range(const uint8_t *ptr, const size_t len)
+{
+	/* Ensure we've set up the range pointers properly. */
+	assert_non_null(valid_range_begin);
+	assert_non_null(valid_range_end);
+	assert_non_null(invalid_range_end);
+
+	/*
+	 * Ensure the length isn't excessively large (a symptom of integer
+	 * underflow).
+	 */
+	assert_in_range(len, 0, 0x1000);
+
+	/* Ensure the memory is in our valid range. */
+	assert_in_range(ptr, valid_range_begin, valid_range_end);
+	assert_in_range(ptr + len, valid_range_begin, valid_range_end);
+}
+
+/*
+ * This function takes a pointer to volatile to allow it to be called from the
+ * ct_memcmp() wrapper.
+ */
+static void assert_mem_outside_invalid_range(const volatile uint8_t *ptr,
+					     const size_t len)
+{
+	const LargestIntegralType _valid_range_end
+		= cast_ptr_to_largest_integral_type(valid_range_end);
+	const LargestIntegralType _invalid_range_end
+		= cast_ptr_to_largest_integral_type(invalid_range_end);
+	const LargestIntegralType _ptr = cast_ptr_to_largest_integral_type(ptr);
+	const LargestIntegralType _len = cast_to_largest_integral_type(len);
+
+	/* Ensure we've set up the range pointers properly. */
+	assert_non_null(valid_range_begin);
+	assert_non_null(valid_range_end);
+	assert_non_null(invalid_range_end);
+
+	/*
+	 * Ensure the length isn't excessively large (a symptom of integer
+	 * underflow).
+	 */
+	assert_in_range(len, 0, 0x1000);
+
+	/* Ensure the memory is outside the invalid range. */
+	if (_ptr < _invalid_range_end && _ptr + _len > _valid_range_end) {
+		fail();
+	}
+}
+
+/*****************************************************************************
+ * wrapped functions
+ *****************************************************************************/
+
+krb5_keyblock dummy_key;
+
+krb5_error_code __wrap_krb5_auth_con_getlocalsubkey(krb5_context context,
+						    krb5_auth_context auth_context,
+						    krb5_keyblock **keyblock);
+krb5_error_code __wrap_krb5_auth_con_getlocalsubkey(krb5_context context,
+						    krb5_auth_context auth_context,
+						    krb5_keyblock **keyblock)
+{
+	*keyblock = &dummy_key;
+	return 0;
+}
+
+void __wrap_krb5_free_keyblock(krb5_context context,
+			krb5_keyblock *keyblock);
+void __wrap_krb5_free_keyblock(krb5_context context,
+			krb5_keyblock *keyblock)
+{
+	assert_ptr_equal(&dummy_key, keyblock);
+}
+
+struct krb5_crypto_data dummy_crypto;
+
+krb5_error_code __wrap_krb5_crypto_init(krb5_context context,
+					const krb5_keyblock *key,
+					krb5_enctype etype,
+					krb5_crypto *crypto);
+krb5_error_code __wrap_krb5_crypto_init(krb5_context context,
+					const krb5_keyblock *key,
+					krb5_enctype etype,
+					krb5_crypto *crypto)
+{
+	static const LargestIntegralType etypes[] = {ETYPE_DES3_CBC_NONE, 0};
+
+	assert_ptr_equal(&dummy_key, key);
+	assert_in_set(etype, etypes, ARRAY_SIZE(etypes));
+
+	*crypto = &dummy_crypto;
+
+	return 0;
+}
+
+krb5_error_code __wrap_krb5_decrypt(krb5_context context,
+				    krb5_crypto crypto,
+				    unsigned usage,
+				    void *data,
+				    size_t len,
+				    krb5_data *result);
+krb5_error_code __wrap_krb5_decrypt(krb5_context context,
+				    krb5_crypto crypto,
+				    unsigned usage,
+				    void *data,
+				    size_t len,
+				    krb5_data *result)
+{
+	assert_ptr_equal(&dummy_crypto, crypto);
+	assert_int_equal(KRB5_KU_USAGE_SEAL, usage);
+
+	assert_mem_in_valid_range(data, len);
+
+	check_expected(len);
+	check_expected_ptr(data);
+
+	result->data = malloc(len);
+	assert_non_null(result->data);
+	result->length = len;
+
+	memcpy(result->data, data, len);
+
+	return 0;
+}
+
+krb5_error_code __wrap_krb5_decrypt_ivec(krb5_context context,
+					 krb5_crypto crypto,
+					 unsigned usage,
+					 void *data,
+					 size_t len,
+					 krb5_data *result,
+					 void *ivec);
+krb5_error_code __wrap_krb5_decrypt_ivec(krb5_context context,
+					 krb5_crypto crypto,
+					 unsigned usage,
+					 void *data,
+					 size_t len,
+					 krb5_data *result,
+					 void *ivec)
+{
+	assert_ptr_equal(&dummy_crypto, crypto);
+	assert_int_equal(KRB5_KU_USAGE_SEQ, usage);
+
+	assert_mem_in_valid_range(data, len);
+
+	assert_int_equal(8, len);
+	check_expected_ptr(data);
+	check_expected_ptr(ivec);


-- 
Samba Shared Repository



More information about the samba-cvs mailing list