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 <jan...@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 <jan...@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 <v...@samba.org>
+   * BUG 15207: CVE-2022-3592.
+
+o  Joseph Sutton <josephsut...@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

Reply via email to