Line data Source code
1 : /*
2 : Unit tests for the dsdb group auditing code in group_audit.c
3 :
4 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include <stdarg.h>
21 : #include <stddef.h>
22 : #include <setjmp.h>
23 : #include <unistd.h>
24 : #include <cmocka.h>
25 :
26 : int ldb_group_audit_log_module_init(const char *version);
27 : #include "../group_audit.c"
28 :
29 : #include "lib/ldb/include/ldb_private.h"
30 : #include <regex.h>
31 :
32 : /*
33 : * Mock version of dsdb_search_one
34 : */
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;
42 : struct ldb_result *g_result = NULL;
43 :
44 2 : int dsdb_search_one(struct ldb_context *ldb,
45 : TALLOC_CTX *mem_ctx,
46 : struct ldb_message **msg,
47 : struct ldb_dn *basedn,
48 : enum ldb_scope scope,
49 : const char * const *attrs,
50 : uint32_t dsdb_flags,
51 : const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(8, 9)
52 : {
53 2 : struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, g_dn);
54 2 : struct ldb_message *m = talloc_zero(mem_ctx, struct ldb_message);
55 2 : m->dn = dn;
56 2 : *msg = m;
57 :
58 2 : g_basedn = basedn;
59 2 : g_scope = scope;
60 2 : g_attrs = attrs;
61 2 : g_dsdb_flags = dsdb_flags;
62 2 : g_exp_fmt = exp_fmt;
63 :
64 2 : return g_status;
65 : }
66 :
67 2 : int dsdb_module_search_dn(
68 : struct ldb_module *module,
69 : TALLOC_CTX *mem_ctx,
70 : struct ldb_result **res,
71 : struct ldb_dn *basedn,
72 : const char * const *attrs,
73 : uint32_t dsdb_flags,
74 : struct ldb_request *parent)
75 : {
76 :
77 2 : g_basedn = basedn;
78 2 : g_attrs = attrs;
79 2 : g_dsdb_flags = dsdb_flags;
80 :
81 2 : *res = g_result;
82 :
83 2 : return g_status;
84 : }
85 : /*
86 : * Mock version of audit_log_json
87 : */
88 :
89 : #define MAX_EXPECTED_MESSAGES 16
90 : static struct json_object messages[MAX_EXPECTED_MESSAGES];
91 : static size_t messages_sent = 0;
92 :
93 11 : void audit_message_send(
94 : struct imessaging_context *msg_ctx,
95 : const char *server_name,
96 : uint32_t message_type,
97 : struct json_object *message)
98 : {
99 11 : messages[messages_sent].root = json_deep_copy(message->root);
100 11 : messages[messages_sent].valid = message->valid;
101 11 : messages_sent++;
102 11 : }
103 :
104 : #define check_group_change_message(m, u, a, e) \
105 : _check_group_change_message(m, u, a, e, __FILE__, __LINE__);
106 : /*
107 : * declare the internal cmocka cm_print_error so that we can output messages
108 : * in sub unit format
109 : */
110 : void cm_print_error(const char * const format, ...);
111 :
112 : /*
113 : * Validate a group change JSON audit message
114 : *
115 : * It should contain 3 elements.
116 : * Have a type of "groupChange"
117 : * Have a groupChange element
118 : *
119 : * The group change element should have 10 elements.
120 : *
121 : * There should be a user element matching the expected value
122 : * There should be an action matching the expected value
123 : */
124 11 : static void _check_group_change_message(const int message,
125 : const char *user,
126 : const char *action,
127 : enum event_id_type event_id,
128 : const char *file,
129 : const int line)
130 : {
131 11 : struct json_object json;
132 11 : json_t *audit = NULL;
133 11 : json_t *v = NULL;
134 11 : const char* value;
135 11 : int int_value;
136 11 : int cmp;
137 :
138 11 : json = messages[message];
139 :
140 : /*
141 : * Validate the root JSON element
142 : * check the number of elements
143 : */
144 11 : if (json_object_size(json.root) != 3) {
145 0 : cm_print_error(
146 : "Unexpected number of elements in root %zu != %d\n",
147 : json_object_size(json.root),
148 : 3);
149 0 : _fail(file, line);
150 : }
151 :
152 : /*
153 : * Check the type element
154 : */
155 11 : v = json_object_get(json.root, "type");
156 11 : if (v == NULL) {
157 0 : cm_print_error( "No \"type\" element\n");
158 0 : _fail(file, line);
159 : }
160 :
161 11 : value = json_string_value(v);
162 11 : cmp = strcmp("groupChange", value);
163 11 : if (cmp != 0) {
164 0 : cm_print_error(
165 : "Unexpected type \"%s\" != \"groupChange\"\n",
166 : value);
167 0 : _fail(file, line);
168 : }
169 :
170 :
171 11 : audit = json_object_get(json.root, "groupChange");
172 11 : if (audit == NULL) {
173 0 : cm_print_error("No groupChange element\n");
174 0 : _fail(file, line);
175 : }
176 :
177 : /*
178 : * Validate the groupChange element
179 : */
180 11 : if ((event_id == EVT_ID_NONE && json_object_size(audit) != 10) ||
181 9 : (event_id != EVT_ID_NONE && json_object_size(audit) != 11)) {
182 0 : cm_print_error("Unexpected number of elements in groupChange "
183 : "%zu != %d\n",
184 : json_object_size(audit),
185 : 11);
186 0 : _fail(file, line);
187 : }
188 : /*
189 : * Validate the user element
190 : */
191 11 : v = json_object_get(audit, "user");
192 11 : if (v == NULL) {
193 0 : cm_print_error( "No user element\n");
194 0 : _fail(file, line);
195 : }
196 :
197 11 : value = json_string_value(v);
198 11 : cmp = strcmp(user, value);
199 11 : if (cmp != 0) {
200 0 : cm_print_error(
201 : "Unexpected user name \"%s\" != \"%s\"\n",
202 : value,
203 : user);
204 0 : _fail(file, line);
205 : }
206 : /*
207 : * Validate the action element
208 : */
209 11 : v = json_object_get(audit, "action");
210 11 : if (v == NULL) {
211 0 : cm_print_error( "No action element\n");
212 0 : _fail(file, line);
213 : }
214 :
215 11 : value = json_string_value(v);
216 11 : cmp = strcmp(action, value);
217 11 : if (cmp != 0) {
218 0 : print_error(
219 : "Unexpected action \"%s\" != \"%s\"\n",
220 : value,
221 : action);
222 0 : _fail(file, line);
223 : }
224 :
225 : /*
226 : * Validate the eventId element
227 : */
228 11 : v = json_object_get(audit, "eventId");
229 11 : if (event_id == EVT_ID_NONE) {
230 2 : if (v != NULL) {
231 0 : int_value = json_integer_value(v);
232 0 : cm_print_error("Unexpected eventId \"%d\", it should "
233 : "NOT be present",
234 : int_value);
235 0 : _fail(file, line);
236 : }
237 : }
238 : else {
239 9 : if (v == NULL) {
240 0 : cm_print_error("No eventId element\n");
241 0 : _fail(file, line);
242 : }
243 :
244 9 : int_value = json_integer_value(v);
245 9 : if (int_value != event_id) {
246 0 : cm_print_error("Unexpected eventId \"%d\" != \"%d\"\n",
247 : int_value,
248 : event_id);
249 0 : _fail(file, line);
250 : }
251 : }
252 11 : }
253 :
254 : #define check_timestamp(b, t)\
255 : _check_timestamp(b, t, __FILE__, __LINE__);
256 : /*
257 : * Test helper to check ISO 8601 timestamps for validity
258 : */
259 3 : static void _check_timestamp(
260 : time_t before,
261 : const char *timestamp,
262 : const char *file,
263 : const int line)
264 : {
265 3 : int rc;
266 3 : int usec, tz;
267 3 : char c[2];
268 3 : struct tm tm;
269 3 : time_t after;
270 3 : time_t actual;
271 3 : struct timeval tv;
272 :
273 :
274 3 : rc = gettimeofday(&tv, NULL);
275 3 : assert_return_code(rc, errno);
276 3 : after = tv.tv_sec;
277 :
278 : /*
279 : * Convert the ISO 8601 timestamp into a time_t
280 : * Note for convenience we ignore the value of the microsecond
281 : * part of the time stamp.
282 : */
283 3 : rc = sscanf(
284 : timestamp,
285 : "%4d-%2d-%2dT%2d:%2d:%2d.%6d%1c%4d",
286 : &tm.tm_year,
287 : &tm.tm_mon,
288 : &tm.tm_mday,
289 : &tm.tm_hour,
290 : &tm.tm_min,
291 : &tm.tm_sec,
292 : &usec,
293 : c,
294 : &tz);
295 3 : assert_int_equal(9, rc);
296 3 : tm.tm_year = tm.tm_year - 1900;
297 3 : tm.tm_mon = tm.tm_mon - 1;
298 3 : tm.tm_isdst = -1;
299 3 : actual = mktime(&tm);
300 :
301 : /*
302 : * The time stamp should be before <= actual <= after
303 : */
304 3 : if (difftime(actual, before) < 0) {
305 0 : char buffer[40];
306 0 : strftime(buffer,
307 : sizeof(buffer)-1,
308 : "%Y-%m-%dT%T",
309 0 : localtime(&before));
310 0 : cm_print_error(
311 : "time stamp \"%s\" is before start time \"%s\"\n",
312 : timestamp,
313 : buffer);
314 0 : _fail(file, line);
315 : }
316 3 : if (difftime(after, actual) < 0) {
317 0 : char buffer[40];
318 0 : strftime(buffer,
319 : sizeof(buffer)-1,
320 : "%Y-%m-%dT%T",
321 0 : localtime(&after));
322 0 : cm_print_error(
323 : "time stamp \"%s\" is after finish time \"%s\"\n",
324 : timestamp,
325 : buffer);
326 0 : _fail(file, line);
327 : }
328 3 : }
329 :
330 : #define check_version(v, m, n)\
331 : _check_version(v, m, n, __FILE__, __LINE__);
332 : /*
333 : * Test helper to validate a version object.
334 : */
335 3 : static void _check_version(
336 : struct json_t *version,
337 : int major,
338 : int minor,
339 : const char* file,
340 : const int line)
341 : {
342 3 : struct json_t *v = NULL;
343 3 : int value;
344 :
345 3 : if (!json_is_object(version)) {
346 0 : cm_print_error("version is not a JSON object\n");
347 0 : _fail(file, line);
348 : }
349 :
350 3 : if (json_object_size(version) != 2) {
351 0 : cm_print_error(
352 : "Unexpected number of elements in version %zu != %d\n",
353 : json_object_size(version),
354 : 2);
355 0 : _fail(file, line);
356 : }
357 :
358 : /*
359 : * Validate the major version number element
360 : */
361 3 : v = json_object_get(version, "major");
362 3 : if (v == NULL) {
363 0 : cm_print_error( "No major element\n");
364 0 : _fail(file, line);
365 : }
366 :
367 3 : value = json_integer_value(v);
368 3 : if (value != major) {
369 0 : print_error(
370 : "Unexpected major version number \"%d\" != \"%d\"\n",
371 : value,
372 : major);
373 0 : _fail(file, line);
374 : }
375 :
376 : /*
377 : * Validate the minor version number element
378 : */
379 3 : v = json_object_get(version, "minor");
380 3 : if (v == NULL) {
381 0 : cm_print_error( "No minor element\n");
382 0 : _fail(file, line);
383 : }
384 :
385 3 : value = json_integer_value(v);
386 3 : if (value != minor) {
387 0 : print_error(
388 : "Unexpected minor version number \"%d\" != \"%d\"\n",
389 : value,
390 : minor);
391 0 : _fail(file, line);
392 : }
393 3 : }
394 :
395 : /*
396 : * Test helper to insert a transaction_id into a request.
397 : */
398 13 : static void add_transaction_id(struct ldb_request *req, const char *id)
399 : {
400 13 : struct GUID guid;
401 13 : struct dsdb_control_transaction_identifier *transaction_id = NULL;
402 :
403 13 : transaction_id = talloc_zero(
404 : req,
405 : struct dsdb_control_transaction_identifier);
406 13 : assert_non_null(transaction_id);
407 13 : GUID_from_string(id, &guid);
408 13 : transaction_id->transaction_guid = guid;
409 13 : ldb_request_add_control(
410 : req,
411 : DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID,
412 : false,
413 : transaction_id);
414 13 : }
415 :
416 : /*
417 : * Test helper to add a session id and user SID
418 : */
419 12 : static void add_session_data(
420 : TALLOC_CTX *ctx,
421 : struct ldb_context *ldb,
422 : const char *session,
423 : const char *user_sid)
424 : {
425 12 : struct auth_session_info *sess = NULL;
426 12 : struct security_token *token = NULL;
427 12 : struct dom_sid *sid = NULL;
428 12 : struct GUID session_id;
429 12 : bool ok;
430 :
431 12 : sess = talloc_zero(ctx, struct auth_session_info);
432 12 : token = talloc_zero(ctx, struct security_token);
433 12 : sid = talloc_zero(ctx, struct dom_sid);
434 12 : ok = string_to_sid(sid, user_sid);
435 12 : assert_true(ok);
436 12 : token->sids = sid;
437 12 : sess->security_token = token;
438 12 : GUID_from_string(session, &session_id);
439 12 : sess->unique_session_token = session_id;
440 12 : ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
441 12 : }
442 :
443 1 : static void test_get_transaction_id(void **state)
444 : {
445 1 : struct ldb_request *req = NULL;
446 1 : struct GUID *guid;
447 1 : const char * const ID = "7130cb06-2062-6a1b-409e-3514c26b1773";
448 1 : char *guid_str = NULL;
449 1 : struct GUID_txt_buf guid_buff;
450 :
451 :
452 1 : TALLOC_CTX *ctx = talloc_new(NULL);
453 :
454 :
455 : /*
456 : * No transaction id, should return a zero guid
457 : */
458 1 : req = talloc_zero(ctx, struct ldb_request);
459 1 : guid = get_transaction_id(req);
460 1 : assert_null(guid);
461 1 : TALLOC_FREE(req);
462 :
463 : /*
464 : * And now test with the transaction_id set
465 : */
466 1 : req = talloc_zero(ctx, struct ldb_request);
467 1 : assert_non_null(req);
468 1 : add_transaction_id(req, ID);
469 :
470 1 : guid = get_transaction_id(req);
471 1 : guid_str = GUID_buf_string(guid, &guid_buff);
472 1 : assert_string_equal(ID, guid_str);
473 1 : TALLOC_FREE(req);
474 :
475 1 : TALLOC_FREE(ctx);
476 1 : }
477 :
478 1 : static void test_audit_group_hr(void **state)
479 : {
480 1 : struct ldb_context *ldb = NULL;
481 1 : struct ldb_module *module = NULL;
482 1 : struct ldb_request *req = NULL;
483 :
484 1 : struct tsocket_address *ts = NULL;
485 :
486 1 : const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
487 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
488 :
489 1 : struct GUID transaction_id;
490 1 : const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
491 :
492 :
493 1 : char *line = NULL;
494 1 : const char *rs = NULL;
495 1 : regex_t regex;
496 1 : int ret;
497 :
498 :
499 1 : TALLOC_CTX *ctx = talloc_new(NULL);
500 :
501 1 : ldb = ldb_init(ctx, NULL);
502 :
503 1 : GUID_from_string(TRANSACTION, &transaction_id);
504 :
505 1 : module = talloc_zero(ctx, struct ldb_module);
506 1 : module->ldb = ldb;
507 :
508 1 : tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
509 1 : ldb_set_opaque(ldb, "remoteAddress", ts);
510 :
511 1 : add_session_data(ctx, ldb, SESSION, SID);
512 :
513 1 : req = talloc_zero(ctx, struct ldb_request);
514 1 : req->operation = LDB_ADD;
515 1 : add_transaction_id(req, TRANSACTION);
516 :
517 1 : line = audit_group_human_readable(
518 : ctx,
519 : module,
520 : req,
521 : "the-action",
522 : "the-user-name",
523 : "the-group-name",
524 : LDB_ERR_OPERATIONS_ERROR);
525 1 : assert_non_null(line);
526 :
527 1 : rs = "\\[the-action\\] at \\["
528 : "[^]]*"
529 : "\\] status \\[Operations error\\] "
530 : "Remote host \\[ipv4:127.0.0.1:0\\] "
531 : "SID \\[S-1-5-21-2470180966-3899876309-2637894779\\] "
532 : "Group \\[the-group-name\\] "
533 : "User \\[the-user-name\\]";
534 :
535 1 : ret = regcomp(®ex, rs, 0);
536 1 : assert_int_equal(0, ret);
537 :
538 1 : ret = regexec(®ex, line, 0, NULL, 0);
539 1 : assert_int_equal(0, ret);
540 :
541 1 : regfree(®ex);
542 1 : TALLOC_FREE(ctx);
543 :
544 1 : }
545 :
546 : /*
547 : * test get_parsed_dns
548 : * For this test we assume Valgrind or Address Sanitizer will detect any over
549 : * runs. Also we don't care that the values are DN's only that the value in the
550 : * element is copied to the parsed_dns.
551 : */
552 1 : static void test_get_parsed_dns(void **state)
553 : {
554 1 : struct ldb_message_element *el = NULL;
555 1 : struct parsed_dn *dns = NULL;
556 :
557 1 : TALLOC_CTX *ctx = talloc_new(NULL);
558 :
559 1 : el = talloc_zero(ctx, struct ldb_message_element);
560 :
561 : /*
562 : * empty element, zero dns
563 : */
564 1 : dns = get_parsed_dns(ctx, el);
565 1 : assert_null(dns);
566 :
567 : /*
568 : * one entry
569 : */
570 1 : el->num_values = 1;
571 1 : el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
572 1 : el->values[0] = data_blob_string_const("The first value");
573 :
574 1 : dns = get_parsed_dns(ctx, el);
575 :
576 1 : assert_ptr_equal(el->values[0].data, dns[0].v->data);
577 1 : assert_int_equal(el->values[0].length, dns[0].v->length);
578 :
579 1 : TALLOC_FREE(dns);
580 1 : TALLOC_FREE(el);
581 :
582 :
583 : /*
584 : * Multiple values
585 : */
586 1 : el = talloc_zero(ctx, struct ldb_message_element);
587 1 : el->num_values = 2;
588 1 : el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
589 1 : el->values[0] = data_blob_string_const("The first value");
590 1 : el->values[0] = data_blob_string_const("The second value");
591 :
592 1 : dns = get_parsed_dns(ctx, el);
593 :
594 1 : assert_ptr_equal(el->values[0].data, dns[0].v->data);
595 1 : assert_int_equal(el->values[0].length, dns[0].v->length);
596 :
597 1 : assert_ptr_equal(el->values[1].data, dns[1].v->data);
598 1 : assert_int_equal(el->values[1].length, dns[1].v->length);
599 :
600 1 : TALLOC_FREE(ctx);
601 1 : }
602 :
603 1 : static void test_dn_compare(void **state)
604 : {
605 :
606 1 : struct ldb_context *ldb = NULL;
607 1 : struct parsed_dn *a;
608 1 : DATA_BLOB ab;
609 :
610 1 : struct parsed_dn *b;
611 1 : DATA_BLOB bb;
612 :
613 1 : int res;
614 :
615 1 : TALLOC_CTX *ctx = talloc_new(NULL);
616 1 : const struct GUID *ZERO_GUID = talloc_zero(ctx, struct GUID);
617 :
618 1 : ldb = ldb_init(ctx, NULL);
619 1 : ldb_register_samba_handlers(ldb);
620 :
621 :
622 : /*
623 : * Identical binary DN's
624 : */
625 1 : ab = data_blob_string_const(
626 : "<GUID=fbee08fd-6f75-4bd4-af3f-e4f063a6379e>;"
627 : "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
628 1 : a = talloc_zero(ctx, struct parsed_dn);
629 1 : a->v = &ab;
630 :
631 1 : bb = data_blob_string_const(
632 : "<GUID=fbee08fd-6f75-4bd4-af3f-e4f063a6379e>;"
633 : "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
634 1 : b = talloc_zero(ctx, struct parsed_dn);
635 1 : b->v = &bb;
636 :
637 1 : res = dn_compare(ctx, ldb, a, b);
638 1 : assert_int_equal(BINARY_EQUAL, res);
639 : /*
640 : * DN's should not have been parsed
641 : */
642 1 : assert_null(a->dsdb_dn);
643 1 : assert_memory_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
644 1 : assert_null(b->dsdb_dn);
645 1 : assert_memory_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
646 :
647 1 : TALLOC_FREE(a);
648 1 : TALLOC_FREE(b);
649 :
650 : /*
651 : * differing binary DN's but equal GUID's
652 : */
653 1 : ab = data_blob_string_const(
654 : "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
655 : "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
656 1 : a = talloc_zero(ctx, struct parsed_dn);
657 1 : a->v = &ab;
658 :
659 1 : bb = data_blob_string_const(
660 : "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
661 : "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
662 1 : b = talloc_zero(ctx, struct parsed_dn);
663 1 : b->v = &bb;
664 :
665 1 : res = dn_compare(ctx, ldb, a, b);
666 1 : assert_int_equal(EQUAL, res);
667 : /*
668 : * DN's should have been parsed
669 : */
670 1 : assert_non_null(a->dsdb_dn);
671 1 : assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
672 1 : assert_non_null(b->dsdb_dn);
673 1 : assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
674 :
675 1 : TALLOC_FREE(a);
676 1 : TALLOC_FREE(b);
677 :
678 : /*
679 : * differing binary DN's but and second guid greater
680 : */
681 1 : ab = data_blob_string_const(
682 : "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651d>;"
683 : "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
684 1 : a = talloc_zero(ctx, struct parsed_dn);
685 1 : a->v = &ab;
686 :
687 1 : bb = data_blob_string_const(
688 : "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651e>;"
689 : "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
690 1 : b = talloc_zero(ctx, struct parsed_dn);
691 1 : b->v = &bb;
692 :
693 1 : res = dn_compare(ctx, ldb, a, b);
694 1 : assert_int_equal(LESS_THAN, res);
695 : /*
696 : * DN's should have been parsed
697 : */
698 1 : assert_non_null(a->dsdb_dn);
699 1 : assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
700 1 : assert_non_null(b->dsdb_dn);
701 1 : assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
702 :
703 1 : TALLOC_FREE(a);
704 1 : TALLOC_FREE(b);
705 :
706 : /*
707 : * differing binary DN's but and second guid less
708 : */
709 1 : ab = data_blob_string_const(
710 : "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651d>;"
711 : "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=com");
712 1 : a = talloc_zero(ctx, struct parsed_dn);
713 1 : a->v = &ab;
714 :
715 1 : bb = data_blob_string_const(
716 : "<GUID=efdc91e5-5a5a-493e-9606-166ed0c2651c>;"
717 : "OU=Domain Controllers,DC=ad,DC=testing,DC=samba,DC=org");
718 1 : b = talloc_zero(ctx, struct parsed_dn);
719 1 : b->v = &bb;
720 :
721 1 : res = dn_compare(ctx, ldb, a, b);
722 1 : assert_int_equal(GREATER_THAN, res);
723 : /*
724 : * DN's should have been parsed
725 : */
726 1 : assert_non_null(a->dsdb_dn);
727 1 : assert_memory_not_equal(ZERO_GUID, &a->guid, sizeof(struct GUID));
728 1 : assert_non_null(b->dsdb_dn);
729 1 : assert_memory_not_equal(ZERO_GUID, &b->guid, sizeof(struct GUID));
730 :
731 1 : TALLOC_FREE(a);
732 1 : TALLOC_FREE(b);
733 :
734 1 : TALLOC_FREE(ctx);
735 1 : }
736 :
737 1 : static void test_get_primary_group_dn(void **state)
738 : {
739 :
740 1 : struct ldb_context *ldb = NULL;
741 1 : struct ldb_module *module = NULL;
742 1 : const uint32_t RID = 71;
743 1 : struct dom_sid sid;
744 1 : const char *SID = "S-1-5-21-2470180966-3899876309-2637894779";
745 1 : const char *DN = "OU=Things,DC=ad,DC=testing,DC=samba,DC=org";
746 1 : const char *dn;
747 :
748 1 : TALLOC_CTX *ctx = talloc_new(NULL);
749 :
750 1 : ldb = ldb_init(ctx, NULL);
751 1 : ldb_register_samba_handlers(ldb);
752 :
753 1 : module = talloc_zero(ctx, struct ldb_module);
754 1 : module->ldb = ldb;
755 :
756 : /*
757 : * Pass an empty dom sid this will cause dom_sid_split_rid to fail;
758 : * assign to sid.num_auths to suppress a valgrind warning.
759 : */
760 1 : sid.num_auths = 0;
761 1 : dn = get_primary_group_dn(ctx, module, &sid, RID);
762 1 : assert_null(dn);
763 :
764 : /*
765 : * A valid dom sid
766 : */
767 1 : assert_true(string_to_sid(&sid, SID));
768 1 : g_dn = DN;
769 1 : dn = get_primary_group_dn(ctx, module, &sid, RID);
770 1 : assert_non_null(dn);
771 1 : assert_string_equal(DN, dn);
772 1 : assert_int_equal(LDB_SCOPE_BASE, g_scope);
773 1 : assert_int_equal(0, g_dsdb_flags);
774 1 : assert_null(g_attrs);
775 1 : assert_null(g_exp_fmt);
776 1 : assert_string_equal
777 : ("<SID=S-1-5-21-2470180966-3899876309-71>",
778 : ldb_dn_get_extended_linearized(ctx, g_basedn, 1));
779 :
780 : /*
781 : * Test dsdb search failure
782 : */
783 1 : g_status = LDB_ERR_NO_SUCH_OBJECT;
784 1 : dn = get_primary_group_dn(ctx, module, &sid, RID);
785 1 : assert_null(dn);
786 :
787 1 : TALLOC_FREE(ldb);
788 1 : TALLOC_FREE(ctx);
789 1 : }
790 :
791 1 : static void test_audit_group_json(void **state)
792 : {
793 1 : struct ldb_context *ldb = NULL;
794 1 : struct ldb_module *module = NULL;
795 1 : struct ldb_request *req = NULL;
796 :
797 1 : struct tsocket_address *ts = NULL;
798 :
799 1 : const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
800 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
801 :
802 1 : struct GUID transaction_id;
803 1 : const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
804 :
805 1 : enum event_id_type event_id = EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP;
806 :
807 1 : struct json_object json;
808 1 : json_t *audit = NULL;
809 1 : json_t *v = NULL;
810 1 : json_t *o = NULL;
811 1 : time_t before;
812 1 : struct timeval tv;
813 1 : int rc;
814 :
815 :
816 1 : TALLOC_CTX *ctx = talloc_new(NULL);
817 :
818 1 : ldb = ldb_init(ctx, NULL);
819 :
820 1 : GUID_from_string(TRANSACTION, &transaction_id);
821 :
822 1 : module = talloc_zero(ctx, struct ldb_module);
823 1 : module->ldb = ldb;
824 :
825 1 : tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
826 1 : ldb_set_opaque(ldb, "remoteAddress", ts);
827 :
828 1 : add_session_data(ctx, ldb, SESSION, SID);
829 :
830 1 : req = talloc_zero(ctx, struct ldb_request);
831 1 : req->operation = LDB_ADD;
832 1 : add_transaction_id(req, TRANSACTION);
833 :
834 1 : rc = gettimeofday(&tv, NULL);
835 1 : assert_return_code(rc, errno);
836 1 : before = tv.tv_sec;
837 1 : json = audit_group_json(module,
838 : req,
839 : "the-action",
840 : "the-user-name",
841 : "the-group-name",
842 : event_id,
843 : LDB_SUCCESS);
844 1 : assert_int_equal(3, json_object_size(json.root));
845 :
846 1 : v = json_object_get(json.root, "type");
847 1 : assert_non_null(v);
848 1 : assert_string_equal("groupChange", json_string_value(v));
849 :
850 1 : v = json_object_get(json.root, "timestamp");
851 1 : assert_non_null(v);
852 1 : assert_true(json_is_string(v));
853 1 : check_timestamp(before, json_string_value(v));
854 :
855 1 : audit = json_object_get(json.root, "groupChange");
856 1 : assert_non_null(audit);
857 1 : assert_true(json_is_object(audit));
858 1 : assert_int_equal(11, json_object_size(audit));
859 :
860 1 : o = json_object_get(audit, "version");
861 1 : assert_non_null(o);
862 1 : check_version(o, AUDIT_MAJOR, AUDIT_MINOR);
863 :
864 1 : v = json_object_get(audit, "eventId");
865 1 : assert_non_null(v);
866 1 : assert_true(json_is_integer(v));
867 1 : assert_int_equal(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
868 : json_integer_value(v));
869 :
870 1 : v = json_object_get(audit, "statusCode");
871 1 : assert_non_null(v);
872 1 : assert_true(json_is_integer(v));
873 1 : assert_int_equal(LDB_SUCCESS, json_integer_value(v));
874 :
875 1 : v = json_object_get(audit, "status");
876 1 : assert_non_null(v);
877 1 : assert_true(json_is_string(v));
878 1 : assert_string_equal("Success", json_string_value(v));
879 :
880 1 : v = json_object_get(audit, "user");
881 1 : assert_non_null(v);
882 1 : assert_true(json_is_string(v));
883 1 : assert_string_equal("the-user-name", json_string_value(v));
884 :
885 1 : v = json_object_get(audit, "group");
886 1 : assert_non_null(v);
887 1 : assert_true(json_is_string(v));
888 1 : assert_string_equal("the-group-name", json_string_value(v));
889 :
890 1 : v = json_object_get(audit, "action");
891 1 : assert_non_null(v);
892 1 : assert_true(json_is_string(v));
893 1 : assert_string_equal("the-action", json_string_value(v));
894 :
895 1 : json_free(&json);
896 1 : TALLOC_FREE(ctx);
897 1 : }
898 :
899 1 : static void test_audit_group_json_error(void **state)
900 : {
901 1 : struct ldb_context *ldb = NULL;
902 1 : struct ldb_module *module = NULL;
903 1 : struct ldb_request *req = NULL;
904 :
905 1 : struct tsocket_address *ts = NULL;
906 :
907 1 : const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
908 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
909 :
910 1 : struct GUID transaction_id;
911 1 : const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
912 :
913 1 : enum event_id_type event_id = EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP;
914 :
915 1 : struct json_object json;
916 1 : json_t *audit = NULL;
917 1 : json_t *v = NULL;
918 1 : json_t *o = NULL;
919 1 : time_t before;
920 1 : struct timeval tv;
921 1 : int rc;
922 :
923 :
924 1 : TALLOC_CTX *ctx = talloc_new(NULL);
925 :
926 1 : ldb = ldb_init(ctx, NULL);
927 :
928 1 : GUID_from_string(TRANSACTION, &transaction_id);
929 :
930 1 : module = talloc_zero(ctx, struct ldb_module);
931 1 : module->ldb = ldb;
932 :
933 1 : tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
934 1 : ldb_set_opaque(ldb, "remoteAddress", ts);
935 :
936 1 : add_session_data(ctx, ldb, SESSION, SID);
937 :
938 1 : req = talloc_zero(ctx, struct ldb_request);
939 1 : req->operation = LDB_ADD;
940 1 : add_transaction_id(req, TRANSACTION);
941 :
942 1 : rc = gettimeofday(&tv, NULL);
943 1 : assert_return_code(rc, errno);
944 1 : before = tv.tv_sec;
945 1 : json = audit_group_json(module,
946 : req,
947 : "the-action",
948 : "the-user-name",
949 : "the-group-name",
950 : event_id,
951 : LDB_ERR_OPERATIONS_ERROR);
952 1 : assert_int_equal(3, json_object_size(json.root));
953 :
954 1 : v = json_object_get(json.root, "type");
955 1 : assert_non_null(v);
956 1 : assert_string_equal("groupChange", json_string_value(v));
957 :
958 1 : v = json_object_get(json.root, "timestamp");
959 1 : assert_non_null(v);
960 1 : assert_true(json_is_string(v));
961 1 : check_timestamp(before, json_string_value(v));
962 :
963 1 : audit = json_object_get(json.root, "groupChange");
964 1 : assert_non_null(audit);
965 1 : assert_true(json_is_object(audit));
966 1 : assert_int_equal(11, json_object_size(audit));
967 :
968 1 : o = json_object_get(audit, "version");
969 1 : assert_non_null(o);
970 1 : check_version(o, AUDIT_MAJOR, AUDIT_MINOR);
971 :
972 1 : v = json_object_get(audit, "eventId");
973 1 : assert_non_null(v);
974 1 : assert_true(json_is_integer(v));
975 1 : assert_int_equal(
976 : EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
977 : json_integer_value(v));
978 :
979 1 : v = json_object_get(audit, "statusCode");
980 1 : assert_non_null(v);
981 1 : assert_true(json_is_integer(v));
982 1 : assert_int_equal(LDB_ERR_OPERATIONS_ERROR, json_integer_value(v));
983 :
984 1 : v = json_object_get(audit, "status");
985 1 : assert_non_null(v);
986 1 : assert_true(json_is_string(v));
987 1 : assert_string_equal("Operations error", json_string_value(v));
988 :
989 1 : v = json_object_get(audit, "user");
990 1 : assert_non_null(v);
991 1 : assert_true(json_is_string(v));
992 1 : assert_string_equal("the-user-name", json_string_value(v));
993 :
994 1 : v = json_object_get(audit, "group");
995 1 : assert_non_null(v);
996 1 : assert_true(json_is_string(v));
997 1 : assert_string_equal("the-group-name", json_string_value(v));
998 :
999 1 : v = json_object_get(audit, "action");
1000 1 : assert_non_null(v);
1001 1 : assert_true(json_is_string(v));
1002 1 : assert_string_equal("the-action", json_string_value(v));
1003 :
1004 1 : json_free(&json);
1005 1 : TALLOC_FREE(ctx);
1006 1 : }
1007 :
1008 1 : static void test_audit_group_json_no_event(void **state)
1009 : {
1010 1 : struct ldb_context *ldb = NULL;
1011 1 : struct ldb_module *module = NULL;
1012 1 : struct ldb_request *req = NULL;
1013 :
1014 1 : struct tsocket_address *ts = NULL;
1015 :
1016 1 : const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1017 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1018 :
1019 1 : struct GUID transaction_id;
1020 1 : const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1021 :
1022 1 : enum event_id_type event_id = EVT_ID_NONE;
1023 :
1024 1 : struct json_object json;
1025 1 : json_t *audit = NULL;
1026 1 : json_t *v = NULL;
1027 1 : json_t *o = NULL;
1028 1 : time_t before;
1029 1 : struct timeval tv;
1030 1 : int rc;
1031 :
1032 :
1033 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1034 :
1035 1 : ldb = ldb_init(ctx, NULL);
1036 :
1037 1 : GUID_from_string(TRANSACTION, &transaction_id);
1038 :
1039 1 : module = talloc_zero(ctx, struct ldb_module);
1040 1 : module->ldb = ldb;
1041 :
1042 1 : tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
1043 1 : ldb_set_opaque(ldb, "remoteAddress", ts);
1044 :
1045 1 : add_session_data(ctx, ldb, SESSION, SID);
1046 :
1047 1 : req = talloc_zero(ctx, struct ldb_request);
1048 1 : req->operation = LDB_ADD;
1049 1 : add_transaction_id(req, TRANSACTION);
1050 :
1051 1 : rc = gettimeofday(&tv, NULL);
1052 1 : assert_return_code(rc, errno);
1053 1 : before = tv.tv_sec;
1054 1 : json = audit_group_json(module,
1055 : req,
1056 : "the-action",
1057 : "the-user-name",
1058 : "the-group-name",
1059 : event_id,
1060 : LDB_SUCCESS);
1061 1 : assert_int_equal(3, json_object_size(json.root));
1062 :
1063 1 : v = json_object_get(json.root, "type");
1064 1 : assert_non_null(v);
1065 1 : assert_string_equal("groupChange", json_string_value(v));
1066 :
1067 1 : v = json_object_get(json.root, "timestamp");
1068 1 : assert_non_null(v);
1069 1 : assert_true(json_is_string(v));
1070 1 : check_timestamp(before, json_string_value(v));
1071 :
1072 1 : audit = json_object_get(json.root, "groupChange");
1073 1 : assert_non_null(audit);
1074 1 : assert_true(json_is_object(audit));
1075 1 : assert_int_equal(10, json_object_size(audit));
1076 :
1077 1 : o = json_object_get(audit, "version");
1078 1 : assert_non_null(o);
1079 1 : check_version(o, AUDIT_MAJOR, AUDIT_MINOR);
1080 :
1081 1 : v = json_object_get(audit, "eventId");
1082 1 : assert_null(v);
1083 :
1084 1 : v = json_object_get(audit, "statusCode");
1085 1 : assert_non_null(v);
1086 1 : assert_true(json_is_integer(v));
1087 1 : assert_int_equal(LDB_SUCCESS, json_integer_value(v));
1088 :
1089 1 : v = json_object_get(audit, "status");
1090 1 : assert_non_null(v);
1091 1 : assert_true(json_is_string(v));
1092 1 : assert_string_equal("Success", json_string_value(v));
1093 :
1094 1 : v = json_object_get(audit, "user");
1095 1 : assert_non_null(v);
1096 1 : assert_true(json_is_string(v));
1097 1 : assert_string_equal("the-user-name", json_string_value(v));
1098 :
1099 1 : v = json_object_get(audit, "group");
1100 1 : assert_non_null(v);
1101 1 : assert_true(json_is_string(v));
1102 1 : assert_string_equal("the-group-name", json_string_value(v));
1103 :
1104 1 : v = json_object_get(audit, "action");
1105 1 : assert_non_null(v);
1106 1 : assert_true(json_is_string(v));
1107 1 : assert_string_equal("the-action", json_string_value(v));
1108 :
1109 1 : json_free(&json);
1110 1 : TALLOC_FREE(ctx);
1111 1 : }
1112 8 : static void setup_ldb(
1113 : TALLOC_CTX *ctx,
1114 : struct ldb_context **ldb,
1115 : struct ldb_module **module,
1116 : const char *ip,
1117 : const char *session,
1118 : const char *sid)
1119 : {
1120 8 : struct tsocket_address *ts = NULL;
1121 8 : struct audit_context *context = NULL;
1122 :
1123 8 : *ldb = ldb_init(ctx, NULL);
1124 8 : ldb_register_samba_handlers(*ldb);
1125 :
1126 :
1127 8 : *module = talloc_zero(ctx, struct ldb_module);
1128 8 : (*module)->ldb = *ldb;
1129 :
1130 8 : context = talloc_zero(*module, struct audit_context);
1131 8 : context->send_events = true;
1132 8 : context->msg_ctx = (struct imessaging_context *) 0x01;
1133 :
1134 8 : ldb_module_set_private(*module, context);
1135 :
1136 8 : tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
1137 8 : ldb_set_opaque(*ldb, "remoteAddress", ts);
1138 :
1139 8 : add_session_data(ctx, *ldb, session, sid);
1140 8 : }
1141 :
1142 : /*
1143 : * Test the removal of a user from a group.
1144 : *
1145 : * The new element contains one group member
1146 : * The old element contains two group member
1147 : *
1148 : * Expect to see the removed entry logged.
1149 : *
1150 : * This test confirms bug 13664
1151 : * https://bugzilla.samba.org/show_bug.cgi?id=13664
1152 : */
1153 1 : static void test_log_membership_changes_removed(void **state)
1154 : {
1155 1 : struct ldb_context *ldb = NULL;
1156 1 : struct ldb_module *module = NULL;
1157 1 : const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1158 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1159 1 : const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1160 1 : const char * const IP = "127.0.0.1";
1161 1 : struct ldb_request *req = NULL;
1162 1 : struct ldb_message_element *new_el = NULL;
1163 1 : struct ldb_message_element *old_el = NULL;
1164 1 : uint32_t group_type = GTYPE_SECURITY_GLOBAL_GROUP;
1165 1 : int status = 0;
1166 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1167 :
1168 1 : setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1169 :
1170 : /*
1171 : * Build the ldb_request
1172 : */
1173 1 : req = talloc_zero(ctx, struct ldb_request);
1174 1 : req->operation = LDB_ADD;
1175 1 : add_transaction_id(req, TRANSACTION);
1176 :
1177 : /*
1178 : * Populate the new elements, containing one entry.
1179 : * Indicating that one element has been removed
1180 : */
1181 1 : new_el = talloc_zero(ctx, struct ldb_message_element);
1182 1 : new_el->num_values = 1;
1183 1 : new_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1184 1 : new_el->values[0] = data_blob_string_const(
1185 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1186 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1187 : "DC=example,DC=com");
1188 :
1189 : /*
1190 : * Populate the old elements, with two elements
1191 : * The first is the same as the one in new elements.
1192 : */
1193 1 : old_el = talloc_zero(ctx, struct ldb_message_element);
1194 1 : old_el->num_values = 2;
1195 1 : old_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1196 1 : old_el->values[0] = data_blob_string_const(
1197 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1198 : "cn=grpadttstuser01,cn=users,DC=addom,"
1199 : "DC=samba,DC=example,DC=com");
1200 1 : old_el->values[1] = data_blob_string_const(
1201 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1202 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1203 : "DC=example,DC=com");
1204 :
1205 : /*
1206 : * call log_membership_changes
1207 : */
1208 1 : messages_sent = 0;
1209 1 : log_membership_changes(module, req, new_el, old_el, group_type, status);
1210 :
1211 : /*
1212 : * Check the results
1213 : */
1214 1 : assert_int_equal(1, messages_sent);
1215 :
1216 1 : check_group_change_message(
1217 : 0,
1218 : "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1219 : "Removed",
1220 1 : EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP);
1221 :
1222 : /*
1223 : * Clean up
1224 : */
1225 1 : json_free(&messages[0]);
1226 1 : TALLOC_FREE(ctx);
1227 1 : }
1228 :
1229 : /* test log_membership_changes
1230 : *
1231 : * old contains 2 user dn's
1232 : * new contains 0 user dn's
1233 : *
1234 : * Expect to see both dn's logged as deleted.
1235 : */
1236 1 : static void test_log_membership_changes_remove_all(void **state)
1237 : {
1238 1 : struct ldb_context *ldb = NULL;
1239 1 : struct ldb_module *module = NULL;
1240 1 : const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1241 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1242 1 : const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1243 1 : const char * const IP = "127.0.0.1";
1244 1 : struct ldb_request *req = NULL;
1245 1 : struct ldb_message_element *new_el = NULL;
1246 1 : struct ldb_message_element *old_el = NULL;
1247 1 : int status = 0;
1248 1 : uint32_t group_type = GTYPE_SECURITY_BUILTIN_LOCAL_GROUP;
1249 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1250 :
1251 1 : setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1252 :
1253 : /*
1254 : * Build the ldb_request
1255 : */
1256 1 : req = talloc_zero(ctx, struct ldb_request);
1257 1 : req->operation = LDB_ADD;
1258 1 : add_transaction_id(req, TRANSACTION);
1259 :
1260 : /*
1261 : * Populate the new elements, containing no entries.
1262 : * Indicating that all elements have been removed
1263 : */
1264 1 : new_el = talloc_zero(ctx, struct ldb_message_element);
1265 1 : new_el->num_values = 0;
1266 1 : new_el->values = NULL;
1267 :
1268 : /*
1269 : * Populate the old elements, with two elements
1270 : */
1271 1 : old_el = talloc_zero(ctx, struct ldb_message_element);
1272 1 : old_el->num_values = 2;
1273 1 : old_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1274 1 : old_el->values[0] = data_blob_string_const(
1275 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1276 : "cn=grpadttstuser01,cn=users,DC=addom,"
1277 : "DC=samba,DC=example,DC=com");
1278 1 : old_el->values[1] = data_blob_string_const(
1279 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1280 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1281 : "DC=example,DC=com");
1282 :
1283 : /*
1284 : * call log_membership_changes
1285 : */
1286 1 : messages_sent = 0;
1287 1 : log_membership_changes(module, req, new_el, old_el, group_type, status);
1288 :
1289 : /*
1290 : * Check the results
1291 : */
1292 1 : assert_int_equal(2, messages_sent);
1293 :
1294 1 : check_group_change_message(
1295 : 0,
1296 : "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1297 : "Removed",
1298 1 : EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP);
1299 :
1300 1 : check_group_change_message(
1301 : 1,
1302 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
1303 : "Removed",
1304 1 : EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP);
1305 :
1306 : /*
1307 : * Clean up
1308 : */
1309 1 : json_free(&messages[0]);
1310 1 : json_free(&messages[1]);
1311 1 : TALLOC_FREE(ctx);
1312 1 : }
1313 :
1314 : /* test log_membership_changes
1315 : *
1316 : * Add an entry.
1317 : *
1318 : * Old entries contains a single user dn
1319 : * New entries contains 2 user dn's, one matching the dn in old entries
1320 : *
1321 : * Should see a single new entry logged.
1322 : */
1323 1 : static void test_log_membership_changes_added(void **state)
1324 : {
1325 1 : struct ldb_context *ldb = NULL;
1326 1 : struct ldb_module *module = NULL;
1327 1 : const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1328 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1329 1 : const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1330 1 : const char * const IP = "127.0.0.1";
1331 1 : struct ldb_request *req = NULL;
1332 1 : struct ldb_message_element *new_el = NULL;
1333 1 : struct ldb_message_element *old_el = NULL;
1334 1 : uint32_t group_type = GTYPE_SECURITY_DOMAIN_LOCAL_GROUP;
1335 1 : int status = 0;
1336 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1337 :
1338 1 : setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1339 :
1340 : /*
1341 : * Build the ldb_request
1342 : */
1343 1 : req = talloc_zero(ctx, struct ldb_request);
1344 1 : req->operation = LDB_ADD;
1345 1 : add_transaction_id(req, TRANSACTION);
1346 :
1347 : /*
1348 : * Populate the old elements adding a single entry.
1349 : */
1350 1 : old_el = talloc_zero(ctx, struct ldb_message_element);
1351 1 : old_el->num_values = 1;
1352 1 : old_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1353 1 : old_el->values[0] = data_blob_string_const(
1354 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1355 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1356 : "DC=example,DC=com");
1357 :
1358 : /*
1359 : * Populate the new elements adding two entries. One matches the entry
1360 : * in old elements. We expect to see the other element logged as Added
1361 : */
1362 1 : new_el = talloc_zero(ctx, struct ldb_message_element);
1363 1 : new_el->num_values = 2;
1364 1 : new_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1365 1 : new_el->values[0] = data_blob_string_const(
1366 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1367 : "cn=grpadttstuser01,cn=users,DC=addom,"
1368 : "DC=samba,DC=example,DC=com");
1369 1 : new_el->values[1] = data_blob_string_const(
1370 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1371 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1372 : "DC=example,DC=com");
1373 :
1374 : /*
1375 : * call log_membership_changes
1376 : */
1377 1 : messages_sent = 0;
1378 1 : log_membership_changes(module, req, new_el, old_el, group_type, status);
1379 :
1380 : /*
1381 : * Check the results
1382 : */
1383 1 : assert_int_equal(1, messages_sent);
1384 :
1385 1 : check_group_change_message(
1386 : 0,
1387 : "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1388 : "Added",
1389 1 : EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP);
1390 :
1391 : /*
1392 : * Clean up
1393 : */
1394 1 : json_free(&messages[0]);
1395 1 : TALLOC_FREE(ctx);
1396 1 : }
1397 :
1398 : /*
1399 : * test log_membership_changes.
1400 : *
1401 : * Old entries is empty
1402 : * New entries contains 2 user dn's
1403 : *
1404 : * Expect to see log messages for two added users
1405 : */
1406 1 : static void test_log_membership_changes_add_to_empty(void **state)
1407 : {
1408 1 : struct ldb_context *ldb = NULL;
1409 1 : struct ldb_module *module = NULL;
1410 1 : const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1411 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1412 1 : const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1413 1 : const char * const IP = "127.0.0.1";
1414 1 : struct ldb_request *req = NULL;
1415 1 : struct ldb_message_element *new_el = NULL;
1416 1 : struct ldb_message_element *old_el = NULL;
1417 1 : uint32_t group_type = GTYPE_SECURITY_UNIVERSAL_GROUP;
1418 1 : int status = 0;
1419 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1420 :
1421 : /*
1422 : * Set up the ldb and module structures
1423 : */
1424 1 : setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1425 :
1426 : /*
1427 : * Build the request structure
1428 : */
1429 1 : req = talloc_zero(ctx, struct ldb_request);
1430 1 : req->operation = LDB_ADD;
1431 1 : add_transaction_id(req, TRANSACTION);
1432 :
1433 : /*
1434 : * Build the element containing the old values
1435 : */
1436 1 : old_el = talloc_zero(ctx, struct ldb_message_element);
1437 1 : old_el->num_values = 0;
1438 1 : old_el->values = NULL;
1439 :
1440 : /*
1441 : * Build the element containing the new values
1442 : */
1443 1 : new_el = talloc_zero(ctx, struct ldb_message_element);
1444 1 : new_el->num_values = 2;
1445 1 : new_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1446 1 : new_el->values[0] = data_blob_string_const(
1447 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1448 : "cn=grpadttstuser01,cn=users,DC=addom,"
1449 : "DC=samba,DC=example,DC=com");
1450 1 : new_el->values[1] = data_blob_string_const(
1451 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1452 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1453 : "DC=example,DC=com");
1454 :
1455 : /*
1456 : * Run log membership changes
1457 : */
1458 1 : messages_sent = 0;
1459 1 : log_membership_changes(module, req, new_el, old_el, group_type, status);
1460 1 : assert_int_equal(2, messages_sent);
1461 :
1462 1 : check_group_change_message(
1463 : 0,
1464 : "cn=grpadttstuser01,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1465 : "Added",
1466 1 : EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP);
1467 :
1468 1 : check_group_change_message(
1469 : 1,
1470 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
1471 : "Added",
1472 1 : EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP);
1473 :
1474 1 : json_free(&messages[0]);
1475 1 : json_free(&messages[1]);
1476 1 : TALLOC_FREE(ctx);
1477 1 : }
1478 :
1479 : /* test log_membership_changes
1480 : *
1481 : * Test Replication Meta Data flag handling.
1482 : *
1483 : * 4 entries in old and new entries with their RMD_FLAGS set as below:
1484 : * old new
1485 : * 1) 0 0 Not logged
1486 : * 2) 1 1 Both deleted, no change not logged
1487 : * 3) 0 1 New tagged as deleted, log as deleted
1488 : * 4) 1 0 Has been undeleted, log as an add
1489 : *
1490 : * Should see a single new entry logged.
1491 : */
1492 1 : static void test_log_membership_changes_rmd_flags(void **state)
1493 : {
1494 1 : struct ldb_context *ldb = NULL;
1495 1 : struct ldb_module *module = NULL;
1496 1 : const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1497 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1498 1 : const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1499 1 : const char * const IP = "127.0.0.1";
1500 1 : struct ldb_request *req = NULL;
1501 1 : struct ldb_message_element *new_el = NULL;
1502 1 : struct ldb_message_element *old_el = NULL;
1503 1 : uint32_t group_type = GTYPE_SECURITY_GLOBAL_GROUP;
1504 1 : int status = 0;
1505 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1506 :
1507 1 : setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1508 :
1509 : /*
1510 : * Build the ldb_request
1511 : */
1512 1 : req = talloc_zero(ctx, struct ldb_request);
1513 1 : req->operation = LDB_ADD;
1514 1 : add_transaction_id(req, TRANSACTION);
1515 :
1516 : /*
1517 : * Populate the old elements.
1518 : */
1519 1 : old_el = talloc_zero(ctx, struct ldb_message_element);
1520 1 : old_el->num_values = 4;
1521 1 : old_el->values = talloc_zero_array(ctx, DATA_BLOB, 4);
1522 1 : old_el->values[0] = data_blob_string_const(
1523 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1524 : "<RMD_FLAGS=0>;"
1525 : "cn=grpadttstuser01,cn=users,DC=addom,"
1526 : "DC=samba,DC=example,DC=com");
1527 1 : old_el->values[1] = data_blob_string_const(
1528 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681c>;"
1529 : "<RMD_FLAGS=1>;"
1530 : "cn=grpadttstuser02,cn=users,DC=addom,"
1531 : "DC=samba,DC=example,DC=com");
1532 1 : old_el->values[2] = data_blob_string_const(
1533 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681d>;"
1534 : "<RMD_FLAGS=0>;"
1535 : "cn=grpadttstuser03,cn=users,DC=addom,"
1536 : "DC=samba,DC=example,DC=com");
1537 1 : old_el->values[3] = data_blob_string_const(
1538 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681e>;"
1539 : "<RMD_FLAGS=1>;"
1540 : "cn=grpadttstuser04,cn=users,DC=addom,"
1541 : "DC=samba,DC=example,DC=com");
1542 :
1543 : /*
1544 : * Populate the new elements.
1545 : */
1546 1 : new_el = talloc_zero(ctx, struct ldb_message_element);
1547 1 : new_el->num_values = 4;
1548 1 : new_el->values = talloc_zero_array(ctx, DATA_BLOB, 4);
1549 1 : new_el->values[0] = data_blob_string_const(
1550 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1551 : "<RMD_FLAGS=0>;"
1552 : "cn=grpadttstuser01,cn=users,DC=addom,"
1553 : "DC=samba,DC=example,DC=com");
1554 1 : new_el->values[1] = data_blob_string_const(
1555 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681c>;"
1556 : "<RMD_FLAGS=1>;"
1557 : "cn=grpadttstuser02,cn=users,DC=addom,"
1558 : "DC=samba,DC=example,DC=com");
1559 1 : new_el->values[2] = data_blob_string_const(
1560 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681d>;"
1561 : "<RMD_FLAGS=1>;"
1562 : "cn=grpadttstuser03,cn=users,DC=addom,"
1563 : "DC=samba,DC=example,DC=com");
1564 1 : new_el->values[3] = data_blob_string_const(
1565 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681e>;"
1566 : "<RMD_FLAGS=0>;"
1567 : "cn=grpadttstuser04,cn=users,DC=addom,"
1568 : "DC=samba,DC=example,DC=com");
1569 :
1570 : /*
1571 : * call log_membership_changes
1572 : */
1573 1 : messages_sent = 0;
1574 1 : log_membership_changes(module, req, new_el, old_el, group_type, status);
1575 :
1576 : /*
1577 : * Check the results
1578 : */
1579 1 : assert_int_equal(2, messages_sent);
1580 :
1581 1 : check_group_change_message(
1582 : 0,
1583 : "cn=grpadttstuser03,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1584 : "Removed",
1585 1 : EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP);
1586 1 : check_group_change_message(
1587 : 1,
1588 : "cn=grpadttstuser04,cn=users,DC=addom,DC=samba,DC=example,DC=com",
1589 : "Added",
1590 1 : EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP);
1591 :
1592 : /*
1593 : * Clean up
1594 : */
1595 1 : json_free(&messages[0]);
1596 1 : json_free(&messages[1]);
1597 1 : TALLOC_FREE(ctx);
1598 1 : }
1599 :
1600 1 : static void test_get_add_member_event(void **state)
1601 : {
1602 1 : assert_int_equal(
1603 : EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP,
1604 : get_add_member_event(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
1605 :
1606 1 : assert_int_equal(EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP,
1607 : get_add_member_event(GTYPE_SECURITY_GLOBAL_GROUP));
1608 :
1609 1 : assert_int_equal(
1610 : EVT_ID_USER_ADDED_TO_LOCAL_SEC_GROUP,
1611 : get_add_member_event(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
1612 :
1613 1 : assert_int_equal(EVT_ID_USER_ADDED_TO_UNIVERSAL_SEC_GROUP,
1614 : get_add_member_event(GTYPE_SECURITY_UNIVERSAL_GROUP));
1615 :
1616 1 : assert_int_equal(EVT_ID_USER_ADDED_TO_GLOBAL_GROUP,
1617 : get_add_member_event(GTYPE_DISTRIBUTION_GLOBAL_GROUP));
1618 :
1619 1 : assert_int_equal(
1620 : EVT_ID_USER_ADDED_TO_LOCAL_GROUP,
1621 : get_add_member_event(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP));
1622 :
1623 1 : assert_int_equal(
1624 : EVT_ID_USER_ADDED_TO_UNIVERSAL_GROUP,
1625 : get_add_member_event(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP));
1626 :
1627 1 : assert_int_equal(EVT_ID_NONE, get_add_member_event(0));
1628 :
1629 1 : assert_int_equal(EVT_ID_NONE, get_add_member_event(UINT32_MAX));
1630 1 : }
1631 :
1632 1 : static void test_get_remove_member_event(void **state)
1633 : {
1634 1 : assert_int_equal(
1635 : EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP,
1636 : get_remove_member_event(GTYPE_SECURITY_BUILTIN_LOCAL_GROUP));
1637 :
1638 1 : assert_int_equal(EVT_ID_USER_REMOVED_FROM_GLOBAL_SEC_GROUP,
1639 : get_remove_member_event(GTYPE_SECURITY_GLOBAL_GROUP));
1640 :
1641 1 : assert_int_equal(
1642 : EVT_ID_USER_REMOVED_FROM_LOCAL_SEC_GROUP,
1643 : get_remove_member_event(GTYPE_SECURITY_DOMAIN_LOCAL_GROUP));
1644 :
1645 1 : assert_int_equal(
1646 : EVT_ID_USER_REMOVED_FROM_UNIVERSAL_SEC_GROUP,
1647 : get_remove_member_event(GTYPE_SECURITY_UNIVERSAL_GROUP));
1648 :
1649 1 : assert_int_equal(
1650 : EVT_ID_USER_REMOVED_FROM_GLOBAL_GROUP,
1651 : get_remove_member_event(GTYPE_DISTRIBUTION_GLOBAL_GROUP));
1652 :
1653 1 : assert_int_equal(
1654 : EVT_ID_USER_REMOVED_FROM_LOCAL_GROUP,
1655 : get_remove_member_event(GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP));
1656 :
1657 1 : assert_int_equal(
1658 : EVT_ID_USER_REMOVED_FROM_UNIVERSAL_GROUP,
1659 : get_remove_member_event(GTYPE_DISTRIBUTION_UNIVERSAL_GROUP));
1660 :
1661 1 : assert_int_equal(EVT_ID_NONE, get_remove_member_event(0));
1662 :
1663 1 : assert_int_equal(EVT_ID_NONE, get_remove_member_event(UINT32_MAX));
1664 1 : }
1665 :
1666 : /* test log_group_membership_changes
1667 : *
1668 : * Happy path test case
1669 : *
1670 : */
1671 1 : static void test_log_group_membership_changes(void **state)
1672 : {
1673 1 : struct ldb_context *ldb = NULL;
1674 1 : struct ldb_module *module = NULL;
1675 1 : const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1676 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1677 1 : const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1678 1 : const char * const IP = "127.0.0.1";
1679 1 : struct ldb_request *req = NULL;
1680 1 : struct ldb_message *msg = NULL;
1681 1 : struct ldb_message_element *el = NULL;
1682 1 : struct audit_callback_context *acc = NULL;
1683 1 : struct ldb_result *res = NULL;
1684 1 : struct ldb_message *new_msg = NULL;
1685 1 : struct ldb_message_element *group_type = NULL;
1686 1 : const char *group_type_str = NULL;
1687 1 : struct ldb_message_element *new_el = NULL;
1688 1 : struct ldb_message_element *old_el = NULL;
1689 1 : int status = 0;
1690 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1691 :
1692 1 : setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1693 :
1694 : /*
1695 : * Build the ldb message
1696 : */
1697 1 : msg = talloc_zero(ctx, struct ldb_message);
1698 :
1699 : /*
1700 : * Populate message elements, adding a new entry to the membership list
1701 : *
1702 : */
1703 :
1704 1 : el = talloc_zero(ctx, struct ldb_message_element);
1705 1 : el->name = "member";
1706 1 : el->num_values = 1;
1707 1 : el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1708 1 : el->values[0] = data_blob_string_const(
1709 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1710 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1711 : "DC=example,DC=com");
1712 1 : msg->elements = el;
1713 1 : msg->num_elements = 1;
1714 :
1715 : /*
1716 : * Build the ldb_request
1717 : */
1718 1 : req = talloc_zero(ctx, struct ldb_request);
1719 1 : req->operation = LDB_ADD;
1720 1 : req->op.add.message = msg;
1721 1 : add_transaction_id(req, TRANSACTION);
1722 :
1723 : /*
1724 : * Build the initial state of the database
1725 : */
1726 1 : old_el = talloc_zero(ctx, struct ldb_message_element);
1727 1 : old_el->name = "member";
1728 1 : old_el->num_values = 1;
1729 1 : old_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1730 1 : old_el->values[0] = data_blob_string_const(
1731 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1732 : "cn=grpadttstuser01,cn=users,DC=addom,"
1733 : "DC=samba,DC=example,DC=com");
1734 :
1735 : /*
1736 : * Build the updated state of the database
1737 : */
1738 1 : res = talloc_zero(ctx, struct ldb_result);
1739 1 : new_msg = talloc_zero(ctx, struct ldb_message);
1740 1 : new_el = talloc_zero(ctx, struct ldb_message_element);
1741 1 : new_el->name = "member";
1742 1 : new_el->num_values = 2;
1743 1 : new_el->values = talloc_zero_array(ctx, DATA_BLOB, 2);
1744 1 : new_el->values[0] = data_blob_string_const(
1745 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1746 : "cn=grpadttstuser01,cn=users,DC=addom,"
1747 : "DC=samba,DC=example,DC=com");
1748 1 : new_el->values[1] = data_blob_string_const(
1749 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1750 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1751 : "DC=example,DC=com");
1752 :
1753 1 : group_type = talloc_zero(ctx, struct ldb_message_element);
1754 1 : group_type->name = "groupType";
1755 1 : group_type->num_values = 1;
1756 1 : group_type->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1757 1 : group_type_str = talloc_asprintf(ctx, "%u", GTYPE_SECURITY_GLOBAL_GROUP);
1758 1 : group_type->values[0] = data_blob_string_const(group_type_str);
1759 :
1760 :
1761 1 : new_msg->elements = talloc_zero_array(ctx, struct ldb_message_element, 2);
1762 1 : new_msg->num_elements = 2;
1763 1 : new_msg->elements[0] = *new_el;
1764 1 : new_msg->elements[1] = *group_type;
1765 :
1766 1 : res->count = 1;
1767 1 : res->msgs = &new_msg;
1768 :
1769 1 : acc = talloc_zero(ctx, struct audit_callback_context);
1770 1 : acc->request = req;
1771 1 : acc->module = module;
1772 1 : acc->members = old_el;
1773 : /*
1774 : * call log_membership_changes
1775 : */
1776 1 : messages_sent = 0;
1777 1 : g_result = res;
1778 1 : g_status = LDB_SUCCESS;
1779 1 : log_group_membership_changes(acc, status);
1780 1 : g_result = NULL;
1781 :
1782 : /*
1783 : * Check the results
1784 : */
1785 1 : assert_int_equal(1, messages_sent);
1786 :
1787 1 : check_group_change_message(
1788 : 0,
1789 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,DC=example,DC=com",
1790 : "Added",
1791 1 : EVT_ID_USER_ADDED_TO_GLOBAL_SEC_GROUP);
1792 :
1793 : /*
1794 : * Clean up
1795 : */
1796 1 : json_free(&messages[0]);
1797 1 : TALLOC_FREE(ctx);
1798 1 : }
1799 :
1800 : /* test log_group_membership_changes
1801 : *
1802 : * The ldb query to retrieve the new values failed.
1803 : *
1804 : * Should generate group membership change Failure message.
1805 : *
1806 : */
1807 1 : static void test_log_group_membership_changes_read_new_failure(void **state)
1808 : {
1809 1 : struct ldb_context *ldb = NULL;
1810 1 : struct ldb_module *module = NULL;
1811 1 : const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1812 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1813 1 : const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1814 1 : const char * const IP = "127.0.0.1";
1815 1 : struct ldb_request *req = NULL;
1816 1 : struct ldb_message *msg = NULL;
1817 1 : struct ldb_message_element *el = NULL;
1818 1 : struct audit_callback_context *acc = NULL;
1819 1 : struct ldb_message_element *old_el = NULL;
1820 1 : int status = 0;
1821 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1822 :
1823 1 : setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1824 :
1825 : /*
1826 : * Build the ldb message
1827 : */
1828 1 : msg = talloc_zero(ctx, struct ldb_message);
1829 :
1830 : /*
1831 : * Populate message elements, adding a new entry to the membership list
1832 : *
1833 : */
1834 :
1835 1 : el = talloc_zero(ctx, struct ldb_message_element);
1836 1 : el->name = "member";
1837 1 : el->num_values = 1;
1838 1 : el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1839 1 : el->values[0] = data_blob_string_const(
1840 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1841 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1842 : "DC=example,DC=com");
1843 1 : msg->elements = el;
1844 1 : msg->num_elements = 1;
1845 :
1846 : /*
1847 : * Build the ldb_request
1848 : */
1849 1 : req = talloc_zero(ctx, struct ldb_request);
1850 1 : req->operation = LDB_ADD;
1851 1 : req->op.add.message = msg;
1852 1 : add_transaction_id(req, TRANSACTION);
1853 :
1854 : /*
1855 : * Build the initial state of the database
1856 : */
1857 1 : old_el = talloc_zero(ctx, struct ldb_message_element);
1858 1 : old_el->name = "member";
1859 1 : old_el->num_values = 1;
1860 1 : old_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1861 1 : old_el->values[0] = data_blob_string_const(
1862 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1863 : "cn=grpadttstuser01,cn=users,DC=addom,"
1864 : "DC=samba,DC=example,DC=com");
1865 :
1866 1 : acc = talloc_zero(ctx, struct audit_callback_context);
1867 1 : acc->request = req;
1868 1 : acc->module = module;
1869 1 : acc->members = old_el;
1870 : /*
1871 : * call log_membership_changes
1872 : */
1873 1 : messages_sent = 0;
1874 1 : g_result = NULL;
1875 1 : g_status = LDB_ERR_NO_SUCH_OBJECT;
1876 1 : log_group_membership_changes(acc, status);
1877 :
1878 : /*
1879 : * Check the results
1880 : */
1881 1 : assert_int_equal(1, messages_sent);
1882 :
1883 1 : check_group_change_message(
1884 : 0,
1885 : "",
1886 : "Failure",
1887 1 : EVT_ID_NONE);
1888 :
1889 : /*
1890 : * Clean up
1891 : */
1892 1 : json_free(&messages[0]);
1893 1 : TALLOC_FREE(ctx);
1894 1 : }
1895 :
1896 : /* test log_group_membership_changes
1897 : *
1898 : * The operation failed.
1899 : *
1900 : * Should generate group membership change Failure message.
1901 : *
1902 : */
1903 1 : static void test_log_group_membership_changes_error(void **state)
1904 : {
1905 1 : struct ldb_context *ldb = NULL;
1906 1 : struct ldb_module *module = NULL;
1907 1 : const char * const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1908 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1909 1 : const char * const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1910 1 : const char * const IP = "127.0.0.1";
1911 1 : struct ldb_request *req = NULL;
1912 1 : struct ldb_message *msg = NULL;
1913 1 : struct ldb_message_element *el = NULL;
1914 1 : struct ldb_message_element *old_el = NULL;
1915 1 : struct audit_callback_context *acc = NULL;
1916 1 : int status = LDB_ERR_OPERATIONS_ERROR;
1917 1 : TALLOC_CTX *ctx = talloc_new(NULL);
1918 :
1919 1 : setup_ldb(ctx, &ldb, &module, IP, SESSION, SID);
1920 :
1921 : /*
1922 : * Build the ldb message
1923 : */
1924 1 : msg = talloc_zero(ctx, struct ldb_message);
1925 :
1926 : /*
1927 : * Populate message elements, adding a new entry to the membership list
1928 : *
1929 : */
1930 :
1931 1 : el = talloc_zero(ctx, struct ldb_message_element);
1932 1 : el->name = "member";
1933 1 : el->num_values = 1;
1934 1 : el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1935 1 : el->values[0] = data_blob_string_const(
1936 : "<GUID=081519b5-a709-44a0-bc95-dd4bfe809bf8>;"
1937 : "CN=testuser131953,CN=Users,DC=addom,DC=samba,"
1938 : "DC=example,DC=com");
1939 1 : msg->elements = el;
1940 1 : msg->num_elements = 1;
1941 :
1942 : /*
1943 : * Build the ldb_request
1944 : */
1945 1 : req = talloc_zero(ctx, struct ldb_request);
1946 1 : req->operation = LDB_ADD;
1947 1 : req->op.add.message = msg;
1948 1 : add_transaction_id(req, TRANSACTION);
1949 :
1950 : /*
1951 : * Build the initial state of the database
1952 : */
1953 1 : old_el = talloc_zero(ctx, struct ldb_message_element);
1954 1 : old_el->name = "member";
1955 1 : old_el->num_values = 1;
1956 1 : old_el->values = talloc_zero_array(ctx, DATA_BLOB, 1);
1957 1 : old_el->values[0] = data_blob_string_const(
1958 : "<GUID=cb8c2777-dcf5-419c-ab57-f645dbdf681b>;"
1959 : "cn=grpadttstuser01,cn=users,DC=addom,"
1960 : "DC=samba,DC=example,DC=com");
1961 :
1962 :
1963 1 : acc = talloc_zero(ctx, struct audit_callback_context);
1964 1 : acc->request = req;
1965 1 : acc->module = module;
1966 1 : acc->members = old_el;
1967 : /*
1968 : * call log_membership_changes
1969 : */
1970 1 : messages_sent = 0;
1971 1 : log_group_membership_changes(acc, status);
1972 :
1973 : /*
1974 : * Check the results
1975 : */
1976 1 : assert_int_equal(1, messages_sent);
1977 :
1978 1 : check_group_change_message(
1979 : 0,
1980 : "",
1981 : "Failure",
1982 1 : EVT_ID_NONE);
1983 :
1984 : /*
1985 : * Clean up
1986 : */
1987 1 : json_free(&messages[0]);
1988 1 : TALLOC_FREE(ctx);
1989 1 : }
1990 :
1991 : /*
1992 : * Note: to run under valgrind us:
1993 : * valgrind --suppressions=test_group_audit.valgrind bin/test_group_audit
1994 : * This suppresses the errors generated because the ldb_modules are not
1995 : * de-registered.
1996 : *
1997 : */
1998 1 : int main(void) {
1999 1 : const struct CMUnitTest tests[] = {
2000 : cmocka_unit_test(test_audit_group_json),
2001 : cmocka_unit_test(test_audit_group_json_error),
2002 : cmocka_unit_test(test_audit_group_json_no_event),
2003 : cmocka_unit_test(test_get_transaction_id),
2004 : cmocka_unit_test(test_audit_group_hr),
2005 : cmocka_unit_test(test_get_parsed_dns),
2006 : cmocka_unit_test(test_dn_compare),
2007 : cmocka_unit_test(test_get_primary_group_dn),
2008 : cmocka_unit_test(test_log_membership_changes_removed),
2009 : cmocka_unit_test(test_log_membership_changes_remove_all),
2010 : cmocka_unit_test(test_log_membership_changes_added),
2011 : cmocka_unit_test(test_log_membership_changes_add_to_empty),
2012 : cmocka_unit_test(test_log_membership_changes_rmd_flags),
2013 : cmocka_unit_test(test_get_add_member_event),
2014 : cmocka_unit_test(test_get_remove_member_event),
2015 : cmocka_unit_test(test_log_group_membership_changes),
2016 : cmocka_unit_test(test_log_group_membership_changes_read_new_failure),
2017 : cmocka_unit_test(test_log_group_membership_changes_error),
2018 : };
2019 :
2020 1 : cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
2021 1 : return cmocka_run_group_tests(tests, NULL, NULL);
2022 : }
|