Line data Source code
1 : /*
2 : Unit tests for the dsdb audit logging code code in audit_log.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 : /*
21 : * These tests exercise the error handling code
22 : */
23 :
24 : #include <stdarg.h>
25 : #include <stddef.h>
26 : #include <setjmp.h>
27 : #include <unistd.h>
28 : #include <cmocka.h>
29 :
30 : int ldb_audit_log_module_init(const char *version);
31 : #include "../audit_log.c"
32 : #include "lib/ldb/include/ldb_private.h"
33 :
34 : /*
35 : * cmocka wrappers for json_new_object
36 : */
37 : struct json_object __wrap_json_new_object(void);
38 : struct json_object __real_json_new_object(void);
39 49 : struct json_object __wrap_json_new_object(void)
40 : {
41 :
42 49 : bool use_real = (bool)mock();
43 49 : if (!use_real) {
44 10 : return json_empty_object;
45 : }
46 39 : return __real_json_new_object();
47 : }
48 :
49 : /*
50 : * cmocka wrappers for json_add_version
51 : */
52 : int __wrap_json_add_version(struct json_object *object, int major, int minor);
53 : int __real_json_add_version(struct json_object *object, int major, int minor);
54 20 : int __wrap_json_add_version(struct json_object *object, int major, int minor)
55 : {
56 :
57 20 : int ret = (int)mock();
58 20 : if (ret) {
59 : return ret;
60 : }
61 15 : return __real_json_add_version(object, major, minor);
62 : }
63 :
64 : /*
65 : * cmocka wrappers for json_add_version
66 : */
67 : int __wrap_json_add_timestamp(struct json_object *object);
68 : int __real_json_add_timestamp(struct json_object *object);
69 10 : int __wrap_json_add_timestamp(struct json_object *object)
70 : {
71 :
72 10 : int ret = (int)mock();
73 10 : if (ret) {
74 : return ret;
75 : }
76 5 : return __real_json_add_timestamp(object);
77 : }
78 : /*
79 : * unit test of operation_json, that ensures that all the expected
80 : * attributes and objects are in the json object.
81 : */
82 1 : static void test_operation_json(void **state)
83 : {
84 1 : struct ldb_context *ldb = NULL;
85 1 : struct ldb_module *module = NULL;
86 1 : struct ldb_request *req = NULL;
87 1 : struct ldb_reply *reply = NULL;
88 1 : struct audit_private *audit_private = NULL;
89 :
90 1 : struct tsocket_address *ts = NULL;
91 :
92 1 : struct auth_session_info *sess = NULL;
93 1 : struct security_token *token = NULL;
94 1 : struct dom_sid sid;
95 1 : const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
96 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
97 1 : struct GUID session_id;
98 :
99 1 : struct GUID transaction_id;
100 1 : const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
101 :
102 1 : struct ldb_dn *dn = NULL;
103 1 : const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
104 :
105 1 : struct ldb_message *msg = NULL;
106 :
107 1 : struct json_object json;
108 :
109 :
110 : /*
111 : * Test setup
112 : */
113 1 : TALLOC_CTX *ctx = talloc_new(NULL);
114 :
115 1 : ldb = ldb_init(ctx, NULL);
116 :
117 1 : audit_private = talloc_zero(ctx, struct audit_private);
118 1 : GUID_from_string(TRANSACTION, &transaction_id);
119 1 : audit_private->transaction_guid = transaction_id;
120 :
121 1 : module = talloc_zero(ctx, struct ldb_module);
122 1 : module->ldb = ldb;
123 1 : ldb_module_set_private(module, audit_private);
124 :
125 1 : tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
126 1 : ldb_set_opaque(ldb, "remoteAddress", ts);
127 :
128 1 : sess = talloc_zero(ctx, struct auth_session_info);
129 1 : token = talloc_zero(ctx, struct security_token);
130 1 : string_to_sid(&sid, SID);
131 1 : token->num_sids = 1;
132 1 : token->sids = &sid;
133 1 : sess->security_token = token;
134 1 : GUID_from_string(SESSION, &session_id);
135 1 : sess->unique_session_token = session_id;
136 1 : ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
137 :
138 1 : msg = talloc_zero(ctx, struct ldb_message);
139 1 : dn = ldb_dn_new(ctx, ldb, DN);
140 1 : msg->dn = dn;
141 1 : ldb_msg_add_string(msg, "attribute", "the-value");
142 :
143 1 : req = talloc_zero(ctx, struct ldb_request);
144 1 : req->operation = LDB_ADD;
145 1 : req->op.add.message = msg;
146 :
147 1 : reply = talloc_zero(ctx, struct ldb_reply);
148 1 : reply->error = LDB_ERR_OPERATIONS_ERROR;
149 :
150 : /*
151 : * Fail on the creation of the audit json object
152 : */
153 :
154 1 : will_return(__wrap_json_new_object, false);
155 :
156 1 : json = operation_json(module, req, reply);
157 1 : assert_true(json_is_invalid(&json));
158 :
159 : /*
160 : * Fail adding the version object .
161 : */
162 :
163 1 : will_return(__wrap_json_new_object, true);
164 1 : will_return(__wrap_json_add_version, JSON_ERROR);
165 :
166 1 : json = operation_json(module, req, reply);
167 1 : assert_true(json_is_invalid(&json));
168 :
169 : /*
170 : * Fail on creation of the wrapper.
171 : */
172 :
173 1 : will_return(__wrap_json_new_object, true);
174 1 : will_return(__wrap_json_add_version, 0);
175 1 : will_return(__wrap_json_new_object, true);
176 1 : will_return(__wrap_json_new_object, true);
177 1 : will_return(__wrap_json_new_object, true);
178 1 : will_return(__wrap_json_new_object, false);
179 :
180 1 : json = operation_json(module, req, reply);
181 1 : assert_true(json_is_invalid(&json));
182 :
183 : /*
184 : * Fail adding the timestamp to the wrapper object.
185 : */
186 1 : will_return(__wrap_json_new_object, true);
187 1 : will_return(__wrap_json_add_version, 0);
188 1 : will_return(__wrap_json_new_object, true);
189 1 : will_return(__wrap_json_new_object, true);
190 1 : will_return(__wrap_json_new_object, true);
191 1 : will_return(__wrap_json_new_object, true);
192 1 : will_return(__wrap_json_add_timestamp, JSON_ERROR);
193 :
194 1 : json = operation_json(module, req, reply);
195 1 : assert_true(json_is_invalid(&json));
196 :
197 : /*
198 : * Now test the happy path
199 : */
200 1 : will_return(__wrap_json_new_object, true);
201 1 : will_return(__wrap_json_add_version, 0);
202 1 : will_return(__wrap_json_new_object, true);
203 1 : will_return(__wrap_json_new_object, true);
204 1 : will_return(__wrap_json_new_object, true);
205 1 : will_return(__wrap_json_new_object, true);
206 1 : will_return(__wrap_json_add_timestamp, 0);
207 :
208 1 : json = operation_json(module, req, reply);
209 1 : assert_false(json_is_invalid(&json));
210 1 : json_free(&json);
211 :
212 1 : TALLOC_FREE(ctx);
213 :
214 1 : }
215 :
216 : /*
217 : * minimal unit test of password_change_json, that ensures that all the expected
218 : * attributes and objects are in the json object.
219 : */
220 1 : static void test_password_change_json(void **state)
221 : {
222 1 : struct ldb_context *ldb = NULL;
223 1 : struct ldb_module *module = NULL;
224 1 : struct ldb_request *req = NULL;
225 1 : struct ldb_reply *reply = NULL;
226 1 : struct audit_private *audit_private = NULL;
227 :
228 1 : struct tsocket_address *ts = NULL;
229 :
230 1 : struct auth_session_info *sess = NULL;
231 1 : struct security_token *token = NULL;
232 1 : struct dom_sid sid;
233 1 : const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
234 1 : const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
235 1 : struct GUID session_id;
236 :
237 1 : struct GUID transaction_id;
238 1 : const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
239 :
240 1 : struct ldb_dn *dn = NULL;
241 1 : const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
242 :
243 1 : struct ldb_message *msg = NULL;
244 :
245 1 : struct json_object json;
246 :
247 1 : TALLOC_CTX *ctx = talloc_new(NULL);
248 :
249 1 : ldb = ldb_init(ctx, NULL);
250 :
251 1 : audit_private = talloc_zero(ctx, struct audit_private);
252 1 : GUID_from_string(TRANSACTION, &transaction_id);
253 1 : audit_private->transaction_guid = transaction_id;
254 :
255 1 : module = talloc_zero(ctx, struct ldb_module);
256 1 : module->ldb = ldb;
257 1 : ldb_module_set_private(module, audit_private);
258 :
259 1 : tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
260 1 : ldb_set_opaque(ldb, "remoteAddress", ts);
261 :
262 1 : sess = talloc_zero(ctx, struct auth_session_info);
263 1 : token = talloc_zero(ctx, struct security_token);
264 1 : string_to_sid(&sid, SID);
265 1 : token->num_sids = 1;
266 1 : token->sids = &sid;
267 1 : sess->security_token = token;
268 1 : GUID_from_string(SESSION, &session_id);
269 1 : sess->unique_session_token = session_id;
270 1 : ldb_set_opaque(ldb, DSDB_SESSION_INFO, sess);
271 :
272 1 : msg = talloc_zero(ctx, struct ldb_message);
273 1 : dn = ldb_dn_new(ctx, ldb, DN);
274 1 : msg->dn = dn;
275 1 : ldb_msg_add_string(msg, "planTextPassword", "super-secret");
276 :
277 1 : req = talloc_zero(ctx, struct ldb_request);
278 1 : req->operation = LDB_ADD;
279 1 : req->op.add.message = msg;
280 1 : reply = talloc_zero(ctx, struct ldb_reply);
281 1 : reply->error = LDB_SUCCESS;
282 :
283 :
284 : /*
285 : * Fail on the creation of the audit json object
286 : */
287 :
288 1 : will_return(__wrap_json_new_object, false);
289 1 : json = password_change_json(module, req, reply);
290 :
291 1 : assert_true(json_is_invalid(&json));
292 :
293 : /*
294 : * Fail adding the version object .
295 : */
296 :
297 1 : will_return(__wrap_json_new_object, true);
298 1 : will_return(__wrap_json_add_version, JSON_ERROR);
299 :
300 1 : json = password_change_json(module, req, reply);
301 1 : assert_true(json_is_invalid(&json));
302 :
303 : /*
304 : * Fail on creation of the wrapper.
305 : */
306 :
307 1 : will_return(__wrap_json_new_object, true);
308 1 : will_return(__wrap_json_add_version, 0);
309 1 : will_return(__wrap_json_new_object, false);
310 :
311 1 : json = password_change_json(module, req, reply);
312 1 : assert_true(json_is_invalid(&json));
313 :
314 : /*
315 : * Fail on creation of the time stamp.
316 : */
317 :
318 1 : will_return(__wrap_json_new_object, true);
319 1 : will_return(__wrap_json_add_version, 0);
320 1 : will_return(__wrap_json_new_object, true);
321 1 : will_return(__wrap_json_add_timestamp, JSON_ERROR);
322 :
323 1 : json = password_change_json(module, req, reply);
324 1 : assert_true(json_is_invalid(&json));
325 :
326 : /*
327 : * Now test the happy path
328 : */
329 1 : will_return(__wrap_json_new_object, true);
330 1 : will_return(__wrap_json_add_version, 0);
331 1 : will_return(__wrap_json_new_object, true);
332 1 : will_return(__wrap_json_add_timestamp, 0);
333 :
334 1 : json = password_change_json(module, req, reply);
335 1 : assert_false(json_is_invalid(&json));
336 1 : json_free(&json);
337 :
338 1 : TALLOC_FREE(ctx);
339 1 : }
340 :
341 :
342 : /*
343 : * minimal unit test of transaction_json, that ensures that all the expected
344 : * attributes and objects are in the json object.
345 : */
346 1 : static void test_transaction_json(void **state)
347 : {
348 :
349 1 : struct GUID guid;
350 1 : const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
351 :
352 1 : struct json_object json;
353 :
354 1 : GUID_from_string(GUID, &guid);
355 :
356 :
357 : /*
358 : * Fail on the creation of the audit json object
359 : */
360 :
361 1 : will_return(__wrap_json_new_object, false);
362 :
363 1 : json = transaction_json("delete", &guid, 10000099);
364 1 : assert_true(json_is_invalid(&json));
365 :
366 : /*
367 : * Fail adding the version object .
368 : */
369 :
370 1 : will_return(__wrap_json_new_object, true);
371 1 : will_return(__wrap_json_add_version, JSON_ERROR);
372 :
373 1 : json = transaction_json("delete", &guid, 10000099);
374 1 : assert_true(json_is_invalid(&json));
375 :
376 : /*
377 : * Fail on creation of the wrapper.
378 : */
379 :
380 1 : will_return(__wrap_json_new_object, true);
381 1 : will_return(__wrap_json_add_version, 0);
382 1 : will_return(__wrap_json_new_object, false);
383 :
384 1 : json = transaction_json("delete", &guid, 10000099);
385 1 : assert_true(json_is_invalid(&json));
386 :
387 : /*
388 : * Fail on creation of the time stamp.
389 : */
390 :
391 1 : will_return(__wrap_json_new_object, true);
392 1 : will_return(__wrap_json_add_version, 0);
393 1 : will_return(__wrap_json_new_object, true);
394 1 : will_return(__wrap_json_add_timestamp, JSON_ERROR);
395 :
396 1 : json = transaction_json("delete", &guid, 10000099);
397 1 : assert_true(json_is_invalid(&json));
398 :
399 : /*
400 : * Now test the happy path
401 : */
402 1 : will_return(__wrap_json_new_object, true);
403 1 : will_return(__wrap_json_add_version, 0);
404 1 : will_return(__wrap_json_new_object, true);
405 1 : will_return(__wrap_json_add_timestamp, 0);
406 :
407 1 : json = transaction_json("delete", &guid, 10000099);
408 1 : assert_false(json_is_invalid(&json));
409 1 : json_free(&json);
410 1 : }
411 :
412 : /*
413 : * minimal unit test of commit_failure_json, that ensures that all the
414 : * expected attributes and objects are in the json object.
415 : */
416 1 : static void test_commit_failure_json(void **state)
417 : {
418 :
419 1 : struct GUID guid;
420 1 : const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
421 :
422 1 : struct json_object json;
423 :
424 1 : GUID_from_string(GUID, &guid);
425 :
426 :
427 : /*
428 : * Fail on the creation of the audit json object
429 : */
430 :
431 1 : will_return(__wrap_json_new_object, false);
432 :
433 1 : json = commit_failure_json(
434 : "prepare",
435 : 987876,
436 : LDB_ERR_OPERATIONS_ERROR,
437 : "because",
438 : &guid);
439 1 : assert_true(json_is_invalid(&json));
440 :
441 : /*
442 : * Fail adding the version object .
443 : */
444 :
445 1 : will_return(__wrap_json_new_object, true);
446 1 : will_return(__wrap_json_add_version, JSON_ERROR);
447 :
448 1 : json = commit_failure_json(
449 : "prepare",
450 : 987876,
451 : LDB_ERR_OPERATIONS_ERROR,
452 : "because",
453 : &guid);
454 1 : assert_true(json_is_invalid(&json));
455 :
456 : /*
457 : * Fail on creation of the wrapper.
458 : */
459 :
460 1 : will_return(__wrap_json_new_object, true);
461 1 : will_return(__wrap_json_add_version, 0);
462 1 : will_return(__wrap_json_new_object, false);
463 :
464 1 : json = commit_failure_json(
465 : "prepare",
466 : 987876,
467 : LDB_ERR_OPERATIONS_ERROR,
468 : "because",
469 : &guid);
470 1 : assert_true(json_is_invalid(&json));
471 :
472 : /*
473 : * Fail on creation of the time stamp.
474 : */
475 :
476 1 : will_return(__wrap_json_new_object, true);
477 1 : will_return(__wrap_json_add_version, 0);
478 1 : will_return(__wrap_json_new_object, true);
479 1 : will_return(__wrap_json_add_timestamp, JSON_ERROR);
480 :
481 1 : json = commit_failure_json(
482 : "prepare",
483 : 987876,
484 : LDB_ERR_OPERATIONS_ERROR,
485 : "because",
486 : &guid);
487 1 : assert_true(json_is_invalid(&json));
488 :
489 : /*
490 : * Now test the happy path
491 : */
492 :
493 1 : will_return(__wrap_json_new_object, true);
494 1 : will_return(__wrap_json_add_version, 0);
495 1 : will_return(__wrap_json_new_object, true);
496 1 : will_return(__wrap_json_add_timestamp, 0);
497 :
498 1 : json = commit_failure_json(
499 : "prepare",
500 : 987876,
501 : LDB_ERR_OPERATIONS_ERROR,
502 : "because",
503 : &guid);
504 1 : assert_false(json_is_invalid(&json));
505 1 : json_free(&json);
506 1 : }
507 :
508 : /*
509 : * unit test of replicated_update_json, that ensures that all the expected
510 : * attributes and objects are in the json object.
511 : */
512 1 : static void test_replicated_update_json(void **state)
513 : {
514 1 : struct ldb_context *ldb = NULL;
515 1 : struct ldb_module *module = NULL;
516 1 : struct ldb_request *req = NULL;
517 1 : struct ldb_reply *reply = NULL;
518 1 : struct audit_private *audit_private = NULL;
519 1 : struct dsdb_extended_replicated_objects *ro = NULL;
520 1 : struct repsFromTo1 *source_dsa = NULL;
521 :
522 1 : struct GUID transaction_id;
523 1 : const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
524 :
525 1 : struct ldb_dn *dn = NULL;
526 1 : const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
527 :
528 1 : struct GUID source_dsa_obj_guid;
529 1 : const char *const SOURCE_DSA = "7130cb06-2062-6a1b-409e-3514c26b1793";
530 :
531 1 : struct GUID invocation_id;
532 1 : const char *const INVOCATION_ID =
533 : "7130cb06-2062-6a1b-409e-3514c26b1893";
534 1 : struct json_object json;
535 :
536 1 : TALLOC_CTX *ctx = talloc_new(NULL);
537 :
538 1 : ldb = ldb_init(ctx, NULL);
539 :
540 1 : audit_private = talloc_zero(ctx, struct audit_private);
541 1 : GUID_from_string(TRANSACTION, &transaction_id);
542 1 : audit_private->transaction_guid = transaction_id;
543 :
544 1 : module = talloc_zero(ctx, struct ldb_module);
545 1 : module->ldb = ldb;
546 1 : ldb_module_set_private(module, audit_private);
547 :
548 1 : dn = ldb_dn_new(ctx, ldb, DN);
549 1 : GUID_from_string(SOURCE_DSA, &source_dsa_obj_guid);
550 1 : GUID_from_string(INVOCATION_ID, &invocation_id);
551 1 : source_dsa = talloc_zero(ctx, struct repsFromTo1);
552 1 : source_dsa->source_dsa_obj_guid = source_dsa_obj_guid;
553 1 : source_dsa->source_dsa_invocation_id = invocation_id;
554 :
555 1 : ro = talloc_zero(ctx, struct dsdb_extended_replicated_objects);
556 1 : ro->source_dsa = source_dsa;
557 1 : ro->num_objects = 808;
558 1 : ro->linked_attributes_count = 2910;
559 1 : ro->partition_dn = dn;
560 1 : ro->error = WERR_NOT_SUPPORTED;
561 :
562 :
563 1 : req = talloc_zero(ctx, struct ldb_request);
564 1 : req->op.extended.data = ro;
565 1 : req->operation = LDB_EXTENDED;
566 :
567 1 : reply = talloc_zero(ctx, struct ldb_reply);
568 1 : reply->error = LDB_ERR_NO_SUCH_OBJECT;
569 :
570 :
571 : /*
572 : * Fail on the creation of the audit json object
573 : */
574 :
575 1 : will_return(__wrap_json_new_object, false);
576 :
577 1 : json = replicated_update_json(module, req, reply);
578 1 : assert_true(json_is_invalid(&json));
579 :
580 : /*
581 : * Fail adding the version object .
582 : */
583 :
584 1 : will_return(__wrap_json_new_object, true);
585 1 : will_return(__wrap_json_add_version, JSON_ERROR);
586 :
587 1 : json = replicated_update_json(module, req, reply);
588 1 : assert_true(json_is_invalid(&json));
589 :
590 : /*
591 : * Fail on creation of the wrapper.
592 : */
593 :
594 1 : will_return(__wrap_json_new_object, true);
595 1 : will_return(__wrap_json_add_version, 0);
596 1 : will_return(__wrap_json_new_object, false);
597 :
598 1 : json = replicated_update_json(module, req, reply);
599 1 : assert_true(json_is_invalid(&json));
600 :
601 : /*
602 : * Fail on creation of the time stamp.
603 : */
604 :
605 1 : will_return(__wrap_json_new_object, true);
606 1 : will_return(__wrap_json_add_version, 0);
607 1 : will_return(__wrap_json_new_object, true);
608 1 : will_return(__wrap_json_add_timestamp, JSON_ERROR);
609 :
610 1 : json = replicated_update_json(module, req, reply);
611 1 : assert_true(json_is_invalid(&json));
612 :
613 : /*
614 : * Now test the happy path.
615 : */
616 1 : will_return(__wrap_json_new_object, true);
617 1 : will_return(__wrap_json_add_version, 0);
618 1 : will_return(__wrap_json_new_object, true);
619 1 : will_return(__wrap_json_add_timestamp, 0);
620 :
621 1 : json = replicated_update_json(module, req, reply);
622 1 : assert_false(json_is_invalid(&json));
623 1 : json_free(&json);
624 :
625 1 : TALLOC_FREE(ctx);
626 1 : }
627 :
628 1 : int main(void) {
629 1 : const struct CMUnitTest tests[] = {
630 : cmocka_unit_test(test_operation_json),
631 : cmocka_unit_test(test_password_change_json),
632 : cmocka_unit_test(test_transaction_json),
633 : cmocka_unit_test(test_commit_failure_json),
634 : cmocka_unit_test(test_replicated_update_json),
635 : };
636 :
637 1 : cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
638 1 : return cmocka_run_group_tests(tests, NULL, NULL);
639 : }
|