1 /*
2    Unit tests for the dsdb audit logging utility code code in audit_util.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 #include "../audit_util.c"
27 
28 #include "lib/ldb/include/ldb_private.h"
29 
test_dsdb_audit_add_ldb_value(void ** state)30 static void test_dsdb_audit_add_ldb_value(void **state)
31 {
32 	struct json_object object;
33 	struct json_object array;
34 	struct ldb_val val = data_blob_null;
35 	struct json_t *el  = NULL;
36 	struct json_t *atr = NULL;
37 	char* base64 = NULL;
38 
39 	TALLOC_CTX *ctx = talloc_new(NULL);
40 	/*
41 	 * Test a non array object
42 	 */
43 	object = json_new_object();
44 	assert_false(json_is_invalid(&object));
45 	dsdb_audit_add_ldb_value(&object, val);
46 	assert_true(json_is_invalid(&object));
47 	json_free(&object);
48 
49 	array = json_new_array();
50 	/*
51 	 * Test a data_blob_null, should encode as a JSON null value.
52 	 */
53 	val = data_blob_null;
54 	dsdb_audit_add_ldb_value(&array, val);
55 	el = json_array_get(array.root, 0);
56 	assert_true(json_is_null(el));
57 
58 	/*
59 	 * Test a +ve length but a null data ptr, should encode as a null.
60 	 */
61 	val = data_blob_null;
62 	val.length = 1;
63 	dsdb_audit_add_ldb_value(&array, val);
64 	el = json_array_get(array.root, 1);
65 	assert_true(json_is_null(el));
66 
67 	/*
68 	 * Test a zero length but a non null data ptr, should encode as a null.
69 	 */
70 	val = data_blob_null;
71 	val.data = discard_const("Data on the stack");
72 	dsdb_audit_add_ldb_value(&array, val);
73 	el = json_array_get(array.root, 2);
74 	assert_true(json_is_null(el));
75 
76 	/*
77 	 * Test a printable value.
78 	 * value should not be encoded
79 	 * truncated and base64 should be missing
80 	 */
81 	val = data_blob_string_const("A value of interest");
82 	dsdb_audit_add_ldb_value(&array, val);
83 	el = json_array_get(array.root, 3);
84 	assert_true(json_is_object(el));
85 	atr = json_object_get(el, "value");
86 	assert_true(json_is_string(atr));
87 	assert_string_equal("A value of interest", json_string_value(atr));
88 	assert_null(json_object_get(el, "truncated"));
89 	assert_null(json_object_get(el, "base64"));
90 
91 	/*
92 	 * Test non printable value, should be base64 encoded.
93 	 * truncated should be missing and base64 should be set.
94 	 */
95 	val = data_blob_string_const("A value of interest\n");
96 	dsdb_audit_add_ldb_value(&array, val);
97 	el = json_array_get(array.root, 4);
98 	assert_true(json_is_object(el));
99 	atr = json_object_get(el, "value");
100 	assert_true(json_is_string(atr));
101 	assert_string_equal(
102 		"QSB2YWx1ZSBvZiBpbnRlcmVzdAo=",
103 		json_string_value(atr));
104 	atr = json_object_get(el, "base64");
105 	assert_true(json_is_boolean(atr));
106 	assert_true(json_boolean(atr));
107 	assert_null(json_object_get(el, "truncated"));
108 
109 	/*
110 	 * test a printable value exactly max bytes long
111 	 * should not be truncated or encoded.
112 	 */
113 	val = data_blob_null;
114 	val.length = MAX_LENGTH;
115 	val.data = (unsigned char *)generate_random_str_list(
116 		ctx,
117 		MAX_LENGTH,
118 		"abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
119 		"1234567890!@#$%^&*()");
120 
121 	dsdb_audit_add_ldb_value(&array, val);
122 
123 	el = json_array_get(array.root, 5);
124 	assert_true(json_is_object(el));
125 	atr = json_object_get(el, "value");
126 	assert_true(json_is_string(atr));
127 	assert_int_equal(MAX_LENGTH, strlen(json_string_value(atr)));
128 	assert_memory_equal(val.data, json_string_value(atr), MAX_LENGTH);
129 
130 	assert_null(json_object_get(el, "base64"));
131 	assert_null(json_object_get(el, "truncated"));
132 
133 
134 	/*
135 	 * test a printable value exactly max + 1 bytes long
136 	 * should be truncated and not encoded.
137 	 */
138 	val = data_blob_null;
139 	val.length = MAX_LENGTH + 1;
140 	val.data = (unsigned char *)generate_random_str_list(
141 		ctx,
142 		MAX_LENGTH + 1,
143 		"abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
144 		"1234567890!@#$%^&*()");
145 
146 	dsdb_audit_add_ldb_value(&array, val);
147 
148 	el = json_array_get(array.root, 6);
149 	assert_true(json_is_object(el));
150 	atr = json_object_get(el, "value");
151 	assert_true(json_is_string(atr));
152 	assert_int_equal(MAX_LENGTH, strlen(json_string_value(atr)));
153 	assert_memory_equal(val.data, json_string_value(atr), MAX_LENGTH);
154 
155 	atr = json_object_get(el, "truncated");
156 	assert_true(json_is_boolean(atr));
157 	assert_true(json_boolean(atr));
158 
159 	assert_null(json_object_get(el, "base64"));
160 
161 	TALLOC_FREE(val.data);
162 
163 	/*
164 	 * test a non-printable value exactly max bytes long
165 	 * should not be truncated but should be encoded.
166 	 */
167 	val = data_blob_null;
168 	val.length = MAX_LENGTH;
169 	val.data = (unsigned char *)generate_random_str_list(
170 		ctx,
171 		MAX_LENGTH,
172 		"abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
173 		"1234567890!@#$%^&*()");
174 
175 	val.data[0] = 0x03;
176 	dsdb_audit_add_ldb_value(&array, val);
177 	base64 = ldb_base64_encode(ctx, (char*) val.data, MAX_LENGTH);
178 
179 	el = json_array_get(array.root, 7);
180 	assert_true(json_is_object(el));
181 	atr = json_object_get(el, "value");
182 	assert_true(json_is_string(atr));
183 	assert_int_equal(strlen(base64), strlen(json_string_value(atr)));
184 	assert_string_equal(base64, json_string_value(atr));
185 
186 	atr = json_object_get(el, "base64");
187 	assert_true(json_is_boolean(atr));
188 	assert_true(json_boolean(atr));
189 
190 	assert_null(json_object_get(el, "truncated"));
191 	TALLOC_FREE(base64);
192 	TALLOC_FREE(val.data);
193 
194 	/*
195 	 * test a non-printable value exactly max + 1 bytes long
196 	 * should be truncated and encoded.
197 	 */
198 	val = data_blob_null;
199 	val.length = MAX_LENGTH + 1;
200 	val.data = (unsigned char *)generate_random_str_list(
201 		ctx,
202 		MAX_LENGTH + 1,
203 		"abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
204 		"1234567890!@#$%^&*()");
205 
206 	val.data[0] = 0x03;
207 	dsdb_audit_add_ldb_value(&array, val);
208 	/*
209 	 * The data is truncated before it is base 64 encoded
210 	 */
211 	base64 = ldb_base64_encode(ctx, (char*) val.data, MAX_LENGTH);
212 
213 	el = json_array_get(array.root, 8);
214 	assert_true(json_is_object(el));
215 	atr = json_object_get(el, "value");
216 	assert_true(json_is_string(atr));
217 	assert_int_equal(strlen(base64), strlen(json_string_value(atr)));
218 	assert_string_equal(base64, json_string_value(atr));
219 
220 	atr = json_object_get(el, "base64");
221 	assert_true(json_is_boolean(atr));
222 	assert_true(json_boolean(atr));
223 
224 	atr = json_object_get(el, "truncated");
225 	assert_true(json_is_boolean(atr));
226 	assert_true(json_boolean(atr));
227 
228 	TALLOC_FREE(base64);
229 	TALLOC_FREE(val.data);
230 
231 	json_free(&array);
232 	TALLOC_FREE(ctx);
233 }
234 
test_dsdb_audit_attributes_json(void ** state)235 static void test_dsdb_audit_attributes_json(void **state)
236 {
237 	struct ldb_message *msg = NULL;
238 
239 	struct json_object o;
240 	json_t *a = NULL;
241 	json_t *v = NULL;
242 	json_t *x = NULL;
243 	json_t *y = NULL;
244 
245 	TALLOC_CTX *ctx = talloc_new(NULL);
246 
247 
248 	/*
249 	 * Test an empty message
250 	 * Should get an empty attributes object
251 	 */
252 	msg = talloc_zero(ctx, struct ldb_message);
253 
254 	o = dsdb_audit_attributes_json(LDB_ADD, msg);
255 	assert_true(json_is_object(o.root));
256 	assert_int_equal(0, json_object_size(o.root));
257 	json_free(&o);
258 
259 	o = dsdb_audit_attributes_json(LDB_MODIFY, msg);
260 	assert_true(json_is_object(o.root));
261 	assert_int_equal(0, json_object_size(o.root));
262 	json_free(&o);
263 
264 	/*
265 	 * Test a message with a single secret attribute
266 	 * should only have that object and it should have no value
267 	 * attribute and redacted should be set.
268 	 */
269 	msg = talloc_zero(ctx, struct ldb_message);
270 	ldb_msg_add_string(msg, "clearTextPassword", "secret");
271 
272 	o = dsdb_audit_attributes_json(LDB_ADD, msg);
273 	assert_true(json_is_object(o.root));
274 	assert_int_equal(1, json_object_size(o.root));
275 
276 	a = json_object_get(o.root, "clearTextPassword");
277 	assert_int_equal(1, json_object_size(a));
278 
279 	v = json_object_get(a, "actions");
280 	assert_true(json_is_array(v));
281 	assert_int_equal(1, json_array_size(v));
282 
283 	a = json_array_get(v, 0);
284 	v = json_object_get(a, "redacted");
285 	assert_true(json_is_boolean(v));
286 	assert_true(json_boolean(v));
287 
288 	json_free(&o);
289 
290 	/*
291 	 * Test as a modify message, should add an action attribute
292 	 */
293 	o = dsdb_audit_attributes_json(LDB_MODIFY, msg);
294 	assert_true(json_is_object(o.root));
295 	assert_int_equal(1, json_object_size(o.root));
296 
297 	a = json_object_get(o.root, "clearTextPassword");
298 	assert_true(json_is_object(a));
299 	assert_int_equal(1, json_object_size(a));
300 
301 	v = json_object_get(a, "actions");
302 	assert_true(json_is_array(v));
303 	assert_int_equal(1, json_array_size(v));
304 
305 	a = json_array_get(v, 0);
306 	v = json_object_get(a, "redacted");
307 	assert_true(json_is_boolean(v));
308 	assert_true(json_boolean(v));
309 
310 	v = json_object_get(a, "action");
311 	assert_true(json_is_string(v));
312 	assert_string_equal("unknown", json_string_value(v));
313 
314 	json_free(&o);
315 	TALLOC_FREE(msg);
316 
317 	/*
318 	 * Test a message with a single attribute, single valued attribute
319 	 */
320 	msg = talloc_zero(ctx, struct ldb_message);
321 	ldb_msg_add_string(msg, "attribute", "value");
322 
323 	o = dsdb_audit_attributes_json(LDB_ADD, msg);
324 	assert_true(json_is_object(o.root));
325 	assert_int_equal(1, json_object_size(o.root));
326 
327 	a = json_object_get(o.root, "attribute");
328 	assert_true(json_is_object(a));
329 	assert_int_equal(1, json_object_size(a));
330 
331 	v = json_object_get(a, "actions");
332 	assert_true(json_is_array(v));
333 	assert_int_equal(1, json_array_size(v));
334 
335 	x = json_array_get(v, 0);
336 	assert_int_equal(2, json_object_size(x));
337 	y = json_object_get(x, "action");
338 	assert_string_equal("add", json_string_value(y));
339 
340 	y = json_object_get(x, "values");
341 	assert_true(json_is_array(y));
342 	assert_int_equal(1, json_array_size(y));
343 
344 	x = json_array_get(y, 0);
345 	assert_true(json_is_object(x));
346 	assert_int_equal(1, json_object_size(x));
347 	y = json_object_get(x, "value");
348 	assert_string_equal("value", json_string_value(y));
349 
350 	json_free(&o);
351 	TALLOC_FREE(msg);
352 
353 	/*
354 	 * Test a message with a single attribute, single valued attribute
355 	 * And as a modify
356 	 */
357 	msg = talloc_zero(ctx, struct ldb_message);
358 	ldb_msg_add_string(msg, "attribute", "value");
359 
360 	o = dsdb_audit_attributes_json(LDB_MODIFY, msg);
361 	assert_true(json_is_object(o.root));
362 	assert_int_equal(1, json_object_size(o.root));
363 
364 	a = json_object_get(o.root, "attribute");
365 	assert_true(json_is_object(a));
366 	assert_int_equal(1, json_object_size(a));
367 
368 	v = json_object_get(a, "actions");
369 	assert_true(json_is_array(v));
370 	assert_int_equal(1, json_array_size(v));
371 
372 	x = json_array_get(v, 0);
373 	assert_int_equal(2, json_object_size(x));
374 	y = json_object_get(x, "action");
375 	assert_string_equal("unknown", json_string_value(y));
376 
377 	y = json_object_get(x, "values");
378 	assert_true(json_is_array(y));
379 	assert_int_equal(1, json_array_size(y));
380 
381 	x = json_array_get(y, 0);
382 	assert_true(json_is_object(x));
383 	assert_int_equal(1, json_object_size(x));
384 	y = json_object_get(x, "value");
385 	assert_string_equal("value", json_string_value(y));
386 
387 	json_free(&o);
388 	TALLOC_FREE(msg);
389 
390 	/*
391 	 * Test a message with a multivalues attributres
392 	 */
393 	msg = talloc_zero(ctx, struct ldb_message);
394 	ldb_msg_add_string(msg, "attribute01", "value01");
395 	ldb_msg_add_string(msg, "attribute02", "value02");
396 	ldb_msg_add_string(msg, "attribute02", "value03");
397 
398 	o = dsdb_audit_attributes_json(LDB_ADD, msg);
399 	assert_true(json_is_object(o.root));
400 	assert_int_equal(2, json_object_size(o.root));
401 
402 	a = json_object_get(o.root, "attribute01");
403 	assert_true(json_is_object(a));
404 	assert_int_equal(1, json_object_size(a));
405 
406 	v = json_object_get(a, "actions");
407 	assert_true(json_is_array(v));
408 	assert_int_equal(1, json_array_size(v));
409 
410 	x = json_array_get(v, 0);
411 	assert_int_equal(2, json_object_size(x));
412 	y = json_object_get(x, "action");
413 	assert_string_equal("add", json_string_value(y));
414 
415 	y = json_object_get(x, "values");
416 	assert_true(json_is_array(y));
417 	assert_int_equal(1, json_array_size(y));
418 
419 	x = json_array_get(y, 0);
420 	assert_true(json_is_object(x));
421 	assert_int_equal(1, json_object_size(x));
422 	y = json_object_get(x, "value");
423 	assert_string_equal("value01", json_string_value(y));
424 
425 	a = json_object_get(o.root, "attribute02");
426 	assert_true(json_is_object(a));
427 	assert_int_equal(1, json_object_size(a));
428 
429 	v = json_object_get(a, "actions");
430 	assert_true(json_is_array(v));
431 	assert_int_equal(1, json_array_size(v));
432 
433 	x = json_array_get(v, 0);
434 	assert_int_equal(2, json_object_size(x));
435 	y = json_object_get(x, "action");
436 	assert_string_equal("add", json_string_value(y));
437 
438 	y = json_object_get(x, "values");
439 	assert_true(json_is_array(y));
440 	assert_int_equal(2, json_array_size(y));
441 
442 	x = json_array_get(y, 0);
443 	assert_true(json_is_object(x));
444 	assert_int_equal(1, json_object_size(x));
445 	v = json_object_get(x, "value");
446 	assert_string_equal("value02", json_string_value(v));
447 
448 	x = json_array_get(y, 1);
449 	assert_true(json_is_object(x));
450 	assert_int_equal(1, json_object_size(x));
451 	v = json_object_get(x, "value");
452 	assert_string_equal("value03", json_string_value(v));
453 
454 	json_free(&o);
455 	TALLOC_FREE(msg);
456 
457 	TALLOC_FREE(ctx);
458 }
459 
test_dsdb_audit_get_remote_address(void ** state)460 static void test_dsdb_audit_get_remote_address(void **state)
461 {
462 	struct ldb_context *ldb = NULL;
463 	const struct tsocket_address *ts = NULL;
464 	struct tsocket_address *in = NULL;
465 
466 	TALLOC_CTX *ctx = talloc_new(NULL);
467 
468 	/*
469 	 * Test a freshly initialized ldb
470 	 * should return NULL
471 	 */
472 	ldb = ldb_init(ctx, NULL);
473 	ts = dsdb_audit_get_remote_address(ldb);
474 	assert_null(ts);
475 
476 	/*
477 	 * opaque set to null, should return NULL
478 	 */
479 	ldb_set_opaque(ldb, "remoteAddress", NULL);
480 	ts = dsdb_audit_get_remote_address(ldb);
481 	assert_null(ts);
482 
483 	/*
484 	 * Ensure that the value set is returned
485 	 */
486 	tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &in);
487 	ldb_set_opaque(ldb, "remoteAddress", in);
488 	ts = dsdb_audit_get_remote_address(ldb);
489 	assert_non_null(ts);
490 	assert_ptr_equal(in, ts);
491 
492 	TALLOC_FREE(ldb);
493 	TALLOC_FREE(ctx);
494 
495 }
496 
test_dsdb_audit_get_ldb_error_string(void ** state)497 static void test_dsdb_audit_get_ldb_error_string(void **state)
498 {
499 	struct ldb_context *ldb = NULL;
500 	struct ldb_module *module = NULL;
501 	const char *s = NULL;
502 	const char * const text = "Custom reason";
503 
504 	TALLOC_CTX *ctx = talloc_new(NULL);
505 
506 	ldb = ldb_init(ctx, NULL);
507 	module = talloc_zero(ctx, struct ldb_module);
508 	module->ldb = ldb;
509 
510 	/*
511 	 * No ldb error string set should get the default error description for
512 	 * the status code
513 	 */
514 	s = dsdb_audit_get_ldb_error_string(module, LDB_ERR_OPERATIONS_ERROR);
515 	assert_string_equal("Operations error", s);
516 
517 	/*
518 	 * Set the error string that should now be returned instead of the
519 	 * default description.
520 	 */
521 	ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, text);
522 	s = dsdb_audit_get_ldb_error_string(module, LDB_ERR_OPERATIONS_ERROR);
523 	/*
524 	 * Only test the start of the string as ldb_error adds location data.
525 	 */
526 	assert_int_equal(0, strncmp(text, s, strlen(text)));
527 
528 	TALLOC_FREE(ctx);
529 }
530 
test_dsdb_audit_get_user_sid(void ** state)531 static void test_dsdb_audit_get_user_sid(void **state)
532 {
533 	struct ldb_context *ldb        = NULL;
534 	struct ldb_module *module      = NULL;
535 	const struct dom_sid *sid      = NULL;
536 	struct auth_session_info *sess = NULL;
537 	struct security_token *token   = NULL;
538 	struct dom_sid sids[2];
539 	const char * const SID0 = "S-1-5-21-2470180966-3899876309-2637894779";
540 	const char * const SID1 = "S-1-5-21-4284042908-2889457889-3672286761";
541 	struct dom_sid_buf sid_buf;
542 
543 
544 	TALLOC_CTX *ctx = talloc_new(NULL);
545 
546 	ldb = ldb_init(ctx, NULL);
547 	module = talloc_zero(ctx, struct ldb_module);
548 	module->ldb = ldb;
549 
550 	/*
551 	 * Freshly initialised structures, will be no session data
552 	 * so expect NULL
553 	 */
554 	sid = dsdb_audit_get_user_sid(module);
555 	assert_null(sid);
556 
557 	/*
558 	 * Now add a NULL session info
559 	 */
560 	ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
561 	sid = dsdb_audit_get_user_sid(module);
562 	assert_null(sid);
563 
564 	/*
565 	 * Now add a session info with no user sid
566 	 */
567 	sess = talloc_zero(ctx, struct auth_session_info);
568 	ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
569 	sid = dsdb_audit_get_user_sid(module);
570 	assert_null(sid);
571 
572 	/*
573 	 * Now add an empty security token.
574 	 */
575 	token = talloc_zero(ctx, struct security_token);
576 	sess->security_token = token;
577 	sid = dsdb_audit_get_user_sid(module);
578 	assert_null(sid);
579 
580 	/*
581 	 * Add a single SID
582 	 */
583 	string_to_sid(&sids[0], SID0);
584 	token->num_sids = 1;
585 	token->sids = sids;
586 	sid = dsdb_audit_get_user_sid(module);
587 	assert_non_null(sid);
588 	dom_sid_str_buf(sid, &sid_buf);
589 	assert_string_equal(SID0, sid_buf.buf);
590 
591 	/*
592 	 * Add a second SID, should still use the first SID
593 	 */
594 	string_to_sid(&sids[1], SID1);
595 	token->num_sids = 2;
596 	sid = dsdb_audit_get_user_sid(module);
597 	assert_non_null(sid);
598 	dom_sid_str_buf(sid, &sid_buf);
599 	assert_string_equal(SID0, sid_buf.buf);
600 
601 
602 	/*
603 	 * Now test a null sid in the first position
604 	 */
605 	token->num_sids = 1;
606 	token->sids = NULL;
607 	sid = dsdb_audit_get_user_sid(module);
608 	assert_null(sid);
609 
610 	TALLOC_FREE(ctx);
611 }
612 
test_dsdb_audit_get_actual_sid(void ** state)613 static void test_dsdb_audit_get_actual_sid(void **state)
614 {
615 	struct ldb_context *ldb        = NULL;
616 	const struct dom_sid *sid      = NULL;
617 	struct auth_session_info *sess = NULL;
618 	struct security_token *token   = NULL;
619 	struct dom_sid sids[2];
620 	const char * const SID0 = "S-1-5-21-2470180966-3899876309-2637894779";
621 	const char * const SID1 = "S-1-5-21-4284042908-2889457889-3672286761";
622 	struct dom_sid_buf sid_buf;
623 
624 
625 	TALLOC_CTX *ctx = talloc_new(NULL);
626 
627 	ldb = ldb_init(ctx, NULL);
628 
629 	/*
630 	 * Freshly initialised structures, will be no session data
631 	 * so expect NULL
632 	 */
633 	sid = dsdb_audit_get_actual_sid(ldb);
634 	assert_null(sid);
635 
636 	/*
637 	 * Now add a NULL session info
638 	 */
639 	ldb_set_opaque(ldb, DSDB_NETWORK_SESSION_INFO, NULL);
640 	sid = dsdb_audit_get_actual_sid(ldb);
641 	assert_null(sid);
642 
643 	/*
644 	 * Now add a session info with no user sid
645 	 */
646 	sess = talloc_zero(ctx, struct auth_session_info);
647 	ldb_set_opaque(ldb, DSDB_NETWORK_SESSION_INFO, sess);
648 	sid = dsdb_audit_get_actual_sid(ldb);
649 	assert_null(sid);
650 
651 	/*
652 	 * Now add an empty security token.
653 	 */
654 	token = talloc_zero(ctx, struct security_token);
655 	sess->security_token = token;
656 	sid = dsdb_audit_get_actual_sid(ldb);
657 	assert_null(sid);
658 
659 	/*
660 	 * Add a single SID
661 	 */
662 	string_to_sid(&sids[0], SID0);
663 	token->num_sids = 1;
664 	token->sids = sids;
665 	sid = dsdb_audit_get_actual_sid(ldb);
666 	assert_non_null(sid);
667 	dom_sid_str_buf(sid, &sid_buf);
668 	assert_string_equal(SID0, sid_buf.buf);
669 
670 	/*
671 	 * Add a second SID, should still use the first SID
672 	 */
673 	string_to_sid(&sids[1], SID1);
674 	token->num_sids = 2;
675 	sid = dsdb_audit_get_actual_sid(ldb);
676 	assert_non_null(sid);
677 	dom_sid_str_buf(sid, &sid_buf);
678 	assert_string_equal(SID0, sid_buf.buf);
679 
680 
681 	/*
682 	 * Now test a null sid in the first position
683 	 */
684 	token->num_sids = 1;
685 	token->sids = NULL;
686 	sid = dsdb_audit_get_actual_sid(ldb);
687 	assert_null(sid);
688 
689 	TALLOC_FREE(ctx);
690 }
691 
test_dsdb_audit_is_system_session(void ** state)692 static void test_dsdb_audit_is_system_session(void **state)
693 {
694 	struct ldb_context *ldb        = NULL;
695 	struct ldb_module *module      = NULL;
696 	const struct dom_sid *sid      = NULL;
697 	struct auth_session_info *sess = NULL;
698 	struct security_token *token   = NULL;
699 	struct dom_sid sids[2];
700 	const char * const SID0 = "S-1-5-21-2470180966-3899876309-2637894779";
701 	const char * const SID1 = "S-1-5-21-4284042908-2889457889-3672286761";
702 
703 
704 	TALLOC_CTX *ctx = talloc_new(NULL);
705 
706 	ldb = ldb_init(ctx, NULL);
707 	module = talloc_zero(ctx, struct ldb_module);
708 	module->ldb = ldb;
709 
710 	/*
711 	 * Freshly initialised structures, will be no session data
712 	 * so expect NULL
713 	 */
714 	assert_false(dsdb_audit_is_system_session(module));
715 
716 	/*
717 	 * Now add a NULL session info
718 	 */
719 	ldb_set_opaque(ldb, DSDB_SESSION_INFO, NULL);
720 	assert_false(dsdb_audit_is_system_session(module));
721 
722 	/*
723 	 * Now add a session info with no user sid
724 	 */
725 	sess = talloc_zero(ctx, struct auth_session_info);
726 	ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
727 	assert_false(dsdb_audit_is_system_session(module));
728 
729 	/*
730 	 * Now add an empty security token.
731 	 */
732 	token = talloc_zero(ctx, struct security_token);
733 	sess->security_token = token;
734 	assert_false(dsdb_audit_is_system_session(module));
735 
736 	/*
737 	 * Add a single SID, non system sid
738 	 */
739 	string_to_sid(&sids[0], SID0);
740 	token->num_sids = 1;
741 	token->sids = sids;
742 	assert_false(dsdb_audit_is_system_session(module));
743 
744 	/*
745 	 * Add the system SID to the second position,
746 	 * this should be ignored.
747 	 */
748 	token->num_sids = 2;
749 	sids[1] = global_sid_System;
750 	assert_false(dsdb_audit_is_system_session(module));
751 
752 	/*
753 	 * Add a single SID, system sid
754 	 */
755 	token->num_sids = 1;
756 	sids[0] = global_sid_System;
757 	token->sids = sids;
758 	assert_true(dsdb_audit_is_system_session(module));
759 
760 	/*
761 	 * Add a non system SID to position 2
762 	 */
763 	sids[0] = global_sid_System;
764 	string_to_sid(&sids[1], SID1);
765 	token->num_sids = 2;
766 	token->sids = sids;
767 	assert_true(dsdb_audit_is_system_session(module));
768 
769 	/*
770 	 * Now test a null sid in the first position
771 	 */
772 	token->num_sids = 1;
773 	token->sids = NULL;
774 	sid = dsdb_audit_get_user_sid(module);
775 	assert_null(sid);
776 
777 	TALLOC_FREE(ctx);
778 }
779 
test_dsdb_audit_get_unique_session_token(void ** state)780 static void test_dsdb_audit_get_unique_session_token(void **state)
781 {
782 	struct ldb_context *ldb = NULL;
783 	struct ldb_module *module = NULL;
784 	struct auth_session_info *sess = NULL;
785 	const struct GUID *guid;
786 	const char * const GUID_S = "7130cb06-2062-6a1b-409e-3514c26b1773";
787 	struct GUID in;
788 	char *guid_str;
789 	struct GUID_txt_buf guid_buff;
790 
791 
792 	TALLOC_CTX *ctx = talloc_new(NULL);
793 
794 	ldb = ldb_init(ctx, NULL);
795 	module = talloc_zero(ctx, struct ldb_module);
796 	module->ldb = ldb;
797 
798 	/*
799 	 * Test a freshly initialized ldb
800 	 * should return NULL
801 	 */
802 	guid = dsdb_audit_get_unique_session_token(module);
803 	assert_null(guid);
804 
805 	/*
806 	 * Now add a NULL session info
807 	 */
808 	ldb_set_opaque(ldb, DSDB_SESSION_INFO, NULL);
809 	guid = dsdb_audit_get_unique_session_token(module);
810 	assert_null(guid);
811 
812 	/*
813 	 * Now add a session info with no session id
814 	 * Note if the memory has not been zeroed correctly all bets are
815 	 *      probably off.
816 	 */
817 	sess = talloc_zero(ctx, struct auth_session_info);
818 	ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
819 	guid = dsdb_audit_get_unique_session_token(module);
820 	/*
821 	 * We will get a GUID, but it's contents will be undefined
822 	 */
823 	assert_non_null(guid);
824 
825 	/*
826 	 * Now set the session id and confirm that we get it back.
827 	 */
828 	GUID_from_string(GUID_S, &in);
829 	sess->unique_session_token = in;
830 	guid = dsdb_audit_get_unique_session_token(module);
831 	assert_non_null(guid);
832 	guid_str = GUID_buf_string(guid, &guid_buff);
833 	assert_string_equal(GUID_S, guid_str);
834 
835 	TALLOC_FREE(ctx);
836 
837 }
838 
test_dsdb_audit_get_actual_unique_session_token(void ** state)839 static void test_dsdb_audit_get_actual_unique_session_token(void **state)
840 {
841 	struct ldb_context *ldb = NULL;
842 	struct auth_session_info *sess = NULL;
843 	const struct GUID *guid;
844 	const char * const GUID_S = "7130cb06-2062-6a1b-409e-3514c26b1773";
845 	struct GUID in;
846 	char *guid_str;
847 	struct GUID_txt_buf guid_buff;
848 
849 
850 	TALLOC_CTX *ctx = talloc_new(NULL);
851 
852 	ldb = ldb_init(ctx, NULL);
853 
854 	/*
855 	 * Test a freshly initialized ldb
856 	 * should return NULL
857 	 */
858 	guid = dsdb_audit_get_actual_unique_session_token(ldb);
859 	assert_null(guid);
860 
861 	/*
862 	 * Now add a NULL session info
863 	 */
864 	ldb_set_opaque(ldb, DSDB_NETWORK_SESSION_INFO, NULL);
865 	guid = dsdb_audit_get_actual_unique_session_token(ldb);
866 	assert_null(guid);
867 
868 	/*
869 	 * Now add a session info with no session id
870 	 * Note if the memory has not been zeroed correctly all bets are
871 	 *      probably off.
872 	 */
873 	sess = talloc_zero(ctx, struct auth_session_info);
874 	ldb_set_opaque(ldb, DSDB_NETWORK_SESSION_INFO, sess);
875 	guid = dsdb_audit_get_actual_unique_session_token(ldb);
876 	/*
877 	 * We will get a GUID, but it's contents will be undefined
878 	 */
879 	assert_non_null(guid);
880 
881 	/*
882 	 * Now set the session id and confirm that we get it back.
883 	 */
884 	GUID_from_string(GUID_S, &in);
885 	sess->unique_session_token = in;
886 	guid = dsdb_audit_get_actual_unique_session_token(ldb);
887 	assert_non_null(guid);
888 	guid_str = GUID_buf_string(guid, &guid_buff);
889 	assert_string_equal(GUID_S, guid_str);
890 
891 	TALLOC_FREE(ctx);
892 
893 }
894 
test_dsdb_audit_get_remote_host(void ** state)895 static void test_dsdb_audit_get_remote_host(void **state)
896 {
897 	struct ldb_context *ldb = NULL;
898 	char *rh = NULL;
899 	struct tsocket_address *in = NULL;
900 
901 	TALLOC_CTX *ctx = talloc_new(NULL);
902 
903 	ldb = ldb_init(ctx, NULL);
904 
905 	/*
906 	 * Test a freshly initialized ldb
907 	 * should return "Unknown"
908 	 */
909 	rh = dsdb_audit_get_remote_host(ldb, ctx);
910 	assert_string_equal("Unknown", rh);
911 	TALLOC_FREE(rh);
912 
913 	/*
914 	 * opaque set to null, should return NULL
915 	 */
916 	ldb_set_opaque(ldb, "remoteAddress", NULL);
917 	rh = dsdb_audit_get_remote_host(ldb, ctx);
918 	assert_string_equal("Unknown", rh);
919 	TALLOC_FREE(rh);
920 
921 	/*
922 	 * Ensure that the value set is returned
923 	 */
924 	tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 42, &in);
925 	ldb_set_opaque(ldb, "remoteAddress", in);
926 	rh = dsdb_audit_get_remote_host(ldb, ctx);
927 	assert_string_equal("ipv4:127.0.0.1:42", rh);
928 	TALLOC_FREE(rh);
929 
930 	TALLOC_FREE(ctx);
931 
932 }
933 
test_dsdb_audit_get_primary_dn(void ** state)934 static void test_dsdb_audit_get_primary_dn(void **state)
935 {
936 	struct ldb_request *req = NULL;
937 	struct ldb_message *msg = NULL;
938 	struct ldb_context *ldb = NULL;
939 
940 	struct ldb_dn *dn = NULL;
941 
942 	const char * const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
943 	const char *s = NULL;
944 
945 	TALLOC_CTX *ctx = talloc_new(NULL);
946 
947 	req = talloc_zero(ctx, struct ldb_request);
948 	msg = talloc_zero(ctx, struct ldb_message);
949 	ldb = ldb_init(ctx, NULL);
950 	dn = ldb_dn_new(ctx, ldb, DN);
951 
952 	/*
953 	 * Try an empty request.
954 	 */
955 	s = dsdb_audit_get_primary_dn(req);
956 	assert_null(s);
957 
958 	/*
959 	 * Now try an add with a null message.
960 	 */
961 	req->operation = LDB_ADD;
962 	req->op.add.message = NULL;
963 	s = dsdb_audit_get_primary_dn(req);
964 	assert_null(s);
965 
966 	/*
967 	 * Now try an mod with a null message.
968 	 */
969 	req->operation = LDB_MODIFY;
970 	req->op.mod.message = NULL;
971 	s = dsdb_audit_get_primary_dn(req);
972 	assert_null(s);
973 
974 	/*
975 	 * Now try an add with a missing dn
976 	 */
977 	req->operation = LDB_ADD;
978 	req->op.add.message = msg;
979 	s = dsdb_audit_get_primary_dn(req);
980 	assert_null(s);
981 
982 	/*
983 	 * Now try a mod with a messing dn
984 	 */
985 	req->operation = LDB_ADD;
986 	req->op.mod.message = msg;
987 	s = dsdb_audit_get_primary_dn(req);
988 	assert_null(s);
989 
990 	/*
991 	 * Add a dn to the message
992 	 */
993 	msg->dn = dn;
994 
995 	/*
996 	 * Now try an add with a dn
997 	 */
998 	req->operation = LDB_ADD;
999 	req->op.add.message = msg;
1000 	s = dsdb_audit_get_primary_dn(req);
1001 	assert_non_null(s);
1002 	assert_string_equal(DN, s);
1003 
1004 	/*
1005 	 * Now try a mod with a dn
1006 	 */
1007 	req->operation = LDB_MODIFY;
1008 	req->op.mod.message = msg;
1009 	s = dsdb_audit_get_primary_dn(req);
1010 	assert_non_null(s);
1011 	assert_string_equal(DN, s);
1012 
1013 	/*
1014 	 * Try a delete without a dn
1015 	 */
1016 	req->operation = LDB_DELETE;
1017 	req->op.del.dn = NULL;
1018 	s = dsdb_audit_get_primary_dn(req);
1019 	assert_null(s);
1020 
1021 	/*
1022 	 * Try a delete with a dn
1023 	 */
1024 	req->operation = LDB_DELETE;
1025 	req->op.del.dn = dn;
1026 	s = dsdb_audit_get_primary_dn(req);
1027 	assert_non_null(s);
1028 	assert_string_equal(DN, s);
1029 
1030 	/*
1031 	 * Try a rename without a dn
1032 	 */
1033 	req->operation = LDB_RENAME;
1034 	req->op.rename.olddn = NULL;
1035 	s = dsdb_audit_get_primary_dn(req);
1036 	assert_null(s);
1037 
1038 	/*
1039 	 * Try a rename with a dn
1040 	 */
1041 	req->operation = LDB_RENAME;
1042 	req->op.rename.olddn = dn;
1043 	s = dsdb_audit_get_primary_dn(req);
1044 	assert_non_null(s);
1045 	assert_string_equal(DN, s);
1046 
1047 	/*
1048 	 * Try an extended operation, i.e. one that does not have a DN
1049 	 * associated with it for logging purposes.
1050 	 */
1051 	req->operation = LDB_EXTENDED;
1052 	s = dsdb_audit_get_primary_dn(req);
1053 	assert_null(s);
1054 
1055 	TALLOC_FREE(ctx);
1056 }
1057 
test_dsdb_audit_get_message(void ** state)1058 static void test_dsdb_audit_get_message(void **state)
1059 {
1060 	struct ldb_request *req = NULL;
1061 	struct ldb_message *msg = NULL;
1062 	const struct ldb_message *r = NULL;
1063 
1064 
1065 	TALLOC_CTX *ctx = talloc_new(NULL);
1066 
1067 	req = talloc_zero(ctx, struct ldb_request);
1068 	msg = talloc_zero(ctx, struct ldb_message);
1069 
1070 	/*
1071 	 * Test an empty message
1072 	 */
1073 	r = dsdb_audit_get_message(req);
1074 	assert_null(r);
1075 
1076 	/*
1077 	 * Test an add message
1078 	 */
1079 	req->operation = LDB_ADD;
1080 	req->op.add.message = msg;
1081 	r = dsdb_audit_get_message(req);
1082 	assert_ptr_equal(msg, r);
1083 
1084 	/*
1085 	 * Test a modify message
1086 	 */
1087 	req->operation = LDB_MODIFY;
1088 	req->op.mod.message = msg;
1089 	r = dsdb_audit_get_message(req);
1090 	assert_ptr_equal(msg, r);
1091 
1092 	/*
1093 	 * Test a Delete message, i.e. trigger the default case
1094 	 */
1095 	req->operation = LDB_DELETE;
1096 	r = dsdb_audit_get_message(req);
1097 	assert_null(r);
1098 
1099 	TALLOC_FREE(ctx);
1100 }
1101 
test_dsdb_audit_get_secondary_dn(void ** state)1102 static void test_dsdb_audit_get_secondary_dn(void **state)
1103 {
1104 	struct ldb_request *req = NULL;
1105 	struct ldb_context *ldb = NULL;
1106 
1107 	struct ldb_dn *dn = NULL;
1108 
1109 	const char * const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
1110 	const char *s = NULL;
1111 
1112 	TALLOC_CTX *ctx = talloc_new(NULL);
1113 
1114 	req = talloc_zero(ctx, struct ldb_request);
1115 	ldb = ldb_init(ctx, NULL);
1116 	dn = ldb_dn_new(ctx, ldb, DN);
1117 
1118 	/*
1119 	 * Try an empty request.
1120 	 */
1121 	s = dsdb_audit_get_secondary_dn(req);
1122 	assert_null(s);
1123 
1124 	/*
1125 	 * Try a rename without a dn
1126 	 */
1127 	req->operation = LDB_RENAME;
1128 	req->op.rename.newdn = NULL;
1129 	s = dsdb_audit_get_secondary_dn(req);
1130 	assert_null(s);
1131 
1132 	/*
1133 	 * Try a rename with a dn
1134 	 */
1135 	req->operation = LDB_RENAME;
1136 	req->op.rename.newdn = dn;
1137 	s = dsdb_audit_get_secondary_dn(req);
1138 	assert_non_null(s);
1139 	assert_string_equal(DN, s);
1140 
1141 	/*
1142 	 * Try an extended operation, i.e. one that does not have a DN
1143 	 * associated with it for logging purposes.
1144 	 */
1145 	req->operation = LDB_EXTENDED;
1146 	s = dsdb_audit_get_primary_dn(req);
1147 	assert_null(s);
1148 
1149 	TALLOC_FREE(ctx);
1150 }
1151 
test_dsdb_audit_get_operation_name(void ** state)1152 static void test_dsdb_audit_get_operation_name(void **state)
1153 {
1154 	struct ldb_request *req = NULL;
1155 
1156 	TALLOC_CTX *ctx = talloc_new(NULL);
1157 
1158 	req = talloc_zero(ctx, struct ldb_request);
1159 
1160 	req->operation =  LDB_SEARCH;
1161 	assert_string_equal("Search", dsdb_audit_get_operation_name(req));
1162 
1163 	req->operation =  LDB_ADD;
1164 	assert_string_equal("Add", dsdb_audit_get_operation_name(req));
1165 
1166 	req->operation =  LDB_MODIFY;
1167 	assert_string_equal("Modify", dsdb_audit_get_operation_name(req));
1168 
1169 	req->operation =  LDB_DELETE;
1170 	assert_string_equal("Delete", dsdb_audit_get_operation_name(req));
1171 
1172 	req->operation =  LDB_RENAME;
1173 	assert_string_equal("Rename", dsdb_audit_get_operation_name(req));
1174 
1175 	req->operation =  LDB_EXTENDED;
1176 	assert_string_equal("Extended", dsdb_audit_get_operation_name(req));
1177 
1178 	req->operation =  LDB_REQ_REGISTER_CONTROL;
1179 	assert_string_equal(
1180 		"Register Control",
1181 		dsdb_audit_get_operation_name(req));
1182 
1183 	req->operation =  LDB_REQ_REGISTER_PARTITION;
1184 	assert_string_equal(
1185 		"Register Partition",
1186 		dsdb_audit_get_operation_name(req));
1187 
1188 	/*
1189 	 * Trigger the default case
1190 	 */
1191 	req->operation =  -1;
1192 	assert_string_equal("Unknown", dsdb_audit_get_operation_name(req));
1193 
1194 	TALLOC_FREE(ctx);
1195 }
1196 
test_dsdb_audit_get_modification_action(void ** state)1197 static void test_dsdb_audit_get_modification_action(void **state)
1198 {
1199 	assert_string_equal(
1200 		"add",
1201 		dsdb_audit_get_modification_action(LDB_FLAG_MOD_ADD));
1202 	assert_string_equal(
1203 		"delete",
1204 		dsdb_audit_get_modification_action(LDB_FLAG_MOD_DELETE));
1205 	assert_string_equal(
1206 		"replace",
1207 		dsdb_audit_get_modification_action(LDB_FLAG_MOD_REPLACE));
1208 	/*
1209 	 * Trigger the default case
1210 	 */
1211 	assert_string_equal(
1212 		"unknown",
1213 		dsdb_audit_get_modification_action(0));
1214 }
1215 
test_dsdb_audit_is_password_attribute(void ** state)1216 static void test_dsdb_audit_is_password_attribute(void **state)
1217 {
1218 	assert_true(dsdb_audit_is_password_attribute("userPassword"));
1219 	assert_true(dsdb_audit_is_password_attribute("clearTextPassword"));
1220 	assert_true(dsdb_audit_is_password_attribute("unicodePwd"));
1221 	assert_true(dsdb_audit_is_password_attribute("dBCSPwd"));
1222 
1223 	assert_false(dsdb_audit_is_password_attribute("xserPassword"));
1224 }
1225 
test_dsdb_audit_redact_attribute(void ** state)1226 static void test_dsdb_audit_redact_attribute(void **state)
1227 {
1228 	assert_true(dsdb_audit_redact_attribute("userPassword"));
1229 
1230 	assert_true(dsdb_audit_redact_attribute("pekList"));
1231 	assert_true(dsdb_audit_redact_attribute("clearTextPassword"));
1232 	assert_true(dsdb_audit_redact_attribute("initialAuthIncoming"));
1233 
1234 	assert_false(dsdb_audit_redact_attribute("supaskrt"));
1235 }
1236 
main(void)1237 int main(void) {
1238 	const struct CMUnitTest tests[] = {
1239 		cmocka_unit_test(test_dsdb_audit_add_ldb_value),
1240 		cmocka_unit_test(test_dsdb_audit_attributes_json),
1241 		cmocka_unit_test(test_dsdb_audit_get_remote_address),
1242 		cmocka_unit_test(test_dsdb_audit_get_ldb_error_string),
1243 		cmocka_unit_test(test_dsdb_audit_get_user_sid),
1244 		cmocka_unit_test(test_dsdb_audit_get_actual_sid),
1245 		cmocka_unit_test(test_dsdb_audit_is_system_session),
1246 		cmocka_unit_test(test_dsdb_audit_get_unique_session_token),
1247 		cmocka_unit_test(test_dsdb_audit_get_actual_unique_session_token),
1248 		cmocka_unit_test(test_dsdb_audit_get_remote_host),
1249 		cmocka_unit_test(test_dsdb_audit_get_primary_dn),
1250 		cmocka_unit_test(test_dsdb_audit_get_message),
1251 		cmocka_unit_test(test_dsdb_audit_get_secondary_dn),
1252 		cmocka_unit_test(test_dsdb_audit_get_operation_name),
1253 		cmocka_unit_test(test_dsdb_audit_get_modification_action),
1254 		cmocka_unit_test(test_dsdb_audit_is_password_attribute),
1255 		cmocka_unit_test(test_dsdb_audit_redact_attribute),
1256 	};
1257 
1258 	cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
1259 	return cmocka_run_group_tests(tests, NULL, NULL);
1260 }
1261