From: Gary Lockyer Date: Tue, 23 Oct 2018 04:14:34 +0000 (+1300) Subject: dsdb group_audit: Test to replicate BUG 13664 X-Git-Tag: tdb-1.3.17~1110 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eeb4089dafc45277d8af19073ef9348451c1836a;p=thirdparty%2Fsamba.git dsdb group_audit: Test to replicate BUG 13664 The group audit code incorrectly logs member additions and deletions. Thanks to metze for the debugging that isolated the issue, and for suggesting the fix to dn_compare. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13664 Signed-off-by: Gary Lockyer Reviewed-by: Stefan Metzmacher --- diff --git a/selftest/knownfail.d/bug13664 b/selftest/knownfail.d/bug13664 new file mode 100644 index 00000000000..6ffbf1297c3 --- /dev/null +++ b/selftest/knownfail.d/bug13664 @@ -0,0 +1 @@ +^samba4.dsdb.samdb.ldb_modules.group_audit.test_log_membership_changes_removed diff --git a/source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c b/source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c index 8551dcbf705..1f4cf3ea5b3 100644 --- a/source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c +++ b/source4/dsdb/samdb/ldb_modules/tests/test_group_audit.c @@ -63,6 +63,142 @@ int dsdb_search_one(struct ldb_context *ldb, return g_status; } +/* + * Mock version of audit_log_json + */ + +#define MAX_EXPECTED_MESSAGES 16 +static struct json_object messages[MAX_EXPECTED_MESSAGES]; +static size_t messages_sent = 0; + +void audit_message_send( + struct imessaging_context *msg_ctx, + const char *server_name, + uint32_t message_type, + struct json_object *message) +{ + messages[messages_sent].root = json_deep_copy(message->root); + messages[messages_sent].valid = message->valid; + messages_sent++; +} + +#define check_group_change_message(m, u, a)\ + _check_group_change_message(m, u, a, __FILE__, __LINE__); +/* + * declare the internal cmocka cm_print_error so that we can output messages + * in sub unit format + */ +void cm_print_error(const char * const format, ...); + +/* + * Validate a group change JSON audit message + * + * It should contain 3 elements. + * Have a type of "groupChange" + * Have a groupChange element + * + * The group change element should have 10 elements. + * + * There should be a user element matching the expected value + * There should be an action matching the expected value + */ +static void _check_group_change_message( + const int message, + const char *user, + const char *action, + const char *file, + const int line) +{ + struct json_object json; + json_t *audit = NULL; + json_t *v = NULL; + const char* value; + json = messages[message]; + + /* + * Validate the root JSON element + * check the number of elements + */ + if (json_object_size(json.root) != 3) { + cm_print_error( + "Unexpected number of elements in root %zu != %d\n", + json_object_size(json.root), + 3); + _fail(file, line); + } + + /* + * Check the type element + */ + v = json_object_get(json.root, "type"); + if (v == NULL) { + cm_print_error( "No \"type\" element\n"); + _fail(file, line); + } + + value = json_string_value(v); + if (strncmp("groupChange", value, strlen("groupChange") != 0)) { + cm_print_error( + "Unexpected type \"%s\" != \"groupChange\"\n", + value); + _fail(file, line); + } + + + audit = json_object_get(json.root, "groupChange"); + if (audit == NULL) { + cm_print_error("No groupChange element\n"); + _fail(file, line); + } + + /* + * Validate the groupChange element + */ + if (json_object_size(audit) != 10) { + cm_print_error( + "Unexpected number of elements in groupChange " + "%zu != %d\n", + json_object_size(audit), + 10); + _fail(file, line); + } + /* + * Validate the user element + */ + v = json_object_get(audit, "user"); + if (v == NULL) { + cm_print_error( "No user element\n"); + _fail(file, line); + } + + value = json_string_value(v); + if (strncmp(user, value, strlen(user) != 0)) { + cm_print_error( + "Unexpected user name \"%s\" != \"%s\"\n", + value, + user); + _fail(file, line); + } + + /* + * Validate the action element + */ + v = json_object_get(audit, "action"); + if (v == NULL) { + cm_print_error( "No action element\n"); + _fail(file, line); + } + + value = json_string_value(v); + if (strncmp(action, value, strlen(action) != 0)) { + print_error( + "Unexpected action \"%s\" != \"%s\"\n", + value, + action); + _fail(file, line); + } +} + /* * Test helper to check ISO 8601 timestamps for validity */ @@ -618,7 +754,121 @@ static void test_audit_group_json(void **state) json_free(&json); TALLOC_FREE(ctx); +} +static void setup_ldb( + TALLOC_CTX *ctx, + struct ldb_context **ldb, + struct ldb_module **module, + const char *ip, + const char *session, + const char *sid) +{ + struct tsocket_address *ts = NULL; + struct audit_context *context = NULL; + + *ldb = ldb_init(ctx, NULL); + ldb_register_samba_handlers(*ldb); + + + *module = talloc_zero(ctx, struct ldb_module); + (*module)->ldb = *ldb; + + context = talloc_zero(*module, struct audit_context); + context->send_events = true; + context->msg_ctx = (struct imessaging_context *) 0x01; + + ldb_module_set_private(*module, context); + + tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts); + ldb_set_opaque(*ldb, "remoteAddress", ts); + + add_session_data(ctx, *ldb, session, sid); +} + +/* + * Test the removal of a user from a group. + * + * The new element contains one group member + * The old element contains two group member + * + * Expect to see the removed entry logged. + * + * This test confirms bug 13664 + * https://bugzilla.samba.org/show_bug.cgi?id=13664 + */ +static void test_log_membership_changes_removed(void **state) +{ + struct ldb_context *ldb = NULL; + struct ldb_module *module = NULL; + const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779"; + const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773"; + const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773"; + const char * const IP = "127.0.0.1"; + struct ldb_request *req = NULL; + struct ldb_message_element *new_el = NULL; + struct ldb_message_element *old_el = NULL; + int status = 0; + TALLOC_CTX *ctx = talloc_new(NULL); + + setup_ldb(ctx, &ldb, &module, IP, SESSION, SID); + + /* + * Build the ldb_request + */ + req = talloc_zero(ctx, struct ldb_request); + req->operation = LDB_ADD; + add_transaction_id(req, TRANSACTION); + + /* + * Populate the new elements, containing one entry. + * Indicating that one element has been removed + */ + new_el = talloc_zero(ctx, struct ldb_message_element); + new_el->num_values = 1; + new_el->values = talloc_zero_array(ctx, DATA_BLOB, 1); + new_el->values[0] = data_blob_string_const( + ";" + "CN=testuser131953,CN=Users,DC=addom,DC=samba," + "DC=example,DC=com"); + + /* + * Populate the old elements, with two elements + * The first is the same as the one in new elements. + */ + old_el = talloc_zero(ctx, struct ldb_message_element); + old_el->num_values = 2; + old_el->values = talloc_zero_array(ctx, DATA_BLOB, 2); + old_el->values[0] = data_blob_string_const( + ";" + "cn=grpadttstuser01,cn=users,DC=addom," + "DC=samba,DC=example,DC=com"); + old_el->values[1] = data_blob_string_const( + ";" + "CN=testuser131953,CN=Users,DC=addom,DC=samba," + "DC=example,DC=com"); + + /* + * call log_membership_changes + */ + messages_sent = 0; + log_membership_changes(module, req, new_el, old_el, status); + + /* + * Check the results + */ + assert_int_equal(1, messages_sent); + + check_group_change_message( + 0, + "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com", + "Removed"); + + /* + * Clean up + */ + json_free(&messages[0]); + TALLOC_FREE(ctx); } /* @@ -636,7 +886,7 @@ int main(void) { cmocka_unit_test(test_get_parsed_dns), cmocka_unit_test(test_dn_compare), cmocka_unit_test(test_get_primary_group_dn), - + cmocka_unit_test(test_log_membership_changes_removed), }; cmocka_set_message_output(CM_OUTPUT_SUBUNIT);