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;
116 json = messages[message];
119 * Validate the root JSON element
120 * check the number of elements
122 if (json_object_size(json.root) != 3) {
124 "Unexpected number of elements in root %zu != %d\n",
125 json_object_size(json.root),
131 * Check the type element
133 v = json_object_get(json.root, "type");
135 cm_print_error( "No \"type\" element\n");
139 value = json_string_value(v);
140 if (strncmp("groupChange", value, strlen("groupChange") != 0)) {
142 "Unexpected type \"%s\" != \"groupChange\"\n",
148 audit = json_object_get(json.root, "groupChange");
150 cm_print_error("No groupChange element\n");
155 * Validate the groupChange element
157 if (json_object_size(audit) != 10) {
159 "Unexpected number of elements in groupChange "
161 json_object_size(audit),
166 * Validate the user element
168 v = json_object_get(audit, "user");
170 cm_print_error( "No user element\n");
174 value = json_string_value(v);
175 if (strncmp(user, value, strlen(user) != 0)) {
177 "Unexpected user name \"%s\" != \"%s\"\n",
184 * Validate the action element
186 v = json_object_get(audit, "action");
188 cm_print_error( "No action element\n");
192 value = json_string_value(v);
193 if (strncmp(action, value, strlen(action) != 0)) {
195 "Unexpected action \"%s\" != \"%s\"\n",
202 #define check_timestamp(b, t)\
203 _check_timestamp(b, t, __FILE__, __LINE__);
205 * Test helper to check ISO 8601 timestamps for validity
207 static void _check_timestamp(
209 const char *timestamp,
224 * Convert the ISO 8601 timestamp into a time_t
225 * Note for convenience we ignore the value of the microsecond
226 * part of the time stamp.
230 "%4d-%2d-%2dT%2d:%2d:%2d.%6d%1c%4d",
240 assert_int_equal(9, rc);
241 tm.tm_year = tm.tm_year - 1900;
242 tm.tm_mon = tm.tm_mon - 1;
244 actual = mktime(&tm);
247 * The time stamp should be before <= actual <= after
249 if (difftime(actual, before) < 0) {
256 "time stamp \"%s\" is before start time \"%s\"\n",
261 if (difftime(after, actual) < 0) {
268 "time stamp \"%s\" is after finish time \"%s\"\n",
275 #define check_version(v, m, n)\
276 _check_version(v, m, n, __FILE__, __LINE__);
278 * Test helper to validate a version object.
280 static void _check_version(
281 struct json_t *version,
287 struct json_t *v = NULL;
290 if (!json_is_object(version)) {
291 cm_print_error("version is not a JSON object\n");
295 if (json_object_size(version) != 2) {
297 "Unexpected number of elements in version %zu != %d\n",
298 json_object_size(version),
304 * Validate the major version number element
306 v = json_object_get(version, "major");
308 cm_print_error( "No major element\n");
312 value = json_integer_value(v);
313 if (value != major) {
315 "Unexpected major version number \"%d\" != \"%d\"\n",
322 * Validate the minor version number element
324 v = json_object_get(version, "minor");
326 cm_print_error( "No minor element\n");
330 value = json_integer_value(v);
331 if (value != minor) {
333 "Unexpected minor version number \"%d\" != \"%d\"\n",
341 * Test helper to insert a transaction_id into a request.
343 static void add_transaction_id(struct ldb_request *req, const char *id)
346 struct dsdb_control_transaction_identifier *transaction_id = NULL;
348 transaction_id = talloc_zero(
350 struct dsdb_control_transaction_identifier);
351 assert_non_null(transaction_id);
352 GUID_from_string(id, &guid);
353 transaction_id->transaction_guid = guid;
354 ldb_request_add_control(
356 DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID,
362 * Test helper to add a session id and user SID
364 static void add_session_data(
366 struct ldb_context *ldb,
368 const char *user_sid)
370 struct auth_session_info *sess = NULL;
371 struct security_token *token = NULL;
372 struct dom_sid *sid = NULL;
373 struct GUID session_id;
376 sess = talloc_zero(ctx, struct auth_session_info);
377 token = talloc_zero(ctx, struct security_token);
378 sid = talloc_zero(ctx, struct dom_sid);
379 ok = string_to_sid(sid, user_sid);
382 sess->security_token = token;
383 GUID_from_string(session, &session_id);
384 sess->unique_session_token = session_id;
385 ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
388 static void test_get_transaction_id(void **state)
390 struct ldb_request *req = NULL;
392 const char * const ID = "7130cb06-2062-6a1b-409e-3514c26b1773";
393 char *guid_str = NULL;
394 struct GUID_txt_buf guid_buff;
397 TALLOC_CTX *ctx = talloc_new(NULL);
401 * No transaction id, should return a zero guid
403 req = talloc_zero(ctx, struct ldb_request);
404 guid = get_transaction_id(req);
409 * And now test with the transaction_id set
411 req = talloc_zero(ctx, struct ldb_request);
412 assert_non_null(req);
413 add_transaction_id(req, ID);
415 guid = get_transaction_id(req);
416 guid_str = GUID_buf_string(guid, &guid_buff);
417 assert_string_equal(ID, guid_str);
423 static void test_audit_group_hr(void **state)
425 struct ldb_context *ldb = NULL;
426 struct ldb_module *module = NULL;
427 struct ldb_request *req = NULL;
429 struct tsocket_address *ts = NULL;
431 const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
432 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
434 struct GUID transaction_id;
435 const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
439 const char *rs = NULL;
444 TALLOC_CTX *ctx = talloc_new(NULL);
446 ldb = ldb_init(ctx, NULL);
448 GUID_from_string(TRANSACTION, &transaction_id);
450 module = talloc_zero(ctx, struct ldb_module);
453 tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
454 ldb_set_opaque(ldb, "remoteAddress", ts);
456 add_session_data(ctx, ldb, SESSION, SID);
458 req = talloc_zero(ctx, struct ldb_request);
459 req->operation = LDB_ADD;
460 add_transaction_id(req, TRANSACTION);
462 line = audit_group_human_readable(
469 LDB_ERR_OPERATIONS_ERROR);
470 assert_non_null(line);
472 rs = "\\[the-action\\] at \\["
474 "\\] status \\[Operations error\\] "
475 "Remote host \\[ipv4:127.0.0.1:0\\] "
476 "SID \\[S-1-5-21-2470180966-3899876309-2637894779\\] "
477 "Group \\[the-group-name\\] "
478 "User \\[the-user-name\\]";
480 ret = regcomp(®ex, rs, 0);
481 assert_int_equal(0, ret);
483 ret = regexec(®ex, line, 0, NULL, 0);
484 assert_int_equal(0, ret);
492 * test get_parsed_dns
493 * For this test we assume Valgrind or Address Sanitizer will detect any over
494 * runs. Also we don't care that the values are DN's only that the value in the
495 * element is copied to the parsed_dns.
497 static void test_get_parsed_dns(void **state)
499 struct ldb_message_element *el = NULL;
500 struct parsed_dn *dns = NULL;
502 TALLOC_CTX *ctx = talloc_new(NULL);
504 el = talloc_zero(ctx, struct ldb_message_element);
507 * empty element, zero dns
509 dns = get_parsed_dns(ctx, el);
516 el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
517 el->values[0] = data_blob_string_const("The first value");
519 dns = get_parsed_dns(ctx, el);
521 assert_ptr_equal(el->values[0].data, dns[0].v->data);
522 assert_int_equal(el->values[0].length, dns[0].v->length);
531 el = talloc_zero(ctx, struct ldb_message_element);
533 el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
534 el->values[0] = data_blob_string_const("The first value");
535 el->values[0] = data_blob_string_const("The second value");
537 dns = get_parsed_dns(ctx, el);
539 assert_ptr_equal(el->values[0].data, dns[0].v->data);
540 assert_int_equal(el->values[0].length, dns[0].v->length);
542 assert_ptr_equal(el->values[1].data, dns[1].v->data);
543 assert_int_equal(el->values[1].length, dns[1].v->length);
548 static void test_dn_compare(void **state)
551 struct ldb_context *ldb = NULL;
560 TALLOC_CTX *ctx = talloc_new(NULL);
561 const struct GUID *ZERO_GUID = talloc_zero(ctx, struct GUID);
563 ldb = ldb_init(ctx, NULL);
564 ldb_register_samba_handlers(ldb);
568 * Identical binary DN's
570 ab = data_blob_string_const(
571 "<GUID=fbee08fd-6f75-4bd4-af3f-e4f063a6379e>;"
572 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
573 a = talloc_zero(ctx, struct parsed_dn);
576 bb = data_blob_string_const(
577 "<GUID=fbee08fd-6f75-4bd4-af3f-e4f063a6379e>;"
578 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
579 b = talloc_zero(ctx, struct parsed_dn);
582 res = dn_compare(ctx, ldb, a, b);
583 assert_int_equal(BINARY_EQUAL, res);
585 * DN's should not have been parsed
587 assert_null(a->dsdb_dn);
588 assert_memory_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
589 assert_null(b->dsdb_dn);
590 assert_memory_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
596 * differing binary DN's but equal GUID's
598 ab = data_blob_string_const(
599 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
600 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
601 a = talloc_zero(ctx, struct parsed_dn);
604 bb = data_blob_string_const(
605 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
606 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
607 b = talloc_zero(ctx, struct parsed_dn);
610 res = dn_compare(ctx, ldb, a, b);
611 assert_int_equal(EQUAL, res);
613 * DN's should have been parsed
615 assert_non_null(a->dsdb_dn);
616 assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
617 assert_non_null(b->dsdb_dn);
618 assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
624 * differing binary DN's but and second guid greater
626 ab = data_blob_string_const(
627 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651d>;"
628 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
629 a = talloc_zero(ctx, struct parsed_dn);
632 bb = data_blob_string_const(
633 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
634 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
635 b = talloc_zero(ctx, struct parsed_dn);
638 res = dn_compare(ctx, ldb, a, b);
639 assert_int_equal(LESS_THAN, res);
641 * DN's should have been parsed
643 assert_non_null(a->dsdb_dn);
644 assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
645 assert_non_null(b->dsdb_dn);
646 assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
652 * differing binary DN's but and second guid less
654 ab = data_blob_string_const(
655 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651d>;"
656 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
657 a = talloc_zero(ctx, struct parsed_dn);
660 bb = data_blob_string_const(
661 "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651c>;"
662 "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
663 b = talloc_zero(ctx, struct parsed_dn);
666 res = dn_compare(ctx, ldb, a, b);
667 assert_int_equal(GREATER_THAN, res);
669 * DN's should have been parsed
671 assert_non_null(a->dsdb_dn);
672 assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
673 assert_non_null(b->dsdb_dn);
674 assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
682 static void test_get_primary_group_dn(void **state)
685 struct ldb_context *ldb = NULL;
686 struct ldb_module *module = NULL;
687 const uint32_t RID = 71;
689 const char *SID = "S-1-5-21-2470180966-3899876309-2637894779";
690 const char *DN = "OU=Things,DC=ad,DC=testing,DC=samba,DC=org";
693 TALLOC_CTX *ctx = talloc_new(NULL);
695 ldb = ldb_init(ctx, NULL);
696 ldb_register_samba_handlers(ldb);
698 module = talloc_zero(ctx, struct ldb_module);
702 * Pass an empty dom sid this will cause dom_sid_split_rid to fail;
703 * assign to sid.num_auths to suppress a valgrind warning.
706 dn = get_primary_group_dn(ctx, module, &sid, RID);
712 assert_true(string_to_sid(&sid, SID));
714 dn = get_primary_group_dn(ctx, module, &sid, RID);
716 assert_string_equal(DN, dn);
717 assert_int_equal(LDB_SCOPE_BASE, g_scope);
718 assert_int_equal(0, g_dsdb_flags);
719 assert_null(g_attrs);
720 assert_null(g_exp_fmt);
722 ("<SID=S-1-5-21-2470180966-3899876309-71>",
723 ldb_dn_get_extended_linearized(ctx, g_basedn, 1));
726 * Test dsdb search failure
728 g_status = LDB_ERR_NO_SUCH_OBJECT;
729 dn = get_primary_group_dn(ctx, module, &sid, RID);
736 static void test_audit_group_json(void **state)
738 struct ldb_context *ldb = NULL;
739 struct ldb_module *module = NULL;
740 struct ldb_request *req = NULL;
742 struct tsocket_address *ts = NULL;
744 const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
745 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
747 struct GUID transaction_id;
748 const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
751 struct json_object json;
752 json_t *audit = NULL;
758 TALLOC_CTX *ctx = talloc_new(NULL);
760 ldb = ldb_init(ctx, NULL);
762 GUID_from_string(TRANSACTION, &transaction_id);
764 module = talloc_zero(ctx, struct ldb_module);
767 tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
768 ldb_set_opaque(ldb, "remoteAddress", ts);
770 add_session_data(ctx, ldb, SESSION, SID);
772 req = talloc_zero(ctx, struct ldb_request);
773 req->operation = LDB_ADD;
774 add_transaction_id(req, TRANSACTION);
777 json = audit_group_json(
783 LDB_ERR_OPERATIONS_ERROR);
784 assert_int_equal(3, json_object_size(json.root));
786 v = json_object_get(json.root, "type");
788 assert_string_equal("groupChange", json_string_value(v));
790 v = json_object_get(json.root, "timestamp");
792 assert_true(json_is_string(v));
793 check_timestamp(before, json_string_value(v));
795 audit = json_object_get(json.root, "groupChange");
796 assert_non_null(audit);
797 assert_true(json_is_object(audit));
798 assert_int_equal(10, json_object_size(audit));
800 o = json_object_get(audit, "version");
802 check_version(o, AUDIT_MAJOR, AUDIT_MINOR);
804 v = json_object_get(audit, "statusCode");
806 assert_true(json_is_integer(v));
807 assert_int_equal(LDB_ERR_OPERATIONS_ERROR, json_integer_value(v));
809 v = json_object_get(audit, "status");
811 assert_true(json_is_string(v));
812 assert_string_equal("Operations error", json_string_value(v));
814 v = json_object_get(audit, "user");
816 assert_true(json_is_string(v));
817 assert_string_equal("the-user-name", json_string_value(v));
819 v = json_object_get(audit, "group");
821 assert_true(json_is_string(v));
822 assert_string_equal("the-group-name", json_string_value(v));
824 v = json_object_get(audit, "action");
826 assert_true(json_is_string(v));
827 assert_string_equal("the-action", json_string_value(v));
833 static void setup_ldb(
835 struct ldb_context **ldb,
836 struct ldb_module **module,
841 struct tsocket_address *ts = NULL;
842 struct audit_context *context = NULL;
844 *ldb = ldb_init(ctx, NULL);
845 ldb_register_samba_handlers(*ldb);
848 *module = talloc_zero(ctx, struct ldb_module);
849 (*module)->ldb = *ldb;
851 context = talloc_zero(*module, struct audit_context);
852 context->send_events = true;
853 context->msg_ctx = (struct imessaging_context *) 0x01;
855 ldb_module_set_private(*module, context);
857 tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
858 ldb_set_opaque(*ldb, "remoteAddress", ts);
860 add_session_data(ctx, *ldb, session, sid);
864 * Test the removal of a user from a group.
866 * The new element contains one group member
867 * The old element contains two group member
869 * Expect to see the removed entry logged.
871 * This test confirms bug 13664
872 * https://bugzilla.samba.org/show_bug.cgi?id=13664
874 static void test_log_membership_changes_removed(void **state)
876 struct ldb_context *ldb = NULL;
877 struct ldb_module *module = NULL;
878 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
879 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
880 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
881 const char * const IP = "127.0.0.1";
882 struct ldb_request *req = NULL;
883 struct ldb_message_element *new_el = NULL;
884 struct ldb_message_element *old_el = NULL;
886 TALLOC_CTX *ctx = talloc_new(NULL);
888 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
891 * Build the ldb_request
893 req = talloc_zero(ctx, struct ldb_request);
894 req->operation = LDB_ADD;
895 add_transaction_id(req, TRANSACTION);
898 * Populate the new elements, containing one entry.
899 * Indicating that one element has been removed
901 new_el = talloc_zero(ctx, struct ldb_message_element);
902 new_el->num_values = 1;
903 new_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
904 new_el->values[0] = data_blob_string_const(
905 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
906 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
907 "DC=example,DC=com");
910 * Populate the old elements, with two elements
911 * The first is the same as the one in new elements.
913 old_el = talloc_zero(ctx, struct ldb_message_element);
914 old_el->num_values = 2;
915 old_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
916 old_el->values[0] = data_blob_string_const(
917 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
918 "cn=grpadttstuser01,cn=users,DC=addom,"
919 "DC=samba,DC=example,DC=com");
920 old_el->values[1] = data_blob_string_const(
921 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
922 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
923 "DC=example,DC=com");
926 * call log_membership_changes
929 log_membership_changes(module, req, new_el, old_el, status);
934 assert_int_equal(1, messages_sent);
936 check_group_change_message(
938 "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
944 json_free(&messages[0]);
948 /* test log_membership_changes
950 * old contains 2 user dn's
951 * new contains 0 user dn's
953 * Expect to see both dn's logged as deleted.
955 static void test_log_membership_changes_remove_all(void **state)
957 struct ldb_context *ldb = NULL;
958 struct ldb_module *module = NULL;
959 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
960 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
961 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
962 const char * const IP = "127.0.0.1";
963 struct ldb_request *req = NULL;
964 struct ldb_message_element *new_el = NULL;
965 struct ldb_message_element *old_el = NULL;
967 TALLOC_CTX *ctx = talloc_new(NULL);
969 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
972 * Build the ldb_request
974 req = talloc_zero(ctx, struct ldb_request);
975 req->operation = LDB_ADD;
976 add_transaction_id(req, TRANSACTION);
979 * Populate the new elements, containing no entries.
980 * Indicating that all elements have been removed
982 new_el = talloc_zero(ctx, struct ldb_message_element);
983 new_el->num_values = 0;
984 new_el->values = NULL;
987 * Populate the old elements, with two elements
989 old_el = talloc_zero(ctx, struct ldb_message_element);
990 old_el->num_values = 2;
991 old_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
992 old_el->values[0] = data_blob_string_const(
993 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
994 "cn=grpadttstuser01,cn=users,DC=addom,"
995 "DC=samba,DC=example,DC=com");
996 old_el->values[1] = data_blob_string_const(
997 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
998 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
999 "DC=example,DC=com");
1002 * call log_membership_changes
1005 log_membership_changes( module, req, new_el, old_el, status);
1010 assert_int_equal(2, messages_sent);
1012 check_group_change_message(
1014 "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1017 check_group_change_message(
1019 "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
1025 json_free(&messages[0]);
1026 json_free(&messages[1]);
1030 /* test log_membership_changes
1034 * Old entries contains a single user dn
1035 * New entries contains 2 user dn's, one matching the dn in old entries
1037 * Should see a single new entry logged.
1039 static void test_log_membership_changes_added(void **state)
1041 struct ldb_context *ldb = NULL;
1042 struct ldb_module *module = NULL;
1043 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1044 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1045 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1046 const char * const IP = "127.0.0.1";
1047 struct ldb_request *req = NULL;
1048 struct ldb_message_element *new_el = NULL;
1049 struct ldb_message_element *old_el = NULL;
1051 TALLOC_CTX *ctx = talloc_new(NULL);
1053 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1056 * Build the ldb_request
1058 req = talloc_zero(ctx, struct ldb_request);
1059 req->operation = LDB_ADD;
1060 add_transaction_id(req, TRANSACTION);
1063 * Populate the old elements adding a single entry.
1065 old_el = talloc_zero(ctx, struct ldb_message_element);
1066 old_el->num_values = 1;
1067 old_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1068 old_el->values[0] = data_blob_string_const(
1069 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1070 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1071 "DC=example,DC=com");
1074 * Populate the new elements adding two entries. One matches the entry
1075 * in old elements. We expect to see the other element logged as Added
1077 new_el = talloc_zero(ctx, struct ldb_message_element);
1078 new_el->num_values = 2;
1079 new_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1080 new_el->values[0] = data_blob_string_const(
1081 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1082 "cn=grpadttstuser01,cn=users,DC=addom,"
1083 "DC=samba,DC=example,DC=com");
1084 new_el->values[1] = data_blob_string_const(
1085 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1086 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1087 "DC=example,DC=com");
1090 * call log_membership_changes
1093 log_membership_changes( module, req, new_el, old_el, status);
1098 assert_int_equal(1, messages_sent);
1100 check_group_change_message(
1102 "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1108 json_free(&messages[0]);
1113 * test log_membership_changes.
1115 * Old entries is empty
1116 * New entries contains 2 user dn's
1118 * Expect to see log messages for two added users
1120 static void test_log_membership_changes_add_to_empty(void **state)
1122 struct ldb_context *ldb = NULL;
1123 struct ldb_module *module = NULL;
1124 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1125 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1126 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1127 const char * const IP = "127.0.0.1";
1128 struct ldb_request *req = NULL;
1129 struct ldb_message_element *new_el = NULL;
1130 struct ldb_message_element *old_el = NULL;
1132 TALLOC_CTX *ctx = talloc_new(NULL);
1135 * Set up the ldb and module structures
1137 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1140 * Build the request structure
1142 req = talloc_zero(ctx, struct ldb_request);
1143 req->operation = LDB_ADD;
1144 add_transaction_id(req, TRANSACTION);
1147 * Build the element containing the old values
1149 old_el = talloc_zero(ctx, struct ldb_message_element);
1150 old_el->num_values = 0;
1151 old_el->values = NULL;
1154 * Build the element containing the new values
1156 new_el = talloc_zero(ctx, struct ldb_message_element);
1157 new_el->num_values = 2;
1158 new_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1159 new_el->values[0] = data_blob_string_const(
1160 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1161 "cn=grpadttstuser01,cn=users,DC=addom,"
1162 "DC=samba,DC=example,DC=com");
1163 new_el->values[1] = data_blob_string_const(
1164 "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1165 "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1166 "DC=example,DC=com");
1169 * Run log membership changes
1172 log_membership_changes( module, req, new_el, old_el, status);
1173 assert_int_equal(2, messages_sent);
1175 check_group_change_message(
1177 "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1180 check_group_change_message(
1182 "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
1185 json_free(&messages[0]);
1186 json_free(&messages[1]);
1190 /* test log_membership_changes
1192 * Test Replication Meta Data flag handling.
1194 * 4 entries in old and new entries with their RMD_FLAGS set as below:
1197 * 2) 1 1 Both deleted, no change not logged
1198 * 3) 0 1 New tagged as deleted, log as deleted
1199 * 4) 1 0 Has been undeleted, log as an add
1201 * Should see a single new entry logged.
1203 static void test_log_membership_changes_rmd_flags(void **state)
1205 struct ldb_context *ldb = NULL;
1206 struct ldb_module *module = NULL;
1207 const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1208 const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1209 const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1210 const char * const IP = "127.0.0.1";
1211 struct ldb_request *req = NULL;
1212 struct ldb_message_element *new_el = NULL;
1213 struct ldb_message_element *old_el = NULL;
1215 TALLOC_CTX *ctx = talloc_new(NULL);
1217 setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1220 * Build the ldb_request
1222 req = talloc_zero(ctx, struct ldb_request);
1223 req->operation = LDB_ADD;
1224 add_transaction_id(req, TRANSACTION);
1227 * Populate the old elements.
1229 old_el = talloc_zero(ctx, struct ldb_message_element);
1230 old_el->num_values = 4;
1231 old_el->values = talloc_zero_array(ctx, DATA_BLOB, 4);
1232 old_el->values[0] = data_blob_string_const(
1233 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1235 "cn=grpadttstuser01,cn=users,DC=addom,"
1236 "DC=samba,DC=example,DC=com");
1237 old_el->values[1] = data_blob_string_const(
1238 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681c>;"
1240 "cn=grpadttstuser02,cn=users,DC=addom,"
1241 "DC=samba,DC=example,DC=com");
1242 old_el->values[2] = data_blob_string_const(
1243 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681d>;"
1245 "cn=grpadttstuser03,cn=users,DC=addom,"
1246 "DC=samba,DC=example,DC=com");
1247 old_el->values[3] = data_blob_string_const(
1248 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681e>;"
1250 "cn=grpadttstuser04,cn=users,DC=addom,"
1251 "DC=samba,DC=example,DC=com");
1254 * Populate the new elements.
1256 new_el = talloc_zero(ctx, struct ldb_message_element);
1257 new_el->num_values = 4;
1258 new_el->values = talloc_zero_array(ctx, DATA_BLOB, 4);
1259 new_el->values[0] = data_blob_string_const(
1260 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1262 "cn=grpadttstuser01,cn=users,DC=addom,"
1263 "DC=samba,DC=example,DC=com");
1264 new_el->values[1] = data_blob_string_const(
1265 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681c>;"
1267 "cn=grpadttstuser02,cn=users,DC=addom,"
1268 "DC=samba,DC=example,DC=com");
1269 new_el->values[2] = data_blob_string_const(
1270 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681d>;"
1272 "cn=grpadttstuser03,cn=users,DC=addom,"
1273 "DC=samba,DC=example,DC=com");
1274 new_el->values[3] = data_blob_string_const(
1275 "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681e>;"
1277 "cn=grpadttstuser04,cn=users,DC=addom,"
1278 "DC=samba,DC=example,DC=com");
1281 * call log_membership_changes
1284 log_membership_changes( module, req, new_el, old_el, status);
1289 assert_int_equal(2, messages_sent);
1291 check_group_change_message(
1293 "cn=grpadttstuser03,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1295 check_group_change_message(
1297 "cn=grpadttstuser04,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1303 json_free(&messages[0]);
1304 json_free(&messages[1]);
1309 * Note: to run under valgrind us:
1310 * valgrind --suppressions=test_group_audit.valgrind bin/test_group_audit
1311 * This suppresses the errors generated because the ldb_modules are not
1316 const struct CMUnitTest tests[] = {
1317 cmocka_unit_test(test_audit_group_json),
1318 cmocka_unit_test(test_get_transaction_id),
1319 cmocka_unit_test(test_audit_group_hr),
1320 cmocka_unit_test(test_get_parsed_dns),
1321 cmocka_unit_test(test_dn_compare),
1322 cmocka_unit_test(test_get_primary_group_dn),
1323 cmocka_unit_test(test_log_membership_changes_removed),
1324 cmocka_unit_test(test_log_membership_changes_remove_all),
1325 cmocka_unit_test(test_log_membership_changes_added),
1326 cmocka_unit_test(test_log_membership_changes_add_to_empty),
1327 cmocka_unit_test(test_log_membership_changes_rmd_flags),
1330 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
1331 return cmocka_run_group_tests(tests, NULL, NULL);