2 Unit tests for the dsdb group auditing code in group_audit.c
4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 int ldb_group_audit_log_module_init(const char *version);
27 #include "../group_audit.c"
29 #include "lib/ldb/include/ldb_private.h"
33 * Mock version of dsdb_search_one
35 struct ldb_dn *g_basedn = NULL;
36 enum ldb_scope g_scope;
37 const char * const *g_attrs = NULL;
38 uint32_t g_dsdb_flags;
39 const char *g_exp_fmt;
40 const char *g_dn = NULL;
41 int g_status = LDB_SUCCESS;
43 int dsdb_search_one(struct ldb_context *ldb,
45 struct ldb_message **msg,
46 struct ldb_dn *basedn,
48 const char * const *attrs,
50 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
52 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, g_dn);
53 struct ldb_message *m = talloc_zero(mem_ctx, struct ldb_message);
60 g_dsdb_flags = dsdb_flags;
67 * Mock version of audit_log_json
70 #define MAX_EXPECTED_MESSAGES 16
71 static struct json_object messages[MAX_EXPECTED_MESSAGES];
72 static size_t messages_sent = 0;
74 void audit_message_send(
75 struct imessaging_context *msg_ctx,
76 const char *server_name,
77 uint32_t message_type,
78 struct json_object *message)
80 messages[messages_sent].root = json_deep_copy(message->root);
81 messages[messages_sent].valid = message->valid;
85 #define check_group_change_message(m, u, a)\
86 _check_group_change_message(m, u, a, __FILE__, __LINE__);
88 * declare the internal cmocka cm_print_error so that we can output messages
91 void cm_print_error(const char * const format, ...);
94 * Validate a group change JSON audit message
96 * It should contain 3 elements.
97 * Have a type of "groupChange"
98 * Have a groupChange element
100 * The group change element should have 10 elements.
102 * There should be a user element matching the expected value
103 * There should be an action matching the expected value
105 static void _check_group_change_message(
112 struct json_object json;
113 json_t *audit = NULL;
118 json = messages[message];
121 * Validate the root JSON element
122 * check the number of elements
124 if (json_object_size(json.root) != 3) {
126 "Unexpected number of elements in root %zu != %d\n",
127 json_object_size(json.root),
133 * Check the type element
135 v = json_object_get(json.root, "type");
137 cm_print_error( "No \"type\" element\n");
141 value = json_string_value(v);
142 cmp = strcmp("groupChange", value);
145 "Unexpected type \"%s\" != \"groupChange\"\n",
151 audit = json_object_get(json.root, "groupChange");
153 cm_print_error("No groupChange element\n");
158 * Validate the groupChange element
160 if (json_object_size(audit) != 10) {
162 "Unexpected number of elements in groupChange "
164 json_object_size(audit),
169 * Validate the user element
171 v = json_object_get(audit, "user");
173 cm_print_error( "No user element\n");
177 value = json_string_value(v);
178 cmp = strcmp(user, value);
181 "Unexpected user name \"%s\" != \"%s\"\n",
188 * Validate the action element
190 v = json_object_get(audit, "action");
192 cm_print_error( "No action element\n");
196 value = json_string_value(v);
197 cmp = strcmp(action, value);
200 "Unexpected action \"%s\" != \"%s\"\n",
207 #define check_timestamp(b, t)\
208 _check_timestamp(b, t, __FILE__, __LINE__);
210 * Test helper to check ISO 8601 timestamps for validity
212 static void _check_timestamp(
214 const char *timestamp,
229 * Convert the ISO 8601 timestamp into a time_t
230 * Note for convenience we ignore the value of the microsecond
231 * part of the time stamp.
235 "%4d-%2d-%2dT%2d:%2d:%2d.%6d%1c%4d",
245 assert_int_equal(9, rc);
246 tm.tm_year = tm.tm_year - 1900;
247 tm.tm_mon = tm.tm_mon - 1;
249 actual = mktime(&tm);
252 * The time stamp should be before <= actual <= after
254 if (difftime(actual, before) < 0) {
261 "time stamp \"%s\" is before start time \"%s\"\n",
266 if (difftime(after, actual) < 0) {
273 "time stamp \"%s\" is after finish time \"%s\"\n",
280 #define check_version(v, m, n)\
281 _check_version(v, m, n, __FILE__, __LINE__);
283 * Test helper to validate a version object.
285 static void _check_version(
286 struct json_t *version,
292 struct json_t *v = NULL;
295 if (!json_is_object(version)) {
296 cm_print_error("version is not a JSON object\n");
300 if (json_object_size(version) != 2) {
302 "Unexpected number of elements in version %zu != %d\n",
303 json_object_size(version),
309 * Validate the major version number element
311 v = json_object_get(version, "major");
313 cm_print_error( "No major element\n");
317 value = json_integer_value(v);
318 if (value != major) {
320 "Unexpected major version number \"%d\" != \"%d\"\n",
327 * Validate the minor version number element
329 v = json_object_get(version, "minor");
331 cm_print_error( "No minor element\n");
335 value = json_integer_value(v);
336 if (value != minor) {
338 "Unexpected minor version number \"%d\" != \"%d\"\n",
346 * Test helper to insert a transaction_id into a request.
348 static void add_transaction_id(struct ldb_request *req, const char *id)
351 struct dsdb_control_transaction_identifier *transaction_id = NULL;
353 transaction_id = talloc_zero(
355 struct dsdb_control_transaction_identifier);
356 assert_non_null(transaction_id);
357 GUID_from_string(id, &guid);
358 transaction_id->transaction_guid = guid;
359 ldb_request_add_control(
361 DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID,
367 * Test helper to add a session id and user SID
369 static void add_session_data(
371 struct ldb_context *ldb,
373 const char *user_sid)
375 struct auth_session_info *sess = NULL;
376 struct security_token *token = NULL;
377 struct dom_sid *sid = NULL;
378 struct GUID session_id;
381 sess = talloc_zero(ctx, struct auth_session_info);
382 token = talloc_zero(ctx, struct security_token);
383 sid = talloc_zero(ctx, struct dom_sid);
384 ok = string_to_sid(sid, user_sid);
387 sess->security_token = token;
388 GUID_from_string(session, &session_id);
389 sess->unique_session_token = session_id;
390 ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
393 static void test_get_transaction_id(void **state)
395 struct ldb_request *req = NULL;
397 const char * const ID = "7130cb06-2062-6a1b-409e-3514c26b1773";
398 char *guid_str = NULL;
399 struct GUID_txt_buf guid_buff;
402 TALLOC_CTX *ctx = talloc_new(NULL);
406 * No transaction id, should return a zero guid
408 req = talloc_zero(ctx, struct ldb_request);
409 guid = get_transaction_id(req);
414 * And now test with the transaction_id set
416 req = talloc_zero(ctx, struct ldb_request);
417 assert_non_null(req);
418 add_transaction_id(req, ID);
420 guid = get_transaction_id(req);
421 guid_str = GUID_buf_string(guid, &guid_buff);
422 assert_string_equal(ID, guid_str);
428 static void test_audit_group_hr(void **state)
430 struct ldb_context *ldb = NULL;
431 struct ldb_module *module = NULL;
432 struct ldb_request *req = NULL;
434 struct tsocket_address *ts = NULL;
436 const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
437 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
439 struct GUID transaction_id;
440 const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
444 const char *rs = NULL;
449 TALLOC_CTX *ctx = talloc_new(NULL);
451 ldb = ldb_init(ctx, NULL);
453 GUID_from_string(TRANSACTION, &transaction_id);
455 module = talloc_zero(ctx, struct ldb_module);
458 tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
459 ldb_set_opaque(ldb, "remoteAddress", ts);
461 add_session_data(ctx, ldb, SESSION, SID);
463 req = talloc_zero(ctx, struct ldb_request);
464 req->operation = LDB_ADD;
465 add_transaction_id(req, TRANSACTION);
467 line = audit_group_human_readable(
474 LDB_ERR_OPERATIONS_ERROR);
475 assert_non_null(line);
477 rs = "\\[the-action\\] at \\["
479 "\\] status \\[Operations error\\] "
480 "Remote host \\[ipv4:127.0.0.1:0\\] "
481 "SID \\[S-1-5-21-2470180966-3899876309-2637894779\\] "
482 "Group \\[the-group-name\\] "
483 "User \\[the-user-name\\]";
485 ret = regcomp(®ex, rs, 0);
486 assert_int_equal(0, ret);
488 ret = regexec(®ex, line, 0, NULL, 0);
489 assert_int_equal(0, ret);
497 * test get_parsed_dns
498 * For this test we assume Valgrind or Address Sanitizer will detect any over
499 * runs. Also we don't care that the values are DN's only that the value in the
500 * element is copied to the parsed_dns.
502 static void test_get_parsed_dns(void **state)
504 struct ldb_message_element *el = NULL;
505 struct parsed_dn *dns = NULL;
507 TALLOC_CTX *ctx = talloc_new(NULL);
509 el = talloc_zero(ctx, struct ldb_message_element);
512 * empty element, zero dns
514 dns = get_parsed_dns(ctx, el);
521 el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
522 el->values[0] = data_blob_string_const("The first value");
524 dns = get_parsed_dns(ctx, el);
526 assert_ptr_equal(el->values[0].data, dns[0].v->data);
527 assert_int_equal(el->values[0].length, dns[0].v->length);
536 el = talloc_zero(ctx, struct ldb_message_element);
538 el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
539 el->values[0] = data_blob_string_const("The first value");
540 el->values[0] = data_blob_string_const("The second value");
542 dns = get_parsed_dns(ctx, el);
544 assert_ptr_equal(el->values[0].data, dns[0].v->data);
545 assert_int_equal(el->values[0].length, dns[0].v->length);
547 assert_ptr_equal(el->values[1].data, dns[1].v->data);
548 assert_int_equal(el->values[1].length, dns[1].v->length);
553 static void test_dn_compare(void **state)
556 struct ldb_context *ldb = NULL;
565 TALLOC_CTX *ctx = talloc_new(NULL);
566 const struct GUID *ZERO_GUID = talloc_zero(ctx, struct GUID);
568 ldb = ldb_init(ctx, NULL);
569 ldb_register_samba_handlers(ldb);
573 * Identical binary DN's
575 ab = data_blob_string_const(
576 "<GUID=fbee08fd-6f75-4bd4-af3f-e4f063a6379e>;"
577 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
578 a = talloc_zero(ctx, struct parsed_dn);
581 bb = data_blob_string_const(
582 "<GUID=fbee08fd-6f75-4bd4-af3f-e4f063a6379e>;"
583 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
584 b = talloc_zero(ctx, struct parsed_dn);
587 res = dn_compare(ctx, ldb, a, b);
588 assert_int_equal(BINARY_EQUAL, res);
590 * DN's should not have been parsed
592 assert_null(a->dsdb_dn);
593 assert_memory_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
594 assert_null(b->dsdb_dn);
595 assert_memory_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
601 * differing binary DN's but equal GUID's
603 ab = data_blob_string_const(
604 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
605 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
606 a = talloc_zero(ctx, struct parsed_dn);
609 bb = data_blob_string_const(
610 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
611 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
612 b = talloc_zero(ctx, struct parsed_dn);
615 res = dn_compare(ctx, ldb, a, b);
616 assert_int_equal(EQUAL, res);
618 * DN's should have been parsed
620 assert_non_null(a->dsdb_dn);
621 assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
622 assert_non_null(b->dsdb_dn);
623 assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
629 * differing binary DN's but and second guid greater
631 ab = data_blob_string_const(
632 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651d>;"
633 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
634 a = talloc_zero(ctx, struct parsed_dn);
637 bb = data_blob_string_const(
638 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
639 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
640 b = talloc_zero(ctx, struct parsed_dn);
643 res = dn_compare(ctx, ldb, a, b);
644 assert_int_equal(LESS_THAN, res);
646 * DN's should have been parsed
648 assert_non_null(a->dsdb_dn);
649 assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
650 assert_non_null(b->dsdb_dn);
651 assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
657 * differing binary DN's but and second guid less
659 ab = data_blob_string_const(
660 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651d>;"
661 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
662 a = talloc_zero(ctx, struct parsed_dn);
665 bb = data_blob_string_const(
666 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651c>;"
667 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
668 b = talloc_zero(ctx, struct parsed_dn);
671 res = dn_compare(ctx, ldb, a, b);
672 assert_int_equal(GREATER_THAN, res);
674 * DN's should have been parsed
676 assert_non_null(a->dsdb_dn);
677 assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
678 assert_non_null(b->dsdb_dn);
679 assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
687 static void test_get_primary_group_dn(void **state)
690 struct ldb_context *ldb = NULL;
691 struct ldb_module *module = NULL;
692 const uint32_t RID = 71;
694 const char *SID = "S-1-5-21-2470180966-3899876309-2637894779";
695 const char *DN = "OU=Things,DC=ad,DC=testing,DC=samba,DC=org";
698 TALLOC_CTX *ctx = talloc_new(NULL);
700 ldb = ldb_init(ctx, NULL);
701 ldb_register_samba_handlers(ldb);
703 module = talloc_zero(ctx, struct ldb_module);
707 * Pass an empty dom sid this will cause dom_sid_split_rid to fail;
708 * assign to sid.num_auths to suppress a valgrind warning.
711 dn = get_primary_group_dn(ctx, module, &sid, RID);
717 assert_true(string_to_sid(&sid, SID));
719 dn = get_primary_group_dn(ctx, module, &sid, RID);
721 assert_string_equal(DN, dn);
722 assert_int_equal(LDB_SCOPE_BASE, g_scope);
723 assert_int_equal(0, g_dsdb_flags);
724 assert_null(g_attrs);
725 assert_null(g_exp_fmt);
727 ("<SID=S-1-5-21-2470180966-3899876309-71>",
728 ldb_dn_get_extended_linearized(ctx, g_basedn, 1));
731 * Test dsdb search failure
733 g_status = LDB_ERR_NO_SUCH_OBJECT;
734 dn = get_primary_group_dn(ctx, module, &sid, RID);
741 static void test_audit_group_json(void **state)
743 struct ldb_context *ldb = NULL;
744 struct ldb_module *module = NULL;
745 struct ldb_request *req = NULL;
747 struct tsocket_address *ts = NULL;
749 const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
750 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
752 struct GUID transaction_id;
753 const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
756 struct json_object json;
757 json_t *audit = NULL;
763 TALLOC_CTX *ctx = talloc_new(NULL);
765 ldb = ldb_init(ctx, NULL);
767 GUID_from_string(TRANSACTION, &transaction_id);
769 module = talloc_zero(ctx, struct ldb_module);
772 tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
773 ldb_set_opaque(ldb, "remoteAddress", ts);
775 add_session_data(ctx, ldb, SESSION, SID);
777 req = talloc_zero(ctx, struct ldb_request);
778 req->operation = LDB_ADD;
779 add_transaction_id(req, TRANSACTION);
782 json = audit_group_json(
788 LDB_ERR_OPERATIONS_ERROR);
789 assert_int_equal(3, json_object_size(json.root));
791 v = json_object_get(json.root, "type");
793 assert_string_equal("groupChange", json_string_value(v));
795 v = json_object_get(json.root, "timestamp");
797 assert_true(json_is_string(v));
798 check_timestamp(before, json_string_value(v));
800 audit = json_object_get(json.root, "groupChange");
801 assert_non_null(audit);
802 assert_true(json_is_object(audit));
803 assert_int_equal(10, json_object_size(audit));
805 o = json_object_get(audit, "version");
807 check_version(o, AUDIT_MAJOR, AUDIT_MINOR);
809 v = json_object_get(audit, "statusCode");
811 assert_true(json_is_integer(v));
812 assert_int_equal(LDB_ERR_OPERATIONS_ERROR, json_integer_value(v));
814 v = json_object_get(audit, "status");
816 assert_true(json_is_string(v));
817 assert_string_equal("Operations error", json_string_value(v));
819 v = json_object_get(audit, "user");
821 assert_true(json_is_string(v));
822 assert_string_equal("the-user-name", json_string_value(v));
824 v = json_object_get(audit, "group");
826 assert_true(json_is_string(v));
827 assert_string_equal("the-group-name", json_string_value(v));
829 v = json_object_get(audit, "action");
831 assert_true(json_is_string(v));
832 assert_string_equal("the-action", json_string_value(v));
838 static void setup_ldb(
840 struct ldb_context **ldb,
841 struct ldb_module **module,
846 struct tsocket_address *ts = NULL;
847 struct audit_context *context = NULL;
849 *ldb = ldb_init(ctx, NULL);
850 ldb_register_samba_handlers(*ldb);
853 *module = talloc_zero(ctx, struct ldb_module);
854 (*module)->ldb = *ldb;
856 context = talloc_zero(*module, struct audit_context);
857 context->send_events = true;
858 context->msg_ctx = (struct imessaging_context *) 0x01;
860 ldb_module_set_private(*module, context);
862 tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
863 ldb_set_opaque(*ldb, "remoteAddress", ts);
865 add_session_data(ctx, *ldb, session, sid);
869 * Test the removal of a user from a group.
871 * The new element contains one group member
872 * The old element contains two group member
874 * Expect to see the removed entry logged.
876 * This test confirms bug 13664
877 * https://bugzilla.samba.org/show_bug.cgi?id=13664
879 static void test_log_membership_changes_removed(void **state)
881 struct ldb_context *ldb = NULL;
882 struct ldb_module *module = NULL;
883 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
884 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
885 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
886 const char * const IP = "127.0.0.1";
887 struct ldb_request *req = NULL;
888 struct ldb_message_element *new_el = NULL;
889 struct ldb_message_element *old_el = NULL;
891 TALLOC_CTX *ctx = talloc_new(NULL);
893 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
896 * Build the ldb_request
898 req = talloc_zero(ctx, struct ldb_request);
899 req->operation = LDB_ADD;
900 add_transaction_id(req, TRANSACTION);
903 * Populate the new elements, containing one entry.
904 * Indicating that one element has been removed
906 new_el = talloc_zero(ctx, struct ldb_message_element);
907 new_el->num_values = 1;
908 new_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
909 new_el->values[0] = data_blob_string_const(
910 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
911 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
912 "DC=example,DC=com");
915 * Populate the old elements, with two elements
916 * The first is the same as the one in new elements.
918 old_el = talloc_zero(ctx, struct ldb_message_element);
919 old_el->num_values = 2;
920 old_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
921 old_el->values[0] = data_blob_string_const(
922 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
923 "cn=grpadttstuser01,cn=users,DC=addom,"
924 "DC=samba,DC=example,DC=com");
925 old_el->values[1] = data_blob_string_const(
926 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
927 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
928 "DC=example,DC=com");
931 * call log_membership_changes
934 log_membership_changes(module, req, new_el, old_el, status);
939 assert_int_equal(1, messages_sent);
941 check_group_change_message(
943 "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
949 json_free(&messages[0]);
953 /* test log_membership_changes
955 * old contains 2 user dn's
956 * new contains 0 user dn's
958 * Expect to see both dn's logged as deleted.
960 static void test_log_membership_changes_remove_all(void **state)
962 struct ldb_context *ldb = NULL;
963 struct ldb_module *module = NULL;
964 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
965 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
966 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
967 const char * const IP = "127.0.0.1";
968 struct ldb_request *req = NULL;
969 struct ldb_message_element *new_el = NULL;
970 struct ldb_message_element *old_el = NULL;
972 TALLOC_CTX *ctx = talloc_new(NULL);
974 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
977 * Build the ldb_request
979 req = talloc_zero(ctx, struct ldb_request);
980 req->operation = LDB_ADD;
981 add_transaction_id(req, TRANSACTION);
984 * Populate the new elements, containing no entries.
985 * Indicating that all elements have been removed
987 new_el = talloc_zero(ctx, struct ldb_message_element);
988 new_el->num_values = 0;
989 new_el->values = NULL;
992 * Populate the old elements, with two elements
994 old_el = talloc_zero(ctx, struct ldb_message_element);
995 old_el->num_values = 2;
996 old_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
997 old_el->values[0] = data_blob_string_const(
998 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
999 "cn=grpadttstuser01,cn=users,DC=addom,"
1000 "DC=samba,DC=example,DC=com");
1001 old_el->values[1] = data_blob_string_const(
1002 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1003 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1004 "DC=example,DC=com");
1007 * call log_membership_changes
1010 log_membership_changes( module, req, new_el, old_el, status);
1015 assert_int_equal(2, messages_sent);
1017 check_group_change_message(
1019 "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1022 check_group_change_message(
1024 "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
1030 json_free(&messages[0]);
1031 json_free(&messages[1]);
1035 /* test log_membership_changes
1039 * Old entries contains a single user dn
1040 * New entries contains 2 user dn's, one matching the dn in old entries
1042 * Should see a single new entry logged.
1044 static void test_log_membership_changes_added(void **state)
1046 struct ldb_context *ldb = NULL;
1047 struct ldb_module *module = NULL;
1048 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1049 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1050 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1051 const char * const IP = "127.0.0.1";
1052 struct ldb_request *req = NULL;
1053 struct ldb_message_element *new_el = NULL;
1054 struct ldb_message_element *old_el = NULL;
1056 TALLOC_CTX *ctx = talloc_new(NULL);
1058 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1061 * Build the ldb_request
1063 req = talloc_zero(ctx, struct ldb_request);
1064 req->operation = LDB_ADD;
1065 add_transaction_id(req, TRANSACTION);
1068 * Populate the old elements adding a single entry.
1070 old_el = talloc_zero(ctx, struct ldb_message_element);
1071 old_el->num_values = 1;
1072 old_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1073 old_el->values[0] = data_blob_string_const(
1074 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1075 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1076 "DC=example,DC=com");
1079 * Populate the new elements adding two entries. One matches the entry
1080 * in old elements. We expect to see the other element logged as Added
1082 new_el = talloc_zero(ctx, struct ldb_message_element);
1083 new_el->num_values = 2;
1084 new_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1085 new_el->values[0] = data_blob_string_const(
1086 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1087 "cn=grpadttstuser01,cn=users,DC=addom,"
1088 "DC=samba,DC=example,DC=com");
1089 new_el->values[1] = data_blob_string_const(
1090 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1091 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1092 "DC=example,DC=com");
1095 * call log_membership_changes
1098 log_membership_changes( module, req, new_el, old_el, status);
1103 assert_int_equal(1, messages_sent);
1105 check_group_change_message(
1107 "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1113 json_free(&messages[0]);
1118 * test log_membership_changes.
1120 * Old entries is empty
1121 * New entries contains 2 user dn's
1123 * Expect to see log messages for two added users
1125 static void test_log_membership_changes_add_to_empty(void **state)
1127 struct ldb_context *ldb = NULL;
1128 struct ldb_module *module = NULL;
1129 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1130 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1131 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1132 const char * const IP = "127.0.0.1";
1133 struct ldb_request *req = NULL;
1134 struct ldb_message_element *new_el = NULL;
1135 struct ldb_message_element *old_el = NULL;
1137 TALLOC_CTX *ctx = talloc_new(NULL);
1140 * Set up the ldb and module structures
1142 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1145 * Build the request structure
1147 req = talloc_zero(ctx, struct ldb_request);
1148 req->operation = LDB_ADD;
1149 add_transaction_id(req, TRANSACTION);
1152 * Build the element containing the old values
1154 old_el = talloc_zero(ctx, struct ldb_message_element);
1155 old_el->num_values = 0;
1156 old_el->values = NULL;
1159 * Build the element containing the new values
1161 new_el = talloc_zero(ctx, struct ldb_message_element);
1162 new_el->num_values = 2;
1163 new_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1164 new_el->values[0] = data_blob_string_const(
1165 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1166 "cn=grpadttstuser01,cn=users,DC=addom,"
1167 "DC=samba,DC=example,DC=com");
1168 new_el->values[1] = data_blob_string_const(
1169 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1170 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1171 "DC=example,DC=com");
1174 * Run log membership changes
1177 log_membership_changes( module, req, new_el, old_el, status);
1178 assert_int_equal(2, messages_sent);
1180 check_group_change_message(
1182 "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1185 check_group_change_message(
1187 "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
1190 json_free(&messages[0]);
1191 json_free(&messages[1]);
1195 /* test log_membership_changes
1197 * Test Replication Meta Data flag handling.
1199 * 4 entries in old and new entries with their RMD_FLAGS set as below:
1202 * 2) 1 1 Both deleted, no change not logged
1203 * 3) 0 1 New tagged as deleted, log as deleted
1204 * 4) 1 0 Has been undeleted, log as an add
1206 * Should see a single new entry logged.
1208 static void test_log_membership_changes_rmd_flags(void **state)
1210 struct ldb_context *ldb = NULL;
1211 struct ldb_module *module = NULL;
1212 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1213 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1214 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1215 const char * const IP = "127.0.0.1";
1216 struct ldb_request *req = NULL;
1217 struct ldb_message_element *new_el = NULL;
1218 struct ldb_message_element *old_el = NULL;
1220 TALLOC_CTX *ctx = talloc_new(NULL);
1222 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1225 * Build the ldb_request
1227 req = talloc_zero(ctx, struct ldb_request);
1228 req->operation = LDB_ADD;
1229 add_transaction_id(req, TRANSACTION);
1232 * Populate the old elements.
1234 old_el = talloc_zero(ctx, struct ldb_message_element);
1235 old_el->num_values = 4;
1236 old_el->values = talloc_zero_array(ctx, DATA_BLOB, 4);
1237 old_el->values[0] = data_blob_string_const(
1238 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1240 "cn=grpadttstuser01,cn=users,DC=addom,"
1241 "DC=samba,DC=example,DC=com");
1242 old_el->values[1] = data_blob_string_const(
1243 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681c>;"
1245 "cn=grpadttstuser02,cn=users,DC=addom,"
1246 "DC=samba,DC=example,DC=com");
1247 old_el->values[2] = data_blob_string_const(
1248 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681d>;"
1250 "cn=grpadttstuser03,cn=users,DC=addom,"
1251 "DC=samba,DC=example,DC=com");
1252 old_el->values[3] = data_blob_string_const(
1253 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681e>;"
1255 "cn=grpadttstuser04,cn=users,DC=addom,"
1256 "DC=samba,DC=example,DC=com");
1259 * Populate the new elements.
1261 new_el = talloc_zero(ctx, struct ldb_message_element);
1262 new_el->num_values = 4;
1263 new_el->values = talloc_zero_array(ctx, DATA_BLOB, 4);
1264 new_el->values[0] = data_blob_string_const(
1265 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1267 "cn=grpadttstuser01,cn=users,DC=addom,"
1268 "DC=samba,DC=example,DC=com");
1269 new_el->values[1] = data_blob_string_const(
1270 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681c>;"
1272 "cn=grpadttstuser02,cn=users,DC=addom,"
1273 "DC=samba,DC=example,DC=com");
1274 new_el->values[2] = data_blob_string_const(
1275 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681d>;"
1277 "cn=grpadttstuser03,cn=users,DC=addom,"
1278 "DC=samba,DC=example,DC=com");
1279 new_el->values[3] = data_blob_string_const(
1280 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681e>;"
1282 "cn=grpadttstuser04,cn=users,DC=addom,"
1283 "DC=samba,DC=example,DC=com");
1286 * call log_membership_changes
1289 log_membership_changes( module, req, new_el, old_el, status);
1294 assert_int_equal(2, messages_sent);
1296 check_group_change_message(
1298 "cn=grpadttstuser03,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1300 check_group_change_message(
1302 "cn=grpadttstuser04,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1308 json_free(&messages[0]);
1309 json_free(&messages[1]);
1314 * Note: to run under valgrind us:
1315 * valgrind --suppressions=test_group_audit.valgrind bin/test_group_audit
1316 * This suppresses the errors generated because the ldb_modules are not
1321 const struct CMUnitTest tests[] = {
1322 cmocka_unit_test(test_audit_group_json),
1323 cmocka_unit_test(test_get_transaction_id),
1324 cmocka_unit_test(test_audit_group_hr),
1325 cmocka_unit_test(test_get_parsed_dns),
1326 cmocka_unit_test(test_dn_compare),
1327 cmocka_unit_test(test_get_primary_group_dn),
1328 cmocka_unit_test(test_log_membership_changes_removed),
1329 cmocka_unit_test(test_log_membership_changes_remove_all),
1330 cmocka_unit_test(test_log_membership_changes_added),
1331 cmocka_unit_test(test_log_membership_changes_add_to_empty),
1332 cmocka_unit_test(test_log_membership_changes_rmd_flags),
1335 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
1336 return cmocka_run_group_tests(tests, NULL, NULL);