[SCM] Samba Shared Repository - branch master updated

Jule Anger janger at samba.org
Tue Oct 25 11:28:02 UTC 2022


The branch, master has been updated
       via  d385058ce7c CVE-2022-3592 smbd: Slightly simplify filename_convert_dirfsp()
       via  d905dbddf8d CVE-2022-3592 lib: Move subdir_of() to source3/lib/util_path.c
       via  fbc0feeca40 CVE-2022-3592 lib: lib/util/fault.h requires _SAMBA_DEBUG_H for SMB_ASSERT()
       via  c770b7872da CVE-2022-3592 torture3: Show that our symlink traversal checks are insecure
       via  dc650bde6f9 CVE-2022-3592 smbd: No empty path components in openat_pathref_dirfsp_nosymlink()
       via  2671f995fed CVE-2022-3437 third_party/heimdal: Pass correct length to _gssapi_verify_pad()
       via  d12bd2cd50b CVE-2022-3437 third_party/heimdal: Check for overflow in _gsskrb5_get_mech()
       via  2d0ad4ede7b CVE-2022-3437 third_party/heimdal: Check buffer length against overflow for DES{,3} unwrap
       via  841b6ddcf2a CVE-2022-3437 third_party/heimdal: Check the result of _gsskrb5_get_mech()
       via  ba60f647524 CVE-2022-3437 third_party/heimdal: Avoid undefined behaviour in _gssapi_verify_pad()
       via  ad9d1690ed5 CVE-2022-3437 third_party/heimdal: Don't pass NULL pointers to memcpy() in DES unwrap
       via  dffc997adac CVE-2022-3437 third_party/heimdal: Use constant-time memcmp() in unwrap_des3()
       via  16120b736f2 CVE-2022-3437 third_party/heimdal: Use constant-time memcmp() for arcfour unwrap
       via  c8e85295c98 CVE-2022-3437 s4/auth/tests: Add unit tests for unwrap_des3()
       via  ec456766d53 CVE-2022-3437 third_party/heimdal_build: Add gssapi-subsystem subsystem
       via  cd48f2da59f CVE-2022-3437 third_party/heimdal: Remove __func__ compatibility workaround
      from  ce7c418ca4f python/samba/tests: fix samba.tests.auth_log_pass_change for later gnutls

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit d385058ce7c9914ea58613f65414e45f2f777481
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>
    
    Autobuild-User(master): Jule Anger <janger at samba.org>
    Autobuild-Date(master): Tue Oct 25 11:27:02 UTC 2022 on sn-devel-184

commit d905dbddf8d2655e6c91752b750cbe9c15837ee5
Author: Volker Lendecke <vl at samba.org>
Date:   Sat Oct 15 13:29:14 2022 +0200

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

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

    CVE-2022-3592 lib: lib/util/fault.h requires _SAMBA_DEBUG_H for SMB_ASSERT()
    
    fault.h has:
    
    which leads to SMB_ASSERT not being defined when you include
    samba_util.h (and thus fault.h) before debug.h.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=15207
    Signed-off-by: Volker Lendecke <vl at samba.org>

commit c770b7872daae21e5ead57374707d7ac334c8f69
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 dc650bde6f97ea63d6105ead874b0249307db13b
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 2671f995fed735bb03d9efd55d6603b35141ff38
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 d12bd2cd50b45e064e5bea5a99c826ef156b4e64
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 2d0ad4ede7b391af3f38cd3664dc04c7ceea76e8
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 841b6ddcf2a80c085ed6159ec9d420f37ceb691e
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 ba60f647524ec12b3b5901680c5922d6b2490420
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 ad9d1690ed51d73fbfb7dcb07c6ecb7750cab290
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 dffc997adaccaa0980911b62473470cb80969700
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 16120b736f28e85e7b46f8c69b7aa02073b2e26c
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 c8e85295c988d653c3c425e0c4b8900f30fa1bba
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 ec456766d53da45c9d3edcb382569768cbef60dd
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 cd48f2da59f48caa20e7ac652c958182671e804b
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:
 selftest/tests.py                                  |    5 +
 source3/lib/util_path.c                            |   52 +-
 source3/lib/util_path.h                            |    4 +
 .../script/tests/test_symlink_traversal_smb2.sh    |    4 +
 source3/smbd/filename.c                            |   11 +-
 source3/smbd/files.c                               |    6 +
 source3/smbd/open.c                                |   52 -
 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 +-
 14 files changed, 1394 insertions(+), 87 deletions(-)
 create mode 100644 source4/auth/tests/heimdal_unwrap_des.c


Changeset truncated at 500 lines:

diff --git a/selftest/tests.py b/selftest/tests.py
index 46d301956ed..db43d8a9e7d 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")
@@ -449,6 +451,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 5b7c01b05e3..5a94b391dd6 100644
--- a/source3/lib/util_path.c
+++ b/source3/lib/util_path.c
@@ -23,8 +23,8 @@
 
 #include "replace.h"
 #include <talloc.h>
-#include "lib/util/samba_util.h"
 #include "lib/util/debug.h"
+#include "lib/util/samba_util.h"
 #include "lib/util_path.h"
 
 struct loadparm_substitution;
@@ -304,3 +304,53 @@ bool extract_snapshot_token(char *fname, NTTIME *twrp)
 
 	return true;
 }
+
+/*
+ * 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 33699da28c2..5b0a1f13e38 100644
--- a/source3/lib/util_path.h
+++ b/source3/lib/util_path.h
@@ -49,5 +49,9 @@ bool clistr_is_previous_version_path(const char *path,
 				     const char **startp,
 				     const char **endp,
 				     NTTIME *ptwrp);
+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 efd4353c533..38719cc8eae 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"
 	mkdir "dir_inside_share_noperms/noperm_subdir_exists"
 	touch "dir_inside_share_noperms/noperm_subdir_exists/noperm_subdir_file_exists"
 	chmod 0 "dir_inside_share_noperms"
+
+	# 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 79bb7dffe99..5bfa4b2f1df 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -1369,6 +1369,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;
@@ -1441,17 +1442,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 87c1f0f6301..64297f18773 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);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 9d85b0d8ef8..d4a679a4cb0 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -475,58 +475,6 @@ static NTSTATUS check_base_file_access(struct files_struct *fsp,
 					access_mask);
 }
 
-/*
- * 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 "/".
- */
-static 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;
-}
-
 static NTSTATUS chdir_below_conn(
 	TALLOC_CTX *mem_ctx,
 	connection_struct *conn,
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);
+
+	result->data = malloc(len);
+	assert_non_null(result->data);
+	result->length = len;
+
+	memcpy(result->data, data, len);
+
+	return 0;
+}
+
+krb5_error_code __wrap_krb5_verify_checksum(krb5_context context,
+					    krb5_crypto crypto,
+					    krb5_key_usage usage,
+					    void *data,
+					    size_t len,
+					    Checksum *cksum);


-- 
Samba Shared Repository



More information about the samba-cvs mailing list