summaryrefslogtreecommitdiffstats
path: root/source4/auth/tests
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth/tests')
-rw-r--r--source4/auth/tests/heimdal_unwrap_des.c1244
-rw-r--r--source4/auth/tests/kerberos.c123
-rw-r--r--source4/auth/tests/sam.c2746
3 files changed, 4113 insertions, 0 deletions
diff --git a/source4/auth/tests/heimdal_unwrap_des.c b/source4/auth/tests/heimdal_unwrap_des.c
new file mode 100644
index 0000000..fbfe778
--- /dev/null
+++ b/source4/auth/tests/heimdal_unwrap_des.c
@@ -0,0 +1,1244 @@
+/*
+ * Unit tests for third_party/heimdal/lib/gssapi/krb5/unwrap.c
+ *
+ * Copyright (C) Catalyst.NET Ltd 2022
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/*
+ * from cmocka.c:
+ * These headers or their equivalents should be included prior to
+ * including
+ * this header file.
+ *
+ * #include <stdarg.h>
+ * #include <stddef.h>
+ * #include <setjmp.h>
+ *
+ * This allows test applications to use custom definitions of C standard
+ * library functions and types.
+ *
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+
+#include <cmocka.h>
+
+#include "includes.h"
+#include "replace.h"
+
+#include "../../../third_party/heimdal/lib/gssapi/gssapi/gssapi.h"
+#include "gsskrb5_locl.h"
+
+/******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+
+const uint8_t *valid_range_begin;
+const uint8_t *valid_range_end;
+const uint8_t *invalid_range_end;
+
+/*
+ * 'array_len' is the size of the passed in array. 'buffer_len' is the size to
+ * report in the resulting buffer.
+ */
+static const gss_buffer_desc get_input_buffer(TALLOC_CTX *mem_ctx,
+ const uint8_t array[],
+ const size_t array_len,
+ const size_t buffer_len)
+{
+ gss_buffer_desc buf;
+
+ /* Add some padding to catch invalid memory accesses. */
+ const size_t padding = 0x100;
+ const size_t padded_len = array_len + padding;
+
+ uint8_t *data = talloc_size(mem_ctx, padded_len);
+ assert_non_null(data);
+
+ memcpy(data, array, array_len);
+ memset(data + array_len, 0, padding);
+
+ assert_in_range(buffer_len, 0, array_len);
+
+ buf.value = data;
+ buf.length = buffer_len;
+
+ valid_range_begin = buf.value;
+ valid_range_end = valid_range_begin + buf.length;
+ invalid_range_end = valid_range_begin + padded_len;
+
+ return buf;
+}
+
+static void assert_mem_in_valid_range(const uint8_t *ptr, const size_t len)
+{
+ /* Ensure we've set up the range pointers properly. */
+ assert_non_null(valid_range_begin);
+ assert_non_null(valid_range_end);
+ assert_non_null(invalid_range_end);
+
+ /*
+ * Ensure the length isn't excessively large (a symptom of integer
+ * underflow).
+ */
+ assert_in_range(len, 0, 0x1000);
+
+ /* Ensure the memory is in our valid range. */
+ assert_in_range(ptr, valid_range_begin, valid_range_end);
+ assert_in_range(ptr + len, valid_range_begin, valid_range_end);
+}
+
+/*
+ * This function takes a pointer to volatile to allow it to be called from the
+ * ct_memcmp() wrapper.
+ */
+static void assert_mem_outside_invalid_range(const volatile uint8_t *ptr,
+ const size_t len)
+{
+ const LargestIntegralType _valid_range_end
+ = cast_ptr_to_largest_integral_type(valid_range_end);
+ const LargestIntegralType _invalid_range_end
+ = cast_ptr_to_largest_integral_type(invalid_range_end);
+ const LargestIntegralType _ptr = cast_ptr_to_largest_integral_type(ptr);
+ const LargestIntegralType _len = cast_to_largest_integral_type(len);
+
+ /* Ensure we've set up the range pointers properly. */
+ assert_non_null(valid_range_begin);
+ assert_non_null(valid_range_end);
+ assert_non_null(invalid_range_end);
+
+ /*
+ * Ensure the length isn't excessively large (a symptom of integer
+ * underflow).
+ */
+ assert_in_range(len, 0, 0x1000);
+
+ /* Ensure the memory is outside the invalid range. */
+ if (_ptr < _invalid_range_end && _ptr + _len > _valid_range_end) {
+ fail();
+ }
+}
+
+/*****************************************************************************
+ * wrapped functions
+ *****************************************************************************/
+
+krb5_keyblock dummy_key;
+
+krb5_error_code __wrap_krb5_auth_con_getlocalsubkey(krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_keyblock **keyblock);
+krb5_error_code __wrap_krb5_auth_con_getlocalsubkey(krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_keyblock **keyblock)
+{
+ *keyblock = &dummy_key;
+ return 0;
+}
+
+void __wrap_krb5_free_keyblock(krb5_context context,
+ krb5_keyblock *keyblock);
+void __wrap_krb5_free_keyblock(krb5_context context,
+ krb5_keyblock *keyblock)
+{
+ assert_ptr_equal(&dummy_key, keyblock);
+}
+
+struct krb5_crypto_data dummy_crypto;
+
+krb5_error_code __wrap_krb5_crypto_init(krb5_context context,
+ const krb5_keyblock *key,
+ krb5_enctype etype,
+ krb5_crypto *crypto);
+krb5_error_code __wrap_krb5_crypto_init(krb5_context context,
+ const krb5_keyblock *key,
+ krb5_enctype etype,
+ krb5_crypto *crypto)
+{
+ static const LargestIntegralType etypes[] = {ETYPE_DES3_CBC_NONE, 0};
+
+ assert_ptr_equal(&dummy_key, key);
+ assert_in_set(etype, etypes, ARRAY_SIZE(etypes));
+
+ *crypto = &dummy_crypto;
+
+ return 0;
+}
+
+krb5_error_code __wrap_krb5_decrypt(krb5_context context,
+ krb5_crypto crypto,
+ unsigned usage,
+ void *data,
+ size_t len,
+ krb5_data *result);
+krb5_error_code __wrap_krb5_decrypt(krb5_context context,
+ krb5_crypto crypto,
+ unsigned usage,
+ void *data,
+ size_t len,
+ krb5_data *result)
+{
+ assert_ptr_equal(&dummy_crypto, crypto);
+ assert_int_equal(KRB5_KU_USAGE_SEAL, usage);
+
+ assert_mem_in_valid_range(data, len);
+
+ check_expected(len);
+ check_expected_ptr(data);
+
+ result->data = malloc(len);
+ assert_non_null(result->data);
+ result->length = len;
+
+ memcpy(result->data, data, len);
+
+ return 0;
+}
+
+krb5_error_code __wrap_krb5_decrypt_ivec(krb5_context context,
+ krb5_crypto crypto,
+ unsigned usage,
+ void *data,
+ size_t len,
+ krb5_data *result,
+ void *ivec);
+krb5_error_code __wrap_krb5_decrypt_ivec(krb5_context context,
+ krb5_crypto crypto,
+ unsigned usage,
+ void *data,
+ size_t len,
+ krb5_data *result,
+ void *ivec)
+{
+ assert_ptr_equal(&dummy_crypto, crypto);
+ assert_int_equal(KRB5_KU_USAGE_SEQ, usage);
+
+ assert_mem_in_valid_range(data, len);
+
+ assert_int_equal(8, len);
+ check_expected_ptr(data);
+ check_expected_ptr(ivec);
+
+ result->data = malloc(len);
+ assert_non_null(result->data);
+ result->length = len;
+
+ memcpy(result->data, data, len);
+
+ return 0;
+}
+
+krb5_error_code __wrap_krb5_verify_checksum(krb5_context context,
+ krb5_crypto crypto,
+ krb5_key_usage usage,
+ void *data,
+ size_t len,
+ Checksum *cksum);
+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/tests/kerberos.c b/source4/auth/tests/kerberos.c
new file mode 100644
index 0000000..d9be356
--- /dev/null
+++ b/source4/auth/tests/kerberos.c
@@ -0,0 +1,123 @@
+#include <time.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+
+#include "includes.h"
+#include "system/kerberos.h"
+#include "auth/kerberos/kerberos.h"
+#include "auth/credentials/credentials.h"
+#include "auth/credentials/credentials_krb5.h"
+#include "auth/kerberos/kerberos_credentials.h"
+#include "auth/kerberos/kerberos_util.h"
+
+static void internal_obsolete_keytab_test(int num_principals, int num_kvnos,
+ krb5_kvno kvno, const char *kt_name)
+{
+ krb5_context krb5_ctx;
+ krb5_keytab keytab;
+ krb5_keytab_entry kt_entry;
+ krb5_kt_cursor cursor;
+ krb5_error_code code;
+
+ int i,j;
+ char princ_name[] = "user0";
+ char expect_princ_name[] = "user0@samba.example.com";
+ bool found_previous;
+ const char *error_str;
+
+ TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+ krb5_principal *principals = talloc_zero_array(tmp_ctx,
+ krb5_principal,
+ num_principals);
+ krb5_init_context(&krb5_ctx);
+ krb5_kt_resolve(krb5_ctx, kt_name, &keytab);
+ ZERO_STRUCT(kt_entry);
+
+ for(i=0; i<num_principals; i++) {
+ princ_name[4] = (char)i+48;
+ smb_krb5_make_principal(krb5_ctx, &(principals[i]),
+ "samba.example.com", princ_name, NULL);
+ kt_entry.principal = principals[i];
+ for (j=0; j<num_kvnos; j++) {
+ kt_entry.vno = j+1;
+ krb5_kt_add_entry(krb5_ctx, keytab, &kt_entry);
+ }
+ }
+
+ code = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
+ assert_int_equal(code, 0);
+#ifdef SAMBA4_USES_HEIMDAL
+ for (i=0; i<num_principals; i++) {
+ expect_princ_name[4] = (char)i+48;
+ for (j=0; j<num_kvnos; j++) {
+ char *unparsed_name;
+ code = krb5_kt_next_entry(krb5_ctx, keytab,
+ &kt_entry, &cursor);
+ assert_int_equal(code, 0);
+ assert_int_equal(kt_entry.vno, j+1);
+#else
+ /* MIT - For MEMORY type keytabs, krb5_kt_add_entry() adds an
+ * entry to the beginning of the keytab table, not the end */
+ for (i=num_principals-1; i>=0; i--) {
+ expect_princ_name[4] = (char)i+48;
+ for (j=num_kvnos; j>0; j--) {
+ char *unparsed_name;
+ code = krb5_kt_next_entry(krb5_ctx, keytab,
+ &kt_entry, &cursor);
+ assert_int_equal(code, 0);
+ assert_int_equal(kt_entry.vno, j);
+#endif
+ krb5_unparse_name(krb5_ctx, kt_entry.principal,
+ &unparsed_name);
+ assert_string_equal(expect_princ_name, unparsed_name);
+ }
+ }
+
+ smb_krb5_remove_obsolete_keytab_entries(tmp_ctx, krb5_ctx, keytab,
+ num_principals, principals,
+ kvno, &found_previous,
+ &error_str);
+
+ code = krb5_kt_start_seq_get(krb5_ctx, keytab, &cursor);
+ assert_int_equal(code, 0);
+#ifdef SAMBA4_USES_HEIMDAL
+ for (i=0; i<num_principals; i++) {
+#else /* MIT - reverse iterate through entries */
+ for (i=num_principals-1; i>=0; i--) {
+#endif
+ char *unparsed_name;
+ expect_princ_name[4] = (char)i+48;
+ code = krb5_kt_next_entry(krb5_ctx, keytab, &kt_entry, &cursor);
+ assert_int_equal(code, 0);
+ assert_int_equal(kt_entry.vno, kvno-1);
+ krb5_unparse_name(krb5_ctx, kt_entry.principal, &unparsed_name);
+ assert_string_equal(expect_princ_name, unparsed_name);
+ }
+ code = krb5_kt_next_entry(krb5_ctx, keytab, &kt_entry, &cursor);
+ assert_int_not_equal(code, 0);
+}
+
+static void test_krb5_remove_obsolete_keytab_entries_many(void **state)
+{
+ internal_obsolete_keytab_test(5, 4, (krb5_kvno)5, "MEMORY:LOL2");
+}
+
+static void test_krb5_remove_obsolete_keytab_entries_one(void **state)
+{
+ internal_obsolete_keytab_test(1, 2, (krb5_kvno)3, "MEMORY:LOL");
+}
+
+int main(int argc, const char **argv)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test_krb5_remove_obsolete_keytab_entries_one),
+ cmocka_unit_test(test_krb5_remove_obsolete_keytab_entries_many),
+ };
+
+ cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/source4/auth/tests/sam.c b/source4/auth/tests/sam.c
new file mode 100644
index 0000000..e1e2c69
--- /dev/null
+++ b/source4/auth/tests/sam.c
@@ -0,0 +1,2746 @@
+/*
+ * Unit tests for source4/auth/sam.c
+ *
+ * Copyright (C) Catalyst.NET Ltd 2021
+ *
+ * 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 <time.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+#include <cmocka.h>
+
+#include "includes.h"
+#include "auth/sam.c"
+#include "ldb.h"
+#include "ntstatus.h"
+#include "librpc/gen_ndr/ndr_security.h"
+
+/*****************************************************************************
+ * wrapped functions
+ *
+ *****************************************************************************/
+int __wrap_samdb_msg_add_int64(
+ struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message *msg,
+ const char *attr_name,
+ int64_t v);
+int __real_samdb_msg_add_int64(
+ struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message *msg,
+ const char *attr_name,
+ int64_t v);
+int __wrap_samdb_msg_add_int64(
+ struct ldb_context *sam_ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message *msg,
+ const char *attr_name,
+ int64_t v)
+{
+
+ int ret;
+ ret = (int)mock();
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ return __real_samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, v);
+}
+/*****************************************************************************
+ * Mock implementations
+ *****************************************************************************/
+
+static int check_dn(const LargestIntegralType left_value,
+ const LargestIntegralType right_value)
+{
+ /*
+ * We have to cast away const so we can get the linearized form with
+ * ldb_dn_get_extended_linearized().
+ */
+ struct ldb_dn *left_dn = (void *)left_value;
+ struct ldb_dn *right_dn = (void *)right_value;
+ char *left_dn_string = NULL;
+ char *right_dn_string = NULL;
+ bool ok;
+
+ if (left_dn == NULL && right_dn == NULL) {
+ return true;
+ }
+
+ if (left_dn != NULL) {
+ left_dn_string = ldb_dn_get_extended_linearized(NULL, left_dn, 1);
+ assert_non_null(left_dn_string);
+ }
+
+ if (right_dn != NULL) {
+ right_dn_string = ldb_dn_get_extended_linearized(NULL, right_dn, 1);
+ assert_non_null(right_dn_string);
+ }
+
+ if (left_dn_string == NULL || right_dn_string == NULL) {
+ ok = false;
+ print_error("\"%s\" != \"%s\"\n",
+ left_dn_string != NULL ? left_dn_string : "<NULL>",
+ right_dn_string != NULL ? right_dn_string : "<NULL>");
+ } else {
+ ok = (strcmp(left_dn_string, right_dn_string) == 0);
+ if (!ok) {
+ print_error("\"%s\" != \"%s\"\n",
+ left_dn_string,
+ right_dn_string);
+ }
+
+ }
+
+ TALLOC_FREE(right_dn_string);
+ TALLOC_FREE(left_dn_string);
+
+ return ok;
+}
+
+int __wrap_dsdb_search_dn(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result **_result,
+ struct ldb_dn *basedn,
+ const char * const *attrs,
+ uint32_t dsdb_flags);
+int __wrap_dsdb_search_dn(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_result **_result,
+ struct ldb_dn *basedn,
+ const char * const *attrs,
+ uint32_t dsdb_flags)
+{
+ check_expected(basedn);
+
+ *_result = talloc_steal(mem_ctx, mock_ptr_type(struct ldb_result *));
+
+ return mock();
+}
+
+int ldb_transaction_start_ret = LDB_SUCCESS;
+bool in_transaction = false;
+int ldb_transaction_start(struct ldb_context *ldb) {
+ assert_false(in_transaction);
+ if (ldb_transaction_start_ret == LDB_SUCCESS) {
+ in_transaction = true;
+ }
+ return ldb_transaction_start_ret;
+}
+
+int ldb_transaction_cancel_ret = LDB_SUCCESS;
+bool transaction_cancelled = false;
+int ldb_transaction_cancel(struct ldb_context *ldb) {
+ assert_true(in_transaction);
+ if (ldb_transaction_cancel_ret == LDB_SUCCESS) {
+ in_transaction = false;
+ transaction_cancelled = true;
+ }
+ return ldb_transaction_cancel_ret;
+}
+
+int ldb_transaction_commit_ret = LDB_SUCCESS;
+bool transaction_committed = false;
+int ldb_transaction_commit(struct ldb_context *ldb) {
+ assert_true(in_transaction);
+ if (ldb_transaction_commit_ret == LDB_SUCCESS) {
+ in_transaction = false;
+ transaction_committed = true;
+ }
+ return ldb_transaction_commit_ret;
+}
+
+NTSTATUS dsdb_update_bad_pwd_count_ret = NT_STATUS_OK;
+struct ldb_message *dsdb_update_bad_pwd_count_res = NULL;
+NTSTATUS dsdb_update_bad_pwd_count(TALLOC_CTX *mem_ctx,
+ struct ldb_context *sam_ctx,
+ struct ldb_message *user_msg,
+ struct ldb_message *domain_msg,
+ struct ldb_message *pso_msg,
+ struct ldb_message **_mod_msg) {
+
+ *_mod_msg = talloc_move(mem_ctx, &dsdb_update_bad_pwd_count_res);
+ return dsdb_update_bad_pwd_count_ret;
+}
+
+int ldb_build_mod_req_ret = LDB_SUCCESS;
+struct ldb_request *ldb_build_mod_req_res = NULL;
+int ldb_build_mod_req(struct ldb_request **ret_req,
+ struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ const struct ldb_message *message,
+ struct ldb_control **controls,
+ void *context,
+ ldb_request_callback_t callback,
+ struct ldb_request *parent)
+{
+ *ret_req = talloc_move(mem_ctx, &ldb_build_mod_req_res);
+ return ldb_build_mod_req_ret;
+}
+
+int ldb_request_add_control_ret = LDB_SUCCESS;
+int ldb_request_add_control(struct ldb_request *req,
+ const char *oid,
+ bool critical,
+ void *data)
+{
+ return ldb_request_add_control_ret;
+}
+
+int ldb_request_ret = LDB_SUCCESS;
+int ldb_request(struct ldb_context *ldb,
+ struct ldb_request *req)
+{
+ return ldb_request_ret;
+}
+
+int ldb_wait_ret = LDB_SUCCESS;
+int ldb_wait(struct ldb_handle *handle,
+ enum ldb_wait_type type)
+{
+ return ldb_wait_ret;
+}
+bool ldb_msg_new_fail = false;
+struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
+{
+ if (ldb_msg_new_fail) {
+ return NULL;
+ } else {
+ return talloc_zero(mem_ctx, struct ldb_message);
+ }
+}
+
+int samdb_rodc_ret = LDB_SUCCESS;
+bool samdb_rodc_res = false;
+
+int samdb_rodc(
+ struct ldb_context *sam_ctx,
+ bool *am_rodc)
+{
+
+ *am_rodc = samdb_rodc_res;
+ return samdb_rodc_ret;
+}
+
+struct loadparm_context *ldb_get_opaque_ret = NULL;
+void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
+{
+ return ldb_get_opaque_ret;
+}
+
+struct db_context {};
+struct db_context *cluster_db_tmp_open_ret = NULL;
+struct db_context *cluster_db_tmp_open(
+ TALLOC_CTX *mem_ctx,
+ struct loadparm_context *lp_ctx,
+ const char *dbbase,
+ int flags)
+{
+ return cluster_db_tmp_open_ret;
+}
+
+NTSTATUS dbwrap_store_ret = NT_STATUS_OK;
+NTSTATUS dbwrap_store(struct db_context *db, TDB_DATA key,
+ TDB_DATA data, int flags)
+{
+ return dbwrap_store_ret;
+}
+bool dbwrap_exists_ret = true;
+
+bool dbwrap_exists(struct db_context *db, TDB_DATA key)
+{
+ return dbwrap_exists_ret;
+}
+
+NTSTATUS dbwrap_delete_ret = NT_STATUS_OK;
+NTSTATUS dbwrap_delete(struct db_context *db, TDB_DATA key)
+{
+ return dbwrap_delete_ret;
+}
+
+/*
+ * Set the globals used by the mocked functions to a known and consistent state
+ *
+ */
+static void init_mock_results(TALLOC_CTX *mem_ctx)
+{
+ ldb_transaction_start_ret = LDB_SUCCESS;
+ in_transaction = false;
+
+ ldb_transaction_cancel_ret = LDB_SUCCESS;
+ transaction_cancelled = false;
+
+ ldb_transaction_commit_ret = LDB_SUCCESS;
+ transaction_committed = false;
+
+ dsdb_update_bad_pwd_count_ret = NT_STATUS_OK;
+ dsdb_update_bad_pwd_count_res = NULL;
+
+ ldb_build_mod_req_ret = LDB_SUCCESS;
+ ldb_build_mod_req_res = NULL;
+
+ ldb_request_add_control_ret = LDB_SUCCESS;
+ ldb_request_ret = LDB_SUCCESS;
+ ldb_wait_ret = LDB_SUCCESS;
+
+ ldb_msg_new_fail = false;
+
+ samdb_rodc_ret = LDB_SUCCESS;
+ samdb_rodc_res = false;
+
+ ldb_get_opaque_ret = loadparm_init(mem_ctx);
+
+ cluster_db_tmp_open_ret = talloc_zero(mem_ctx, struct db_context);
+
+ dbwrap_store_ret = NT_STATUS_OK;
+
+ dbwrap_exists_ret = true;
+
+ dbwrap_delete_ret = NT_STATUS_OK;
+
+}
+
+/*****************************************************************************
+ * Unit test set up and tear down
+ *****************************************************************************/
+struct context {
+};
+
+static int setup(void **state) {
+ struct context *ctx = talloc_zero(NULL, struct context);
+ init_mock_results(ctx);
+
+ *state = ctx;
+ return 0;
+}
+
+static int teardown(void **state) {
+ struct context *ctx = *state;
+ TALLOC_FREE(ctx);
+ return 0;
+}
+
+/******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+
+/*
+ * Build the "Original" user details record, i.e. the user being
+ * authenticated
+ */
+static struct ldb_message *create_message(TALLOC_CTX *ctx)
+{
+
+ int ret;
+ struct timeval tv_now = timeval_current();
+ NTTIME now = timeval_to_nttime(&tv_now);
+
+ struct ldb_message *msg = ldb_msg_new(ctx);
+
+ assert_non_null(msg);
+ ret = samdb_msg_add_int(ctx, msg, msg, "badPwdCount", 10);
+ assert_int_equal(LDB_SUCCESS, ret);
+ ret = __real_samdb_msg_add_int64(ctx, msg, msg, "badPasswordTime", now);
+ assert_int_equal(LDB_SUCCESS, ret);
+ ret = __real_samdb_msg_add_int64(ctx, msg, msg, "lockoutTime", now);
+ assert_int_equal(LDB_SUCCESS, ret);
+ return msg;
+}
+
+/*
+ * Add a binary objectSID from string form to the supplied message
+ *
+ *
+ */
+static void add_sid(
+ struct ldb_message *msg,
+ const char *sid_str)
+{
+ struct ldb_val v;
+ enum ndr_err_code ndr_err;
+ struct dom_sid *sid = NULL;
+
+ sid = talloc_zero(msg, struct dom_sid);
+ assert_non_null(sid);
+ assert_true(string_to_sid(sid, sid_str));
+ ndr_err = ndr_push_struct_blob(
+ &v, msg, sid, (ndr_push_flags_fn_t)ndr_push_dom_sid);
+ assert_true(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
+ assert_int_equal(0, ldb_msg_add_value(msg, "objectSID", &v, NULL));
+}
+
+/*
+ * Build an ldb_result, for the re-reading of a user record
+ *
+ * if account_control < 0 then the msDS-User-Account-Control-Computed
+ * element is not included
+ * otherwise it is set to the value passed in account_control.
+ *
+ */
+static struct ldb_result *build_reread_result(
+ struct ldb_context *ldb,
+ TALLOC_CTX *ctx,
+ int account_control)
+{
+ struct ldb_message *msg = NULL;
+ int ret;
+
+ struct ldb_result *res = talloc_zero(ctx, struct ldb_result);
+
+ assert_non_null(res);
+ res->count = 1;
+ res->msgs = talloc_array(res, struct ldb_message *, 1);
+
+ msg = create_message(res);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+ if (account_control >= 0) {
+ ret = samdb_msg_add_int(
+ ldb,
+ msg,
+ msg,
+ "msDS-User-Account-Control-Computed",
+ account_control);
+ assert_int_equal(LDB_SUCCESS, ret);
+ }
+
+ res->msgs[0] = msg;
+ return res;
+}
+
+/*
+ * Build a mock domain pso ldb_result
+ */
+static struct ldb_result *build_domain_pso_result(
+ struct ldb_context *ldb,
+ TALLOC_CTX *ctx)
+{
+ struct ldb_message *msg = NULL;
+ struct ldb_result *res = talloc_zero(ctx, struct ldb_result);
+
+ assert_non_null(res);
+ res->count = 1;
+ res->msgs = talloc_array(res, struct ldb_message *, 1);
+ assert_non_null(res->msgs);
+ msg = talloc_zero(res, struct ldb_message);
+ assert_non_null(msg);
+ res->msgs[0] = msg;
+ return res;
+}
+
+/*****************************************************************************
+ * authsam_reread_user_logon_data unit tests
+ *****************************************************************************/
+/*
+ * authsam_reread_user_logon_data unable to re-read the user record.
+ *
+ */
+static void test_reread_read_failure(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_message *cur = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, NULL);
+ will_return(__wrap_dsdb_search_dn, LDB_ERR_NO_SUCH_OBJECT);
+
+ status = authsam_reread_user_logon_data(ldb, ctx, msg, &cur);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_reread_user_logon_data account control flags missing from
+ * re-read data
+ *
+ */
+static void test_reread_missing_account_control(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_message *cur = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, -1));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ status = authsam_reread_user_logon_data(ldb, ctx, msg, &cur);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_reread_user_logon_data account locked
+ * re-read data
+ *
+ */
+static void test_reread_account_locked(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_message *cur = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, UF_LOCKOUT));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ status = authsam_reread_user_logon_data(ldb, ctx, msg, &cur);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_reread_user_logon_data account is not locked
+ * re-read data
+ *
+ */
+static void test_reread_account_not_locked(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_message *cur = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ size_t result_size = 0;
+ NTSTATUS status;
+ struct ldb_result *res = NULL;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ /*
+ * authsam_reread_user_logon_data returns the ldb_message portion
+ * of the ldb_result created by build_reread_result.
+ * So the tests for memory leaks will need to adjust for that
+ */
+ res = build_reread_result(ldb, ctx, 0);
+ will_return(__wrap_dsdb_search_dn, res);
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ result_size = talloc_total_size(res) -
+ talloc_total_size(res->msgs[0]);
+ before = talloc_total_size(ctx) - result_size;
+
+ status = authsam_reread_user_logon_data(ldb, ctx, msg, &cur);
+ assert_true(NT_STATUS_IS_OK(status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+
+/*****************************************************************************
+ * authsam_update_bad_pwd_count unit tests
+ *****************************************************************************/
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * Unable to read the domain_dn record
+ *
+ */
+static void test_update_bad_domain_dn_search_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = talloc_zero(ctx, struct ldb_message);
+ assert_non_null(msg);
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, NULL);
+ will_return(__wrap_dsdb_search_dn, LDB_ERR_NO_SUCH_OBJECT);
+
+ before = talloc_total_size(ctx);
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_DB_CORRUPTION));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * authsam_get_user_pso failure
+ *
+ */
+static void test_update_bad_get_pso_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ struct ldb_dn *pso_dn = NULL;
+ const char *pso_dn_str = "CN=PSO";
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+ int ret;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ pso_dn = ldb_dn_new(ctx, ldb, pso_dn_str);
+ assert_non_null(pso_dn);
+
+ msg = talloc_zero(ctx, struct ldb_message);
+ assert_non_null(msg);
+ ret = ldb_msg_add_string(msg, "msDS-ResultantPSO", pso_dn_str);
+ assert_int_equal(LDB_SUCCESS, ret);
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, pso_dn);
+ will_return(__wrap_dsdb_search_dn, NULL);
+ will_return(__wrap_dsdb_search_dn, LDB_ERR_NO_SUCH_OBJECT);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_IS_OK(status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * start_transaction failure
+ *
+ */
+static void test_update_bad_start_txn_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = talloc_zero(ctx, struct ldb_message);
+ assert_non_null(msg);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_transaction_start_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * User details re-read failed
+ *
+ */
+static void test_update_bad_reread_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = talloc_zero(ctx, struct ldb_message);
+ assert_non_null(msg);
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, NULL);
+ will_return(__wrap_dsdb_search_dn, LDB_ERR_NO_SUCH_OBJECT);
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * User details re-read reported locked out.
+ *
+ */
+static void test_update_bad_reread_locked_out(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, UF_LOCKOUT));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_ACCOUNT_LOCKED_OUT));
+ assert_false(transaction_cancelled);
+ assert_true(transaction_committed);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * Transaction cancel failure
+ */
+static void test_update_bad_txn_cancel_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = talloc_zero(ctx, struct ldb_message);
+ assert_non_null(msg);
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, NULL);
+ will_return(__wrap_dsdb_search_dn, LDB_ERR_NO_SUCH_OBJECT);
+
+ ldb_transaction_cancel_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(in_transaction);
+ assert_false(transaction_cancelled);
+ assert_false(transaction_committed);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * The following tests all expect the same setup, that is a normal
+ * good user object and empty domain object.
+ *
+ * returns the talloc size after result array setup for leak tests
+ */
+static size_t setup_bad_password_search_results(TALLOC_CTX *ctx,
+ struct ldb_context *ldb,
+ struct ldb_dn *domain_dn,
+ struct ldb_dn *user_dn)
+{
+ size_t before = 0;
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, user_dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ return before;
+}
+
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * dsdb_update_bad_pwd_count failure
+ *
+ */
+static void test_update_bad_update_count_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = setup_bad_password_search_results(ctx, ldb,
+ domain_dn,
+ msg->dn);
+
+ dsdb_update_bad_pwd_count_ret = NT_STATUS_INTERNAL_ERROR;
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * No need to update the bad password stats
+ *
+ */
+static void test_update_bad_no_update_required(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = setup_bad_password_search_results(ctx, ldb,
+ domain_dn,
+ msg->dn);
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_IS_OK(status));
+ assert_true(transaction_committed);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * Transaction commit failure
+ *
+ */
+static void test_update_bad_commit_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = setup_bad_password_search_results(ctx, ldb,
+ domain_dn,
+ msg->dn);
+
+ ldb_transaction_commit_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(in_transaction);
+ assert_false(transaction_cancelled);
+ assert_false(transaction_committed);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * ldb_build_mod_req failed building the user update details
+ *
+ */
+static void test_update_bad_build_mod_request_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = setup_bad_password_search_results(ctx, ldb,
+ domain_dn,
+ msg->dn);
+
+ dsdb_update_bad_pwd_count_res = talloc_zero(ctx, struct ldb_message);
+ ldb_build_mod_req_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * ldb_request_add_control failed to add DSDB_CONTROL_FORCE_RODC_LOCAL_CHANGE
+ * to the user update record.
+ *
+ */
+static void test_update_bad_add_control_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = setup_bad_password_search_results(ctx, ldb,
+ domain_dn,
+ msg->dn);
+
+ dsdb_update_bad_pwd_count_res = talloc_zero(ctx, struct ldb_message);
+ ldb_build_mod_req_res = talloc_zero(ctx, struct ldb_request);
+ ldb_request_add_control_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * call to ldb_request failed
+ *
+ */
+static void test_update_bad_ldb_request_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = setup_bad_password_search_results(ctx, ldb,
+ domain_dn,
+ msg->dn);
+
+ dsdb_update_bad_pwd_count_res = talloc_zero(ctx, struct ldb_message);
+ ldb_build_mod_req_res = talloc_zero(ctx, struct ldb_request);
+ ldb_request_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_update_bad_pwd_account
+ *
+ * call to ldb_wait failed
+ *
+ */
+static void test_update_bad_ldb_wait_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = setup_bad_password_search_results(ctx, ldb,
+ domain_dn,
+ msg->dn);
+
+ dsdb_update_bad_pwd_count_res = talloc_zero(ctx, struct ldb_message);
+ ldb_build_mod_req_res = talloc_zero(ctx, struct ldb_request);
+ ldb_wait_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_update_bad_pwd_count(ldb, msg, domain_dn);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*****************************************************************************
+ * authsam_logon_success_accounting unit tests
+ *****************************************************************************/
+/*
+ * authsam_logon_success_accounting
+ *
+ * start_transaction failure
+ *
+ */
+static void test_success_accounting_start_txn_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_transaction_start_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * User details re-read failed
+ *
+ */
+static void test_success_accounting_reread_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, NULL);
+ will_return(__wrap_dsdb_search_dn, LDB_ERR_NO_SUCH_OBJECT);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * ldb_msg_new failed
+ *
+ */
+static void test_success_accounting_ldb_msg_new_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_msg_new_fail = true;
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * samdb_rodc failed
+ *
+ */
+static void test_success_accounting_samdb_rodc_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ samdb_rodc_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_false(in_transaction);
+ assert_false(transaction_cancelled);
+ assert_false(transaction_committed);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * authsam_update_lastlogon_timestamp failed
+ *
+ */
+static void test_success_accounting_update_lastlogon_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ ldb_build_mod_req_res = talloc_zero(ctx, struct ldb_request);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ will_return(__wrap_samdb_msg_add_int64, LDB_ERR_OPERATIONS_ERROR);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_NO_MEMORY));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * ldb_build_mod_req failed
+ *
+ */
+static void test_success_accounting_build_mod_req_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_build_mod_req_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * ldb_request_add_control failed
+ *
+ */
+static void test_success_accounting_add_control_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_build_mod_req_res = talloc_zero(ldb, struct ldb_request);
+ ldb_request_add_control_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * ldb_request failed
+ *
+ */
+static void test_success_accounting_ldb_request_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_build_mod_req_res = talloc_zero(ldb, struct ldb_request);
+ ldb_request_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * ldb_wait failed
+ *
+ */
+static void test_success_accounting_ldb_wait_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_build_mod_req_res = talloc_zero(ldb, struct ldb_request);
+ ldb_wait_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(transaction_cancelled);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * ldb_transaction_commit failed
+ *
+ */
+static void test_success_accounting_commit_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_build_mod_req_res = talloc_zero(ldb, struct ldb_request);
+ ldb_transaction_commit_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(in_transaction);
+ assert_false(transaction_cancelled);
+ assert_false(transaction_committed);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * ldb_wait failed and then ldb_transaction_cancel failed
+ *
+ */
+static void test_success_accounting_rollback_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ ldb_build_mod_req_res = talloc_zero(ldb, struct ldb_request);
+ ldb_wait_ret = LDB_ERR_OPERATIONS_ERROR;
+ ldb_transaction_cancel_ret = LDB_ERR_OPERATIONS_ERROR;
+
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+ will_return(__wrap_samdb_msg_add_int64, LDB_SUCCESS);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR));
+ assert_true(in_transaction);
+ assert_false(transaction_cancelled);
+ assert_false(transaction_committed);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * authsam_logon_success_accounting
+ *
+ * The bad password indicator is set, but the account is not locked out.
+ *
+ */
+static void test_success_accounting_spurious_bad_pwd_indicator(void **state) {
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *domain_dn = NULL;
+ TALLOC_CTX *ctx = NULL;
+ size_t before = 0;
+ size_t after = 0;
+ NTSTATUS status;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ domain_dn = ldb_dn_new(ctx, ldb, "CN=Domain");
+ assert_non_null(domain_dn);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1000");
+
+ msg->dn = ldb_dn_new(ctx, ldb, "CN=User");
+ assert_non_null(msg->dn);
+
+ before = talloc_total_size(ctx);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, domain_dn);
+ will_return(__wrap_dsdb_search_dn, build_domain_pso_result(ldb, ctx));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ expect_check(__wrap_dsdb_search_dn, basedn, check_dn, msg->dn);
+ will_return(__wrap_dsdb_search_dn, build_reread_result(ldb, ctx, 0));
+ will_return(__wrap_dsdb_search_dn, LDB_SUCCESS);
+
+ will_return_count(__wrap_samdb_msg_add_int64, LDB_SUCCESS, 2);
+
+ /*
+ * Set the bad password indicator.
+ */
+ status = authsam_set_bad_password_indicator(ldb, ctx, msg);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_OK, status));
+
+ ldb_build_mod_req_res = talloc_zero(ctx, struct ldb_request);
+
+ status = authsam_logon_success_accounting(
+ ldb, msg, domain_dn, true, NULL, NULL);
+ assert_true(NT_STATUS_EQUAL(status, NT_STATUS_OK));
+ assert_false(in_transaction);
+ assert_false(transaction_cancelled);
+ assert_true(transaction_committed);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * get_bad_password_db
+ *
+ * ldb_get_opaque failure.
+ */
+static void test_get_bad_password_get_opaque_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ TALLOC_CTX *ctx = NULL;
+ struct db_context *db = NULL;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ /*
+ * clear the mock ldb_get_opaque return value, so that we get a null
+ * response.
+ */
+ TALLOC_FREE(ldb_get_opaque_ret);
+
+ before = talloc_total_size(ctx);
+
+ db = authsam_get_bad_password_db(ctx, ldb);
+ assert_null(db);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * get_bad_password_db
+ *
+ * cluster_db_tmp_open failure.
+ */
+static void test_get_bad_password_db_open_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ TALLOC_CTX *ctx = NULL;
+ struct db_context *db = NULL;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ /*
+ * Clear the mock cluster_db_tmp_open return value so that
+ * it returns NULL
+ */
+ TALLOC_FREE(cluster_db_tmp_open_ret);
+ before = talloc_total_size(ctx);
+
+ db = authsam_get_bad_password_db(ctx, ldb);
+ assert_null(db);
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * set_bad_password_indicator
+ *
+ * set_bad_password_indicator failure.
+ */
+static void test_set_bad_password_indicator_get_db_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ /*
+ * Clear the mock cluster_db_tmp_open return value so that
+ * it returns NULL
+ */
+ TALLOC_FREE(cluster_db_tmp_open_ret);
+ before = talloc_total_size(ctx);
+
+ status = authsam_set_bad_password_indicator(ldb, ctx, NULL);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * set_bad_password_indicator
+ *
+ * get_object_sid_as_tdb_data failure.
+ */
+static void test_set_bad_password_indicator_get_object_sid_failed(
+ void **state)
+{
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ /*
+ * The created message does not contain an objectSid, so
+ * get_object_sid_as_tdb_data will fail.
+ */
+ msg = create_message(ctx);
+
+ before = talloc_total_size(ctx);
+
+ status = authsam_set_bad_password_indicator(ldb, ctx, msg);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * set_bad_password_indicator
+ *
+ * dbwrap_store failure.
+ */
+static void test_set_bad_password_indicator_dbwrap_store_failed(
+ void **state)
+{
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1010");
+
+ dbwrap_store_ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+
+ before = talloc_total_size(ctx);
+
+ status = authsam_set_bad_password_indicator(ldb, ctx, msg);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_INTERNAL_DB_CORRUPTION, status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * check_bad_password_indicator
+ *
+ * set_bad_password_indicator failure.
+ */
+static void test_check_bad_password_indicator_get_db_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+ bool exists = false;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ /*
+ * Clear the mock cluster_db_tmp_open return value so that
+ * it returns NULL
+ */
+ TALLOC_FREE(cluster_db_tmp_open_ret);
+ before = talloc_total_size(ctx);
+
+ status = authsam_check_bad_password_indicator(ldb, ctx, &exists, NULL);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * check_bad_password_indicator
+ *
+ * get_object_sid_as_tdb_data failure.
+ */
+static void test_check_bad_password_indicator_get_object_sid_failed(
+ void **state)
+{
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+ bool exists = false;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ /*
+ * The created message does not contain an objectSid, so
+ * get_object_sid_as_tdb_data will fail.
+ */
+ msg = create_message(ctx);
+
+ before = talloc_total_size(ctx);
+
+ status = authsam_check_bad_password_indicator(ldb, ctx, &exists, msg);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * clear_bad_password_indicator
+ *
+ * set_bad_password_indicator failure.
+ */
+static void test_clear_bad_password_indicator_get_db_failed(void **state) {
+ struct ldb_context *ldb = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ /*
+ * Clear the mock cluster_db_tmp_open return value so that
+ * it returns NULL
+ */
+ TALLOC_FREE(cluster_db_tmp_open_ret);
+ before = talloc_total_size(ctx);
+
+ status = authsam_clear_bad_password_indicator(ldb, ctx, NULL);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * clear_bad_password_indicator
+ *
+ * get_object_sid_as_tdb_data failure.
+ */
+static void test_clear_bad_password_indicator_get_object_sid_failed(
+ void **state)
+{
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ /*
+ * The created message does not contain an objectSid, so
+ * get_object_sid_as_tdb_data will fail.
+ */
+ msg = create_message(ctx);
+
+ before = talloc_total_size(ctx);
+
+ status = authsam_clear_bad_password_indicator(ldb, ctx, msg);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_INTERNAL_ERROR, status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * clear_bad_password_indicator
+ *
+ * dbwrap_delete failure.
+ */
+static void test_clear_bad_password_indicator_dbwrap_store_failed(
+ void **state)
+{
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1010");
+
+ dbwrap_delete_ret = NT_STATUS_INTERNAL_DB_CORRUPTION;
+
+ before = talloc_total_size(ctx);
+
+ status = authsam_clear_bad_password_indicator(ldb, ctx, msg);
+ assert_true(NT_STATUS_EQUAL(NT_STATUS_INTERNAL_DB_CORRUPTION, status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+/*
+ * clear_bad_password_indicator
+ *
+ * dbwrap_delete returns NT_STATUS_NOT_FOUND.
+ */
+static void test_clear_bad_pwd_indicator_dbwrap_store_not_found(
+ void **state)
+{
+ struct ldb_context *ldb = NULL;
+ struct ldb_message *msg = NULL;
+ TALLOC_CTX *ctx = NULL;
+ NTSTATUS status;
+ size_t before = 0;
+ size_t after = 0;
+
+ ctx = talloc_new(*state);
+ assert_non_null(ctx);
+
+ ldb = ldb_init(ctx, NULL);
+ assert_non_null(ldb);
+
+ msg = create_message(ctx);
+ add_sid(msg, "S-1-5-21-2470180966-3899876309-2637894779-1010");
+
+ dbwrap_delete_ret = NT_STATUS_NOT_FOUND;
+
+ before = talloc_total_size(ctx);
+
+ status = authsam_clear_bad_password_indicator(ldb, ctx, msg);
+ assert_true(NT_STATUS_IS_OK(status));
+
+ /*
+ * Check that all allocated memory was freed
+ */
+ after = talloc_total_size(ctx);
+ assert_int_equal(before, after);
+
+ /*
+ * Clean up
+ */
+ TALLOC_FREE(ctx);
+}
+
+int main(int argc, const char **argv)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test_setup_teardown(
+ test_reread_read_failure, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_reread_missing_account_control, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_reread_account_locked, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_reread_account_not_locked, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_domain_dn_search_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_get_pso_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_start_txn_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_reread_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_reread_locked_out, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_update_count_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_no_update_required, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_build_mod_request_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_add_control_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_ldb_request_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_ldb_wait_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_txn_cancel_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_update_bad_commit_failed, setup, teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_start_txn_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_reread_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_ldb_msg_new_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_samdb_rodc_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_update_lastlogon_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_build_mod_req_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_add_control_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_ldb_request_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_ldb_wait_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_commit_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_rollback_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_success_accounting_spurious_bad_pwd_indicator,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_get_bad_password_get_opaque_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_get_bad_password_db_open_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_set_bad_password_indicator_get_db_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_set_bad_password_indicator_get_object_sid_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_set_bad_password_indicator_dbwrap_store_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_check_bad_password_indicator_get_db_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_check_bad_password_indicator_get_object_sid_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_clear_bad_password_indicator_get_db_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_clear_bad_password_indicator_get_object_sid_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_clear_bad_password_indicator_dbwrap_store_failed,
+ setup,
+ teardown),
+ cmocka_unit_test_setup_teardown(
+ test_clear_bad_pwd_indicator_dbwrap_store_not_found,
+ setup,
+ teardown),
+ };
+
+ cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}