diff --git a/backport-0001-CVE-2022-3437.patch b/backport-0001-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..af5c103318ae8a7058e2ca8b133ed1f2f450979e --- /dev/null +++ b/backport-0001-CVE-2022-3437.patch @@ -0,0 +1,39 @@ +From fe1204d9da2c6f761c4dc4421f67057b10eaf430 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 12 Oct 2022 13:56:08 +1300 +Subject: [PATCH 05/15] 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 +Reviewed-by: Andrew Bartlett + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0002-CVE-2022-3437.patch b/backport-0002-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..2c2a2e744dc98fb5995bc068fda3d6103d4110aa --- /dev/null +++ b/backport-0002-CVE-2022-3437.patch @@ -0,0 +1,58 @@ +From a49a3ac8e082921c2793a073b5991c4693f167ab Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 12 Oct 2022 13:55:51 +1300 +Subject: [PATCH 06/15] 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 +Reviewed-by: Andrew Bartlett + +[jsutton@samba.org Adapted to older wscript_build file] + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0003-CVE-2022-3437.patch b/backport-0003-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..ccc5abd698e6910245520d3c1cb2c10874bef314 --- /dev/null +++ b/backport-0003-CVE-2022-3437.patch @@ -0,0 +1,1351 @@ +From 310bffc085514f9ceba5b3501ddef15807c53809 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 12 Oct 2022 13:55:39 +1300 +Subject: [PATCH 07/15] 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 +Reviewed-by: Andrew Bartlett +[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] + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 . ++ * ++ */ ++ ++/* ++ * from cmocka.c: ++ * These headers or their equivalents should be included prior to ++ * including ++ * this header file. ++ * ++ * #include ++ * #include ++ * #include ++ * ++ * This allows test applications to use custom definitions of C standard ++ * library functions and types. ++ * ++ */ ++ ++#include ++#include ++#include ++ ++#include ++ ++#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 diff --git a/backport-0004-CVE-2022-3437.patch b/backport-0004-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..f91795b0f26023acb8e4f7688181bd8848b20dcf --- /dev/null +++ b/backport-0004-CVE-2022-3437.patch @@ -0,0 +1,81 @@ +From c22914f845b3eba1c9ad444333f3d044352b7e2c Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 12 Oct 2022 13:57:13 +1300 +Subject: [PATCH 08/15] 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 +Reviewed-by: Andrew Bartlett + +[jsutton@samba.org Adapted to small differences in comparisons, and + removed erroneous duplicate code in conflicting region] + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0005-CVE-2022-3437.patch b/backport-0005-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..c5f3ba6f550907f110f04b8f6af8d5e0705628b7 --- /dev/null +++ b/backport-0005-CVE-2022-3437.patch @@ -0,0 +1,35 @@ +From 5f6dbf2ab29bcd30c701cab3daecf5a6a53a44cd Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 12 Oct 2022 13:57:55 +1300 +Subject: [PATCH 09/15] 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 +Reviewed-by: Andrew Bartlett + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0006-CVE-2022-3437.patch b/backport-0006-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..4af5b9c73de9e54397364a17d75eeca805f8f979 --- /dev/null +++ b/backport-0006-CVE-2022-3437.patch @@ -0,0 +1,51 @@ +From 9f6f1e01aca4f00a5d23127803c81939253e0577 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 12 Oct 2022 13:57:42 +1300 +Subject: [PATCH 10/15] 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 +Reviewed-by: Andrew Bartlett + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0007-CVE-2022-3437.patch b/backport-0007-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..ae786f85a3fb174a761e2532bf5663d298c3cd78 --- /dev/null +++ b/backport-0007-CVE-2022-3437.patch @@ -0,0 +1,57 @@ +From 5a62eb5734d50fe556934aefa3bac5698372f00e Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 15 Aug 2022 16:53:45 +1200 +Subject: [PATCH 11/15] 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 +Reviewed-by: Andrew Bartlett + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0008-CVE-2022-3437.patch b/backport-0008-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..9e7161bc88d21b9f2345fee4a4f4686a0971896d --- /dev/null +++ b/backport-0008-CVE-2022-3437.patch @@ -0,0 +1,50 @@ +From ebac8bf0478e19849f83af6d44b73d7ab3afd25b Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 15 Aug 2022 16:53:55 +1200 +Subject: [PATCH 12/15] 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 +Reviewed-by: Andrew Bartlett + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0009-CVE-2022-3437.patch b/backport-0009-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..afbd04478d1e2736a2ebdaf6443f477ad85d4a7f --- /dev/null +++ b/backport-0009-CVE-2022-3437.patch @@ -0,0 +1,79 @@ +From 1aca34515515f2cb00fbf5ad8b9212b319f01836 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 15 Aug 2022 16:54:23 +1200 +Subject: [PATCH 13/15] 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 +Reviewed-by: Andrew Bartlett + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0010-CVE-2022-3437.patch b/backport-0010-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..f13cb9ef9b6295ed22f8a8c8fefddc0d12527243 --- /dev/null +++ b/backport-0010-CVE-2022-3437.patch @@ -0,0 +1,48 @@ +From 77e0f2febaaf4d6e5e42f8e73a1f8f3c0e4a2985 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Mon, 10 Oct 2022 20:33:09 +1300 +Subject: [PATCH 14/15] 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 +Reviewed-by: Andrew Bartlett + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/backport-0011-CVE-2022-3437.patch b/backport-0011-CVE-2022-3437.patch new file mode 100644 index 0000000000000000000000000000000000000000..ce643fe4877a7d385c3fe00916fbab075d821574 --- /dev/null +++ b/backport-0011-CVE-2022-3437.patch @@ -0,0 +1,58 @@ +From e9db03736007721e37c4fba847ce4aa0c4520924 Mon Sep 17 00:00:00 2001 +From: Joseph Sutton +Date: Wed, 12 Oct 2022 13:57:33 +1300 +Subject: [PATCH 15/15] 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 +Reviewed-by: Andrew Bartlett + +Conflict: NA +Reference: https://download.samba.org/pub/samba/patches/security/samba-4.15.11-security-2022-10-25.patch +--- + 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 diff --git a/samba.spec b/samba.spec index 2324fb8cb7eb4a39c8637d0f0d7472a3e73d5425..d0ae6a565f8a810b774d61b258c1708a14fba024 100644 --- a/samba.spec +++ b/samba.spec @@ -48,7 +48,7 @@ Name: samba Version: 4.15.3 -Release: 11 +Release: 12 Summary: A suite for Linux to interoperate with Windows License: GPLv3+ and LGPLv3+ @@ -94,6 +94,17 @@ Patch25: 0014-CVE-2022-32743-s4-rpc_server-common-Add-dcesrv_samdb.patch Patch26: 0015-CVE-2022-32743-s4-rpc_server-netlogon-Reconnect-to-s.patch Patch27: backport-0001-CVE-2022-1615-util-genrand-don-t-ignore-errors-in-random-number-ge.patch Patch28: backport-0002-CVE-2022-1615-py-uptodateness-more-details-in-missing-dn-report.patch +Patch29: backport-0001-CVE-2022-3437.patch +Patch30: backport-0002-CVE-2022-3437.patch +Patch31: backport-0003-CVE-2022-3437.patch +Patch32: backport-0004-CVE-2022-3437.patch +Patch33: backport-0005-CVE-2022-3437.patch +Patch34: backport-0006-CVE-2022-3437.patch +Patch35: backport-0007-CVE-2022-3437.patch +Patch36: backport-0008-CVE-2022-3437.patch +Patch37: backport-0009-CVE-2022-3437.patch +Patch38: backport-0010-CVE-2022-3437.patch +Patch39: backport-0011-CVE-2022-3437.patch BuildRequires: avahi-devel bison dbus-devel docbook-style-xsl e2fsprogs-devel flex gawk gnupg2 gnutls-devel >= 3.4.7 gpgme-devel BuildRequires: jansson-devel krb5-devel >= %{required_mit_krb5} libacl-devel libaio-devel libarchive-devel libattr-devel @@ -3417,6 +3428,12 @@ fi %endif %changelog +* Wed Oct 26 2022 xinghe - 4.15.3-12 +- Type:cves +- ID:CVE-2022-3437 +- SUG:NA +- DESC:fix CVE-2022-3437 + * Thu Sep 29 2022 xinghe - 4.15.3-11 - Type:bugfix - ID:NA