The Samba-Bugzilla – Attachment 17559 Details for
Bug 15134
CVE-2022-3437 [SECURITY] Heimdal des/des3 overflow
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for Samba 4.15 (v4a)
CVE-2022-3437-des3-overflow-v4a-4.15.patch (text/plain), 63.22 KB, created by
Andrew Bartlett
on 2022-10-13 01:03:00 UTC
(
hide
)
Description:
Patch for Samba 4.15 (v4a)
Filename:
MIME Type:
Creator:
Andrew Bartlett
Created:
2022-10-13 01:03:00 UTC
Size:
63.22 KB
patch
obsolete
>From 2f28aa3706866258b6e562cbe5f804a9e5b7092c Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Wed, 12 Oct 2022 13:56:08 +1300 >Subject: [PATCH 01/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >--- > source4/heimdal/lib/krb5/krb5_locl.h | 4 ---- > 1 file changed, 4 deletions(-) > >diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h >index 49c614d5efe..d3360c556ce 100644 >--- a/source4/heimdal/lib/krb5/krb5_locl.h >+++ b/source4/heimdal/lib/krb5/krb5_locl.h >@@ -188,10 +188,6 @@ struct _krb5_krb_auth_data; > #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) > #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0) > >-#ifndef __func__ >-#define __func__ "unknown-function" >-#endif >- > #define krb5_einval(context, argnum) _krb5_einval((context), __func__, (argnum)) > > #ifndef PATH_SEP >-- >2.25.1 > > >From 1a37e7d50b1b337f67bee0e5acf742b7d44277ef Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Wed, 12 Oct 2022 13:55:51 +1300 >Subject: [PATCH 02/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> > >[jsutton@samba.org Adapted to older wscript_build file] >--- > source4/heimdal_build/wscript_build | 14 ++++++++++---- > 1 file changed, 10 insertions(+), 4 deletions(-) > >diff --git a/source4/heimdal_build/wscript_build b/source4/heimdal_build/wscript_build >index e91c8ab2eeb..41152192798 100644 >--- a/source4/heimdal_build/wscript_build >+++ b/source4/heimdal_build/wscript_build >@@ -571,8 +571,8 @@ if not bld.CONFIG_SET("USING_SYSTEM_GSSAPI"): > HEIMDAL_AUTOPROTO_PRIVATE('lib/gssapi/krb5/gsskrb5-private.h', > HEIMDAL_GSSAPI_KRB5_SOURCE) > >- HEIMDAL_LIBRARY('gssapi', >- HEIMDAL_GSSAPI_SPNEGO_SOURCE + HEIMDAL_GSSAPI_KRB5_SOURCE + ''' >+ HEIMDAL_SUBSYSTEM('gssapi-subsystem', >+ HEIMDAL_GSSAPI_SPNEGO_SOURCE + HEIMDAL_GSSAPI_KRB5_SOURCE + ''' > lib/gssapi/mech/context.c lib/gssapi/mech/gss_krb5.c lib/gssapi/mech/gss_mech_switch.c > lib/gssapi/mech/gss_process_context_token.c lib/gssapi/mech/gss_buffer_set.c > lib/gssapi/mech/gss_aeap.c lib/gssapi/mech/gss_add_cred.c lib/gssapi/mech/gss_cred.c >@@ -597,10 +597,16 @@ if not bld.CONFIG_SET("USING_SYSTEM_GSSAPI"): > lib/gssapi/mech/gss_set_cred_option.c lib/gssapi/mech/gss_pseudo_random.c ../heimdal_build/gssapi-glue.c''', > includes='../heimdal/lib/gssapi ../heimdal/lib/gssapi/gssapi ../heimdal/lib/gssapi/spnego ../heimdal/lib/gssapi/krb5 ../heimdal/lib/gssapi/mech', > deps='hcrypto asn1 HEIMDAL_SPNEGO_ASN1 HEIMDAL_GSSAPI_ASN1 roken krb5 com_err wind heimbase', >- vnum='2.0.0', >- version_script='lib/gssapi/version-script.map', > ) > >+ HEIMDAL_LIBRARY('gssapi', >+ '', >+ includes='../heimdal/lib/gssapi ../heimdal/lib/gssapi/gssapi ../heimdal/lib/gssapi/spnego ../heimdal/lib/gssapi/krb5 ../heimdal/lib/gssapi/mech', >+ deps='gssapi-subsystem', >+ vnum='2.0.0', >+ version_script='lib/gssapi/version-script.map', >+ ) >+ > if not bld.CONFIG_SET("USING_SYSTEM_KRB5"): > # expand_path.c needs some of the install paths > HEIMDAL_SUBSYSTEM('HEIMDAL_CONFIG', >-- >2.25.1 > > >From 2d91e39a37f332eba66764a6e00da2f129b68a56 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Wed, 12 Oct 2022 13:55:39 +1300 >Subject: [PATCH 03/11] 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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >[jsutton@samba.org Adapted to lack of 'samba.unittests.auth.sam' test, > renamed 'third_party' to 'source4' in paths, defined > HEIMDAL_NORETURN_ATTRIBUTE and HEIMDAL_PRINTF_ATTRIBUTE to fix compiler > error] >--- > selftest/knownfail.d/heimdal-des-overflow | 9 + > selftest/tests.py | 5 + > source4/auth/tests/heimdal_unwrap_des.c | 1247 +++++++++++++++++++++ > source4/auth/wscript_build | 21 + > 4 files changed, 1282 insertions(+) > create mode 100644 selftest/knownfail.d/heimdal-des-overflow > create mode 100644 source4/auth/tests/heimdal_unwrap_des.c > >diff --git a/selftest/knownfail.d/heimdal-des-overflow b/selftest/knownfail.d/heimdal-des-overflow >new file mode 100644 >index 00000000000..23acbb43d31 >--- /dev/null >+++ b/selftest/knownfail.d/heimdal-des-overflow >@@ -0,0 +1,9 @@ >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_dce_style_missing_payload.none >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_dce_style_with_seal_missing_payload.none >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_missing_8_bytes.none >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_missing_payload.none >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_truncated_header_0.none >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_truncated_header_1.none >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_0.none >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_1.none >+^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_seal_missing_payload.none >diff --git a/selftest/tests.py b/selftest/tests.py >index c87b41c1a66..1331a6841e0 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") > if have_man_pages_support: >@@ -429,6 +431,9 @@ plantestsuite("samba.unittests.test_registry_regfio", "none", > [os.path.join(bindir(), "default/source3/test_registry_regfio")]) > plantestsuite("samba.unittests.test_oLschema2ldif", "none", > [os.path.join(bindir(), "default/source4/utils/oLschema2ldif/test_oLschema2ldif")]) >+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/source4/auth/tests/heimdal_unwrap_des.c b/source4/auth/tests/heimdal_unwrap_des.c >new file mode 100644 >index 00000000000..dc31e9d0ad1 >--- /dev/null >+++ b/source4/auth/tests/heimdal_unwrap_des.c >@@ -0,0 +1,1247 @@ >+/* >+ * Unit tests for source4/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" >+ >+#define HEIMDAL_NORETURN_ATTRIBUTE _NORETURN_ >+#define HEIMDAL_PRINTF_ATTRIBUTE(x) FORMAT_ATTRIBUTE(x) >+ >+#include "../../../source4/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); >+krb5_error_code __wrap_krb5_verify_checksum(krb5_context context, >+ krb5_crypto crypto, >+ krb5_key_usage usage, >+ void *data, >+ size_t len, >+ Checksum *cksum) >+{ >+ assert_ptr_equal(&dummy_crypto, crypto); >+ assert_int_equal(KRB5_KU_USAGE_SIGN, usage); >+ >+ assert_mem_in_valid_range(data, len); >+ >+ check_expected(len); >+ check_expected_ptr(data); >+ >+ assert_non_null(cksum); >+ assert_int_equal(CKSUMTYPE_HMAC_SHA1_DES3, cksum->cksumtype); >+ assert_int_equal(20, cksum->checksum.length); >+ check_expected_ptr(cksum->checksum.data); >+ >+ return 0; >+} >+ >+krb5_error_code __wrap_krb5_crypto_destroy(krb5_context context, >+ krb5_crypto crypto); >+krb5_error_code __wrap_krb5_crypto_destroy(krb5_context context, >+ krb5_crypto crypto) >+{ >+ assert_ptr_equal(&dummy_crypto, crypto); >+ >+ return 0; >+} >+ >+ >+int __wrap_der_get_length(const unsigned char *p, >+ size_t len, >+ size_t *val, >+ size_t *size); >+int __real_der_get_length(const unsigned char *p, >+ size_t len, >+ size_t *val, >+ size_t *size); >+int __wrap_der_get_length(const unsigned char *p, >+ size_t len, >+ size_t *val, >+ size_t *size) >+{ >+ assert_mem_in_valid_range(p, len); >+ >+ return __real_der_get_length(p, len, val, size); >+} >+ >+int __wrap_ct_memcmp(const volatile void * volatile p1, >+ const volatile void * volatile p2, >+ size_t len); >+int __real_ct_memcmp(const volatile void * volatile p1, >+ const volatile void * volatile p2, >+ size_t len); >+int __wrap_ct_memcmp(const volatile void * volatile p1, >+ const volatile void * volatile p2, >+ size_t len) >+{ >+ assert_mem_outside_invalid_range(p1, len); >+ assert_mem_outside_invalid_range(p2, len); >+ >+ return __real_ct_memcmp(p1, p2, len); >+} >+ >+void *__wrap_malloc(size_t size); >+void *__real_malloc(size_t size); >+void *__wrap_malloc(size_t size) >+{ >+ /* >+ * Ensure the length isn't excessively large (a symptom of integer >+ * underflow). >+ */ >+ assert_in_range(size, 0, 0x10000); >+ >+ return __real_malloc(size); >+} >+ >+/***************************************************************************** >+ * Mock implementations >+ *****************************************************************************/ >+ >+/* >+ * Set the globals used by the mocked functions to a known and consistent state >+ * >+ */ >+static void init_mock_results(TALLOC_CTX *mem_ctx) >+{ >+ dummy_key.keytype = KRB5_ENCTYPE_DES3_CBC_MD5; >+ dummy_key.keyvalue.data = NULL; >+ dummy_key.keyvalue.length = 0; >+ >+ dummy_crypto = (struct krb5_crypto_data) {0}; >+ >+ valid_range_begin = NULL; >+ valid_range_end = NULL; >+ invalid_range_end = NULL; >+} >+ >+/***************************************************************************** >+ * Unit test set up and tear down >+ *****************************************************************************/ >+ >+struct context { >+ gss_ctx_id_t context_handle; >+}; >+ >+static int setup(void **state) { >+ struct context *ctx = NULL; >+ krb5_context context = NULL; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ krb5_error_code code; >+ >+ ctx = talloc_zero(NULL, struct context); >+ assert_non_null(ctx); >+ >+ init_mock_results(ctx); >+ >+ code = _gsskrb5_init(&context); >+ assert_int_equal(0, code); >+ >+ major_status = _gsskrb5_create_ctx(&minor_status, >+ &ctx->context_handle, >+ context, >+ GSS_C_NO_CHANNEL_BINDINGS, >+ ACCEPTOR_START); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+ >+ *state = ctx; >+ return 0; >+} >+ >+static int teardown(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ >+ major_status = _gsskrb5_delete_sec_context(&minor_status, >+ &ctx->context_handle, >+ GSS_C_NO_BUFFER); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+ >+ TALLOC_FREE(ctx); >+ return 0; >+} >+ >+/***************************************************************************** >+ * _gsskrb5_unwrap unit tests >+ *****************************************************************************/ >+ >+static void test_unwrap_dce_style_missing_payload(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gsskrb5_ctx gss_ctx; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x37, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0xff, 0xff, /* SEAL_ALG (none) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 22); >+ >+ gss_ctx = (gsskrb5_ctx) ctx->context_handle; >+ gss_ctx->flags |= GSS_C_DCE_STYLE; >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_BAD_MECH, major_status); >+} >+ >+static void test_unwrap_dce_style_valid(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gsskrb5_ctx gss_ctx; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x37, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0xff, 0xff, /* SEAL_ALG (none) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ /* unused */ >+ 0xb8, 0xb9, 0xba, 0xbb, >+ 0xbc, 0xbd, 0xbe, >+ 0x00, /* padding byte */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 57); >+ >+ gss_ctx = (gsskrb5_ctx) ctx->context_handle; >+ gss_ctx->flags |= GSS_C_DCE_STYLE; >+ >+ expect_value(__wrap_krb5_decrypt_ivec, data, (uint8_t *)input.value + 21); >+ expect_memory(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN); >+ >+ expect_value(__wrap_krb5_verify_checksum, len, 16); >+ expect_value(__wrap_krb5_verify_checksum, data, (uint8_t *)input.value + 41); >+ expect_memory(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+ >+ assert_int_equal(0, conf_state); >+ assert_int_equal(GSS_C_QOP_DEFAULT, qop_state); >+ >+ assert_int_equal(output.length, 0); >+ >+ major_status = gss_release_buffer(&minor_status, &output); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+} >+ >+static void test_unwrap_dce_style_with_seal_missing_payload(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gsskrb5_ctx gss_ctx; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x37, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0x02, 0x00, /* SEAL_ALG (DES3-KD) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 22); >+ >+ gss_ctx = (gsskrb5_ctx) ctx->context_handle; >+ gss_ctx->flags |= GSS_C_DCE_STYLE; >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_BAD_MECH, major_status); >+} >+ >+static void test_unwrap_dce_style_with_seal_valid(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gsskrb5_ctx gss_ctx; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x37, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0x02, 0x00, /* SEAL_ALG (DES3-KD) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ /* unused */ >+ 0xb8, 0xb9, 0xba, 0xbb, >+ 0xbc, 0xbd, 0xbe, >+ 0x00, /* padding byte */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 57); >+ >+ gss_ctx = (gsskrb5_ctx) ctx->context_handle; >+ gss_ctx->flags |= GSS_C_DCE_STYLE; >+ >+ expect_value(__wrap_krb5_decrypt, len, 8); >+ expect_value(__wrap_krb5_decrypt, data, (uint8_t *)input.value + 49); >+ >+ expect_value(__wrap_krb5_decrypt_ivec, data, (uint8_t *)input.value + 21); >+ expect_memory(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN); >+ >+ expect_value(__wrap_krb5_verify_checksum, len, 16); >+ expect_value(__wrap_krb5_verify_checksum, data, (uint8_t *)input.value + 41); >+ expect_memory(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+ >+ assert_int_equal(1, conf_state); >+ assert_int_equal(GSS_C_QOP_DEFAULT, qop_state); >+ >+ assert_int_equal(output.length, 0); >+ >+ major_status = gss_release_buffer(&minor_status, &output); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+} >+ >+static void test_unwrap_missing_8_bytes(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x2f, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0xff, 0xff, /* SEAL_ALG (none) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0x00, /* padding byte */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 49); >+ >+ /* >+ * A fixed unwrap_des3() should fail before these wrappers are called, >+ * but we want the wrappers to have access to any required values in the >+ * event that they are called. Specifying WILL_RETURN_ONCE avoids a test >+ * failure if these values remain unused. >+ */ >+ expect_value_count(__wrap_krb5_decrypt_ivec, data, >+ (uint8_t *)input.value + 21, >+ WILL_RETURN_ONCE); >+ expect_memory_count(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN, >+ WILL_RETURN_ONCE); >+ >+ expect_value_count(__wrap_krb5_verify_checksum, len, 8, WILL_RETURN_ONCE); >+ expect_value_count(__wrap_krb5_verify_checksum, data, >+ (uint8_t *)input.value + 41, >+ WILL_RETURN_ONCE); >+ expect_memory_count(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20, >+ WILL_RETURN_ONCE); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_BAD_MECH, major_status); >+} >+ >+static void test_unwrap_missing_payload(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x14, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0xff, 0xff, /* SEAL_ALG (none) */ >+ 0xff, 0xff, /* Filler */ >+ 0x00, 0xa1, 0xa2, 0xa3, /* padding byte / encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 22); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_BAD_MECH, major_status); >+} >+ >+static void test_unwrap_truncated_header_0(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x00, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 2); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_DEFECTIVE_TOKEN, major_status); >+} >+ >+static void test_unwrap_truncated_header_1(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x02, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, /* GSS KRB5 mech */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 4); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_BAD_MECH, major_status); >+} >+ >+static void test_unwrap_valid(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x37, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0xff, 0xff, /* SEAL_ALG (none) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ /* unused */ >+ 0xb8, 0xb9, 0xba, 0xbb, >+ 0xbc, 0xbd, 0xbe, >+ 0x00, /* padding byte */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 57); >+ >+ expect_value(__wrap_krb5_decrypt_ivec, data, (uint8_t *)input.value + 21); >+ expect_memory(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN); >+ >+ expect_value(__wrap_krb5_verify_checksum, len, 16); >+ expect_value(__wrap_krb5_verify_checksum, data, (uint8_t *)input.value + 41); >+ expect_memory(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+ >+ assert_int_equal(0, conf_state); >+ assert_int_equal(GSS_C_QOP_DEFAULT, qop_state); >+ >+ assert_int_equal(output.length, 0); >+ >+ major_status = gss_release_buffer(&minor_status, &output); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+} >+ >+static void test_unwrap_with_padding_truncated_0(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x37, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0xff, 0xff, /* SEAL_ALG (none) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ /* unused */ >+ 0xb8, 0xb9, 0xba, 0xbb, >+ 0x04, 0x04, 0x04, 0x04, /* padding bytes */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 57); >+ >+ /* >+ * A fixed unwrap_des3() should fail before these wrappers are called, >+ * but we want the wrappers to have access to any required values in the >+ * event that they are called. Specifying WILL_RETURN_ONCE avoids a test >+ * failure if these values remain unused. >+ */ >+ expect_value_count(__wrap_krb5_decrypt_ivec, data, >+ (uint8_t *)input.value + 21, >+ WILL_RETURN_ONCE); >+ expect_memory_count(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN, >+ WILL_RETURN_ONCE); >+ >+ expect_value_count(__wrap_krb5_verify_checksum, len, 16, WILL_RETURN_ONCE); >+ expect_value_count(__wrap_krb5_verify_checksum, data, >+ (uint8_t *)input.value + 41, >+ WILL_RETURN_ONCE); >+ expect_memory_count(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20, >+ WILL_RETURN_ONCE); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_BAD_MECH, major_status); >+} >+ >+static void test_unwrap_with_padding_truncated_1(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x37, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0xff, 0xff, /* SEAL_ALG (none) */ >+ 0xff, 0xff, /* Filler */ >+ 0x00, 0xa1, 0xa2, 0xa3, /* padding byte / encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ /* padding bytes */ >+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 57); >+ >+ /* >+ * A fixed unwrap_des3() should fail before these wrappers are called, >+ * but we want the wrappers to have access to any required values in the >+ * event that they are called. Specifying WILL_RETURN_ONCE avoids a test >+ * failure if these values remain unused. >+ */ >+ expect_value_count(__wrap_krb5_decrypt_ivec, data, >+ (uint8_t *)input.value + 21, >+ WILL_RETURN_ONCE); >+ expect_memory_count(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN, >+ WILL_RETURN_ONCE); >+ >+ expect_value_count(__wrap_krb5_verify_checksum, len, 16, WILL_RETURN_ONCE); >+ expect_value_count(__wrap_krb5_verify_checksum, data, >+ (uint8_t *)input.value + 41, >+ WILL_RETURN_ONCE); >+ expect_memory_count(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20, >+ WILL_RETURN_ONCE); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_BAD_MECH, major_status); >+} >+ >+static void test_unwrap_with_padding_valid(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x3f, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0xff, 0xff, /* SEAL_ALG (none) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ /* unused */ >+ 0xb8, 0xb9, 0xba, 0xbb, >+ 0xbc, 0xbd, 0xbe, 0xbf, >+ /* padding bytes */ >+ 0x08, 0x08, 0x08, 0x08, >+ 0x08, 0x08, 0x08, 0x08, >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 65); >+ >+ expect_value(__wrap_krb5_decrypt_ivec, data, (uint8_t *)input.value + 21); >+ expect_memory(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN); >+ >+ expect_value(__wrap_krb5_verify_checksum, len, 24); >+ expect_value(__wrap_krb5_verify_checksum, data, (uint8_t *)input.value + 41); >+ expect_memory(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+ >+ assert_int_equal(0, conf_state); >+ assert_int_equal(GSS_C_QOP_DEFAULT, qop_state); >+ >+ assert_int_equal(output.length, 0); >+ >+ major_status = gss_release_buffer(&minor_status, &output); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+} >+ >+static void test_unwrap_with_seal_empty_token_valid(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x37, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0x02, 0x00, /* SEAL_ALG (DES3-KD) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ /* unused */ >+ 0xb8, 0xb9, 0xba, 0xbb, >+ 0xbc, 0xbd, 0xbe, >+ 0x00, /* padding byte */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 57); >+ >+ expect_value(__wrap_krb5_decrypt, len, 8); >+ expect_value(__wrap_krb5_decrypt, data, (uint8_t *)input.value + 49); >+ >+ expect_value(__wrap_krb5_decrypt_ivec, data, (uint8_t *)input.value + 21); >+ expect_memory(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN); >+ >+ expect_value(__wrap_krb5_verify_checksum, len, 16); >+ expect_value(__wrap_krb5_verify_checksum, data, (uint8_t *)input.value + 41); >+ expect_memory(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+ >+ assert_int_equal(1, conf_state); >+ assert_int_equal(GSS_C_QOP_DEFAULT, qop_state); >+ >+ assert_int_equal(output.length, 0); >+ >+ major_status = gss_release_buffer(&minor_status, &output); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+} >+ >+static void test_unwrap_with_seal_missing_payload(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x14, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0x02, 0x00, /* SEAL_ALG (DES3-KD) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 22); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_BAD_MECH, major_status); >+} >+ >+static void test_unwrap_with_seal_valid(void **state) { >+ struct context *ctx = *state; >+ OM_uint32 major_status; >+ OM_uint32 minor_status; >+ gss_buffer_desc input = {0}; >+ gss_buffer_desc output = {0}; >+ int conf_state; >+ gss_qop_t qop_state; >+ >+ /* See RFC 1964 for token format. */ >+ static const uint8_t data[] = { >+ 0x60, /* ASN.1 Application tag */ >+ 0x3e, /* total length */ >+ 0x06, /* OBJECT IDENTIFIER */ >+ 0x09, /* mech length */ >+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x01, 0x02, 0x02, /* GSS KRB5 mech */ >+ 0x02, 0x01, /* TOK_ID */ >+ 0x04, 0x00, /* SGN_ALG (HMAC SHA1 DES3-KD) */ >+ 0x02, 0x00, /* SEAL_ALG (DES3-KD) */ >+ 0xff, 0xff, /* Filler */ >+ 0xa0, 0xa1, 0xa2, 0xa3, /* encrypted sequence number */ >+ 0x00, 0x00, 0x00, 0x00, /* sequence number direction (remote) */ >+ /* checksum */ >+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, >+ 0xa9, 0xaa, 0xab, 0xac, 0xad, >+ 0xae, 0xaf, 0xb0, 0xb1, 0xb2, >+ 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, >+ /* unused */ >+ 0xb8, 0xb9, 0xba, 0xbb, >+ 0xbc, 0xbd, 0xbe, 0xbf, >+ 0xc0, 0xc1, 0xc2, 0xc3, >+ 0xc4, 0xc5, >+ 0x00, /* padding byte */ >+ }; >+ >+ input = get_input_buffer(ctx, data, sizeof(data), 64); >+ >+ expect_value(__wrap_krb5_decrypt, len, 15); >+ expect_value(__wrap_krb5_decrypt, data, (uint8_t *)input.value + 49); >+ >+ expect_value(__wrap_krb5_decrypt_ivec, data, (uint8_t *)input.value + 21); >+ expect_memory(__wrap_krb5_decrypt_ivec, ivec, >+ (uint8_t *)input.value + 29, DES_CBLOCK_LEN); >+ >+ expect_value(__wrap_krb5_verify_checksum, len, 23); >+ expect_value(__wrap_krb5_verify_checksum, data, (uint8_t *)input.value + 41); >+ expect_memory(__wrap_krb5_verify_checksum, cksum->checksum.data, >+ (uint8_t *)input.value + 29, 20); >+ >+ major_status = _gsskrb5_unwrap(&minor_status, >+ ctx->context_handle, >+ &input, >+ &output, >+ &conf_state, >+ &qop_state); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+ >+ assert_int_equal(1, conf_state); >+ assert_int_equal(GSS_C_QOP_DEFAULT, qop_state); >+ >+ assert_int_equal(output.length, 7); >+ assert_memory_equal((uint8_t *)input.value + 57, output.value, output.length); >+ >+ major_status = gss_release_buffer(&minor_status, &output); >+ assert_int_equal(GSS_S_COMPLETE, major_status); >+} >+ >+int main(int argc, const char **argv) >+{ >+ static const struct CMUnitTest tests[] = { >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_dce_style_missing_payload, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_dce_style_valid, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_dce_style_with_seal_missing_payload, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_dce_style_with_seal_valid, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_missing_8_bytes, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_missing_payload, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_truncated_header_0, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_truncated_header_1, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_valid, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_with_padding_truncated_0, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_with_padding_truncated_1, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_with_padding_valid, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_with_seal_empty_token_valid, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_with_seal_missing_payload, setup, teardown), >+ cmocka_unit_test_setup_teardown( >+ test_unwrap_with_seal_valid, setup, teardown), >+ }; >+ >+ cmocka_set_message_output(CM_OUTPUT_SUBUNIT); >+ return cmocka_run_group_tests(tests, NULL, NULL); >+} >diff --git a/source4/auth/wscript_build b/source4/auth/wscript_build >index 381a7b19bf0..01b2f280609 100644 >--- a/source4/auth/wscript_build >+++ b/source4/auth/wscript_build >@@ -49,6 +49,27 @@ bld.SAMBA_BINARY('test_kerberos', > for_selftest=True > ) > >+bld.SAMBA_BINARY('test_heimdal_gensec_unwrap_des', >+ source='tests/heimdal_unwrap_des.c', >+ deps='cmocka talloc gssapi-subsystem', >+ local_include=False, >+ for_selftest=True, >+ enabled=(bld.CONFIG_SET('SAMBA4_USES_HEIMDAL') and >+ not bld.CONFIG_SET('USING_SYSTEM_GSSAPI')), >+ ldflags=''' >+ -Wl,--wrap,ct_memcmp >+ -Wl,--wrap,der_get_length >+ -Wl,--wrap,krb5_auth_con_getlocalsubkey >+ -Wl,--wrap,krb5_crypto_destroy >+ -Wl,--wrap,krb5_crypto_init >+ -Wl,--wrap,krb5_decrypt >+ -Wl,--wrap,krb5_decrypt_ivec >+ -Wl,--wrap,krb5_free_keyblock >+ -Wl,--wrap,krb5_verify_checksum >+ -Wl,--wrap,malloc >+ ''' >+) >+ > pytalloc_util = bld.pyembed_libname('pytalloc-util') > pyparam_util = bld.pyembed_libname('pyparam_util') > pyldb_util = bld.pyembed_libname('pyldb-util') >-- >2.25.1 > > >From 7e3f64bfc4f9526cba58c263e3adca51c52eb495 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Wed, 12 Oct 2022 13:57:13 +1300 >Subject: [PATCH 04/11] CVE-2022-3437 source4/heimdal: Use constant-time > memcmp() for arcfour unwrap > >BUG: https://bugzilla.samba.org/show_bug.cgi?id=15134 > >Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> > >[jsutton@samba.org Adapted to small differences in comparisons, and > removed erroneous duplicate code in conflicting region] >--- > source4/heimdal/lib/gssapi/krb5/arcfour.c | 24 +++++++---------------- > 1 file changed, 7 insertions(+), 17 deletions(-) > >diff --git a/source4/heimdal/lib/gssapi/krb5/arcfour.c b/source4/heimdal/lib/gssapi/krb5/arcfour.c >index a61f7686e95..c6b317ff683 100644 >--- a/source4/heimdal/lib/gssapi/krb5/arcfour.c >+++ b/source4/heimdal/lib/gssapi/krb5/arcfour.c >@@ -385,9 +385,9 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, > _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); > > if (context_handle->more_flags & LOCAL) >- cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); >+ cmp = ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); > else >- cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); >+ cmp = ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); > > memset(SND_SEQ, 0, sizeof(SND_SEQ)); > if (cmp != 0) { >@@ -656,9 +656,9 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, > _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); > > if (context_handle->more_flags & LOCAL) >- cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); >+ cmp = ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); > else >- cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); >+ cmp = ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4); > > if (cmp != 0) { > *minor_status = 0; >@@ -1266,19 +1266,9 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, > _gsskrb5_decode_be_om_uint32(snd_seq, &seq_number); > > if (ctx->more_flags & LOCAL) { >- cmp = memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4); >+ cmp = ct_memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4); > } else { >- cmp = memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4); >- } >- if (cmp != 0) { >- *minor_status = 0; >- return GSS_S_BAD_MIC; >- } >- >- if (ctx->more_flags & LOCAL) { >- cmp = memcmp(&snd_seq[4], "\xff\xff\xff\xff", 4); >- } else { >- cmp = memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4); >+ cmp = ct_memcmp(&snd_seq[4], "\x00\x00\x00\x00", 4); > } > if (cmp != 0) { > *minor_status = 0; >@@ -1353,7 +1343,7 @@ _gssapi_unwrap_iov_arcfour(OM_uint32 *minor_status, > return GSS_S_FAILURE; > } > >- cmp = memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ >+ cmp = ct_memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ > if (cmp != 0) { > *minor_status = 0; > return GSS_S_BAD_MIC; >-- >2.25.1 > > >From 28f0174d628b6918286ebe582a0b635db1206a70 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Wed, 12 Oct 2022 13:57:55 +1300 >Subject: [PATCH 05/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >--- > source4/heimdal/lib/gssapi/krb5/unwrap.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > >diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c >index b3da35ee9e2..7111a7944fe 100644 >--- a/source4/heimdal/lib/gssapi/krb5/unwrap.c >+++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c >@@ -227,7 +227,7 @@ unwrap_des3 > if (ret) > return ret; > >- if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ >+ if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ > return GSS_S_BAD_SIG; > p += 2; > if (ct_memcmp (p, "\x02\x00", 2) == 0) { >-- >2.25.1 > > >From 88f4c032746b24d423008a77b0727334c89098ec Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Wed, 12 Oct 2022 13:57:42 +1300 >Subject: [PATCH 06/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >--- > source4/heimdal/lib/gssapi/krb5/unwrap.c | 14 ++++++++------ > 1 file changed, 8 insertions(+), 6 deletions(-) > >diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c >index 7111a7944fe..9639091cb3a 100644 >--- a/source4/heimdal/lib/gssapi/krb5/unwrap.c >+++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c >@@ -180,9 +180,10 @@ unwrap_des > output_message_buffer->value = malloc(output_message_buffer->length); > if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) > return GSS_S_FAILURE; >- memcpy (output_message_buffer->value, >- p + 24, >- output_message_buffer->length); >+ if (output_message_buffer->value != NULL) >+ memcpy (output_message_buffer->value, >+ p + 24, >+ output_message_buffer->length); > return GSS_S_COMPLETE; > } > #endif >@@ -374,9 +375,10 @@ unwrap_des3 > output_message_buffer->value = malloc(output_message_buffer->length); > if(output_message_buffer->length != 0 && output_message_buffer->value == NULL) > return GSS_S_FAILURE; >- memcpy (output_message_buffer->value, >- p + 36, >- output_message_buffer->length); >+ if (output_message_buffer->value != NULL) >+ memcpy (output_message_buffer->value, >+ p + 36, >+ output_message_buffer->length); > return GSS_S_COMPLETE; > } > >-- >2.25.1 > > >From b377426b14090fa893b6709bb282c3fa35dc93fe Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Mon, 15 Aug 2022 16:53:45 +1200 >Subject: [PATCH 07/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >--- > source4/heimdal/lib/gssapi/krb5/decapsulate.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > >diff --git a/source4/heimdal/lib/gssapi/krb5/decapsulate.c b/source4/heimdal/lib/gssapi/krb5/decapsulate.c >index 86085f56950..4e3fcd659e9 100644 >--- a/source4/heimdal/lib/gssapi/krb5/decapsulate.c >+++ b/source4/heimdal/lib/gssapi/krb5/decapsulate.c >@@ -193,13 +193,13 @@ _gssapi_verify_pad(gss_buffer_t wrapped_token, > if (wrapped_token->length < 1) > return GSS_S_BAD_MECH; > >- pad = (u_char *)wrapped_token->value + wrapped_token->length - 1; >- padlength = *pad; >+ pad = (u_char *)wrapped_token->value + wrapped_token->length; >+ padlength = pad[-1]; > > if (padlength > datalen) > return GSS_S_BAD_MECH; > >- for (i = padlength; i > 0 && *pad == padlength; i--, pad--) >+ for (i = padlength; i > 0 && *--pad == padlength; i--) > ; > if (i != 0) > return GSS_S_BAD_MIC; >-- >2.25.1 > > >From a1a2e4e60706ae6cdb8d913a5499f449ffd9e9f9 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Mon, 15 Aug 2022 16:53:55 +1200 >Subject: [PATCH 08/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >--- > selftest/knownfail.d/heimdal-des-overflow | 1 - > source4/heimdal/lib/gssapi/krb5/decapsulate.c | 4 ++++ > 2 files changed, 4 insertions(+), 1 deletion(-) > >diff --git a/selftest/knownfail.d/heimdal-des-overflow b/selftest/knownfail.d/heimdal-des-overflow >index 23acbb43d31..68b304530db 100644 >--- a/selftest/knownfail.d/heimdal-des-overflow >+++ b/selftest/knownfail.d/heimdal-des-overflow >@@ -3,7 +3,6 @@ > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_missing_8_bytes.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_missing_payload.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_truncated_header_0.none >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_truncated_header_1.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_0.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_1.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_seal_missing_payload.none >diff --git a/source4/heimdal/lib/gssapi/krb5/decapsulate.c b/source4/heimdal/lib/gssapi/krb5/decapsulate.c >index 4e3fcd659e9..031a621eabc 100644 >--- a/source4/heimdal/lib/gssapi/krb5/decapsulate.c >+++ b/source4/heimdal/lib/gssapi/krb5/decapsulate.c >@@ -80,6 +80,10 @@ _gssapi_verify_mech_header(u_char **str, > > if (mech_len != mech->length) > return GSS_S_BAD_MECH; >+ if (mech_len > total_len) >+ return GSS_S_BAD_MECH; >+ if (p - *str > total_len - mech_len) >+ return GSS_S_BAD_MECH; > if (ct_memcmp(p, > mech->elements, > mech->length) != 0) >-- >2.25.1 > > >From 81aa25a26e7154cbaa8f947a8464856f59d31d24 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Mon, 15 Aug 2022 16:54:23 +1200 >Subject: [PATCH 09/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >--- > selftest/knownfail.d/heimdal-des-overflow | 5 ----- > source4/heimdal/lib/gssapi/krb5/unwrap.c | 14 ++++++++++++++ > 2 files changed, 14 insertions(+), 5 deletions(-) > >diff --git a/selftest/knownfail.d/heimdal-des-overflow b/selftest/knownfail.d/heimdal-des-overflow >index 68b304530db..94a49bbee7f 100644 >--- a/selftest/knownfail.d/heimdal-des-overflow >+++ b/selftest/knownfail.d/heimdal-des-overflow >@@ -1,8 +1,3 @@ >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_dce_style_missing_payload.none >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_dce_style_with_seal_missing_payload.none >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_missing_8_bytes.none >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_missing_payload.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_truncated_header_0.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_0.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_1.none >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_seal_missing_payload.none >diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c >index 9639091cb3a..70d26a75ccf 100644 >--- a/source4/heimdal/lib/gssapi/krb5/unwrap.c >+++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c >@@ -64,6 +64,8 @@ unwrap_des > > if (IS_DCE_STYLE(context_handle)) { > token_len = 22 + 8 + 15; /* 45 */ >+ if (input_message_buffer->length < token_len) >+ return GSS_S_BAD_MECH; > } else { > token_len = input_message_buffer->length; > } >@@ -76,6 +78,11 @@ unwrap_des > if (ret) > return ret; > >+ len = (p - (u_char *)input_message_buffer->value) >+ + 22 + 8; >+ if (input_message_buffer->length < len) >+ return GSS_S_BAD_MECH; >+ > if (memcmp (p, "\x00\x00", 2) != 0) > return GSS_S_BAD_SIG; > p += 2; >@@ -216,6 +223,8 @@ unwrap_des3 > > if (IS_DCE_STYLE(context_handle)) { > token_len = 34 + 8 + 15; /* 57 */ >+ if (input_message_buffer->length < token_len) >+ return GSS_S_BAD_MECH; > } else { > token_len = input_message_buffer->length; > } >@@ -228,6 +237,11 @@ unwrap_des3 > if (ret) > return ret; > >+ len = (p - (u_char *)input_message_buffer->value) >+ + 34 + 8; >+ if (input_message_buffer->length < len) >+ return GSS_S_BAD_MECH; >+ > if (ct_memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */ > return GSS_S_BAD_SIG; > p += 2; >-- >2.25.1 > > >From ec0d97d3002e9abcab4d65d63e911f38d1294168 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Mon, 10 Oct 2022 20:33:09 +1300 >Subject: [PATCH 10/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >--- > selftest/knownfail.d/heimdal-des-overflow | 1 - > source4/heimdal/lib/gssapi/krb5/decapsulate.c | 2 ++ > 2 files changed, 2 insertions(+), 1 deletion(-) > >diff --git a/selftest/knownfail.d/heimdal-des-overflow b/selftest/knownfail.d/heimdal-des-overflow >index 94a49bbee7f..a7416dc61d9 100644 >--- a/selftest/knownfail.d/heimdal-des-overflow >+++ b/selftest/knownfail.d/heimdal-des-overflow >@@ -1,3 +1,2 @@ >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_truncated_header_0.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_0.none > ^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_1.none >diff --git a/source4/heimdal/lib/gssapi/krb5/decapsulate.c b/source4/heimdal/lib/gssapi/krb5/decapsulate.c >index 031a621eabc..d7b75a64222 100644 >--- a/source4/heimdal/lib/gssapi/krb5/decapsulate.c >+++ b/source4/heimdal/lib/gssapi/krb5/decapsulate.c >@@ -54,6 +54,8 @@ _gsskrb5_get_mech (const u_char *ptr, > e = der_get_length (p, total_len - 1, &len, &len_len); > if (e || 1 + len_len + len != total_len) > return -1; >+ if (total_len < 1 + len_len + 1) >+ return -1; > p += len_len; > if (*p++ != 0x06) > return -1; >-- >2.25.1 > > >From 1c04833dff52d0733eae9da7282e2a2a520e8418 Mon Sep 17 00:00:00 2001 >From: Joseph Sutton <josephsutton@catalyst.net.nz> >Date: Wed, 12 Oct 2022 13:57:33 +1300 >Subject: [PATCH 11/11] CVE-2022-3437 source4/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@catalyst.net.nz> >Reviewed-by: Andrew Bartlett <abartlet@samba.org> >--- > selftest/knownfail.d/heimdal-des-overflow | 2 -- > source4/heimdal/lib/gssapi/krb5/unwrap.c | 4 ++-- > 2 files changed, 2 insertions(+), 4 deletions(-) > delete mode 100644 selftest/knownfail.d/heimdal-des-overflow > >diff --git a/selftest/knownfail.d/heimdal-des-overflow b/selftest/knownfail.d/heimdal-des-overflow >deleted file mode 100644 >index a7416dc61d9..00000000000 >--- a/selftest/knownfail.d/heimdal-des-overflow >+++ /dev/null >@@ -1,2 +0,0 @@ >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_0.none >-^samba.unittests.auth.heimdal_gensec_unwrap_des.test_unwrap_with_padding_truncated_1.none >diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c >index 70d26a75ccf..ed8f7d78ffa 100644 >--- a/source4/heimdal/lib/gssapi/krb5/unwrap.c >+++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c >@@ -124,7 +124,7 @@ unwrap_des > } else { > /* check pad */ > ret = _gssapi_verify_pad(input_message_buffer, >- input_message_buffer->length - len, >+ input_message_buffer->length - len - 8, > &padlength); > if (ret) > return ret; >@@ -289,7 +289,7 @@ unwrap_des3 > } else { > /* check pad */ > ret = _gssapi_verify_pad(input_message_buffer, >- input_message_buffer->length - len, >+ input_message_buffer->length - len - 8, > &padlength); > if (ret) > return ret; >-- >2.25.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Flags:
jsutton
:
review+
abartlet
:
ci-passed+
Actions:
View
Attachments on
bug 15134
:
17455
|
17474
|
17539
|
17540
|
17541
|
17542
|
17543
|
17549
|
17550
|
17551
|
17552
|
17553
|
17554
|
17555
|
17556
|
17557
|
17558
| 17559 |
17561
|
17564
|
17577
|
17598