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

Jule Anger janger at samba.org
Tue Oct 25 09:48:42 UTC 2022


The branch, v4-17-test has been updated
       via  0b562285733 VERSION: Bump version up to Samba 4.17.3...
       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
      from  96e8adf7ae9 VERSION: Bump version up to Samba 4.17.2...

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


- Log -----------------------------------------------------------------
commit 0b5622857339b9c2c50677c6b823eaa0f7f7fbf5
Author: Jule Anger <janger at samba.org>
Date:   Tue Oct 25 11:47:31 2022 +0200

    VERSION: Bump version up to Samba 4.17.3...
    
    and re-enable GIT_SNAPSHOT.
    
    Signed-off-by: Jule Anger <janger 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 8d324fa4c66..59521d4f944 100644
--- a/VERSION
+++ b/VERSION
@@ -25,7 +25,7 @@
 ########################################################
 SAMBA_VERSION_MAJOR=4
 SAMBA_VERSION_MINOR=17
-SAMBA_VERSION_RELEASE=2
+SAMBA_VERSION_RELEASE=3
 
 ########################################################
 # 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