dsdb: audit samdb and password changes
[nivanova/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / tests / test_audit_log.c
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 #include <stdarg.h>
21 #include <stddef.h>
22 #include <setjmp.h>
23 #include <unistd.h>
24 #include <cmocka.h>
25
26 int ldb_audit_log_module_init(const char *version);
27 #include "../audit_log.c"
28
29 #include "lib/ldb/include/ldb_private.h"
30 #include <regex.h>
31
32 /*
33  * Test helper to check ISO 8601 timestamps for validity
34  */
35 static void check_timestamp(time_t before, const char* timestamp)
36 {
37         int rc;
38         int usec, tz;
39         char c[2];
40         struct tm tm;
41         time_t after;
42         time_t actual;
43
44
45         after = time(NULL);
46
47         /*
48          * Convert the ISO 8601 timestamp into a time_t
49          * Note for convenience we ignore the value of the microsecond
50          * part of the time stamp.
51          */
52         rc = sscanf(
53                 timestamp,
54                 "%4d-%2d-%2dT%2d:%2d:%2d.%6d%1c%4d",
55                 &tm.tm_year,
56                 &tm.tm_mon,
57                 &tm.tm_mday,
58                 &tm.tm_hour,
59                 &tm.tm_min,
60                 &tm.tm_sec,
61                 &usec,
62                 c,
63                 &tz);
64         assert_int_equal(9, rc);
65         tm.tm_year = tm.tm_year - 1900;
66         tm.tm_mon = tm.tm_mon - 1;
67         tm.tm_isdst = -1;
68         actual = mktime(&tm);
69
70         /*
71          * The timestamp should be before <= actual <= after
72          */
73         assert_true(difftime(actual, before) >= 0);
74         assert_true(difftime(after, actual) >= 0);
75 }
76
77 static void test_has_password_changed(void **state)
78 {
79         struct ldb_context *ldb = NULL;
80         struct ldb_message *msg = NULL;
81
82         TALLOC_CTX *ctx = talloc_new(NULL);
83
84         ldb = talloc_zero(ctx, struct ldb_context);
85
86         /*
87          * Empty message
88          */
89         msg = ldb_msg_new(ldb);
90         assert_false(has_password_changed(msg));
91         TALLOC_FREE(msg);
92
93         /*
94          * No password attributes
95          */
96         msg = ldb_msg_new(ldb);
97         ldb_msg_add_string(msg, "attr01", "value01");
98         assert_false(has_password_changed(msg));
99         TALLOC_FREE(msg);
100
101         /*
102          * No password attributes >1 entries
103          */
104         msg = ldb_msg_new(ldb);
105         ldb_msg_add_string(msg, "attr01", "value01");
106         ldb_msg_add_string(msg, "attr02", "value03");
107         ldb_msg_add_string(msg, "attr03", "value03");
108         assert_false(has_password_changed(msg));
109         TALLOC_FREE(msg);
110
111         /*
112          *  userPassword set
113          */
114         msg = ldb_msg_new(ldb);
115         ldb_msg_add_string(msg, "userPassword", "value01");
116         assert_true(has_password_changed(msg));
117         TALLOC_FREE(msg);
118
119         /*
120          *  clearTextPassword set
121          */
122         msg = ldb_msg_new(ldb);
123         ldb_msg_add_string(msg, "clearTextPassword", "value01");
124         assert_true(has_password_changed(msg));
125         TALLOC_FREE(msg);
126
127         /*
128          *  unicodePwd set
129          */
130         msg = ldb_msg_new(ldb);
131         ldb_msg_add_string(msg, "unicodePwd", "value01");
132         assert_true(has_password_changed(msg));
133         TALLOC_FREE(msg);
134
135         /*
136          *  dBCSPwd set
137          */
138         msg = ldb_msg_new(ldb);
139         ldb_msg_add_string(msg, "dBCSPwd", "value01");
140         assert_true(has_password_changed(msg));
141         TALLOC_FREE(msg);
142
143         /*
144          *  All attributes set
145          */
146         msg = ldb_msg_new(ldb);
147         ldb_msg_add_string(msg, "userPassword", "value01");
148         ldb_msg_add_string(msg, "clearTextPassword", "value02");
149         ldb_msg_add_string(msg, "unicodePwd", "value03");
150         ldb_msg_add_string(msg, "dBCSPwd", "value04");
151         assert_true(has_password_changed(msg));
152         TALLOC_FREE(msg);
153
154         /*
155          *  first attribute is a password attribute
156          */
157         msg = ldb_msg_new(ldb);
158         ldb_msg_add_string(msg, "userPassword", "value01");
159         ldb_msg_add_string(msg, "attr02", "value02");
160         ldb_msg_add_string(msg, "attr03", "value03");
161         ldb_msg_add_string(msg, "attr04", "value04");
162         assert_true(has_password_changed(msg));
163         TALLOC_FREE(msg);
164
165         /*
166          *  last attribute is a password attribute
167          */
168         msg = ldb_msg_new(ldb);
169         ldb_msg_add_string(msg, "attr01", "value01");
170         ldb_msg_add_string(msg, "attr02", "value02");
171         ldb_msg_add_string(msg, "attr03", "value03");
172         ldb_msg_add_string(msg, "clearTextPassword", "value04");
173         assert_true(has_password_changed(msg));
174         TALLOC_FREE(msg);
175
176         /*
177          *  middle attribute is a password attribute
178          */
179         msg = ldb_msg_new(ldb);
180         ldb_msg_add_string(msg, "attr01", "value01");
181         ldb_msg_add_string(msg, "attr02", "value02");
182         ldb_msg_add_string(msg, "unicodePwd", "pwd");
183         ldb_msg_add_string(msg, "attr03", "value03");
184         ldb_msg_add_string(msg, "attr04", "value04");
185         assert_true(has_password_changed(msg));
186         TALLOC_FREE(msg);
187
188         TALLOC_FREE(ctx);
189 }
190
191 static void test_get_password_action(void **state)
192 {
193         struct ldb_context *ldb = NULL;
194         struct ldb_request *req = NULL;
195         struct ldb_reply *reply = NULL;
196         struct dsdb_control_password_acl_validation *pav = NULL;
197
198         TALLOC_CTX *ctx = talloc_new(NULL);
199         ldb = talloc_zero(ctx, struct ldb_context);
200
201         /*
202          * Add request, will always be a reset
203          */
204         ldb_build_add_req(&req, ldb, ctx, NULL, NULL, NULL, NULL, NULL);
205         reply = talloc_zero(ctx, struct ldb_reply);
206         assert_string_equal("Reset", get_password_action(req, reply));
207         TALLOC_FREE(req);
208         TALLOC_FREE(reply);
209
210         /*
211          * No password control acl, expect "Reset"
212          */
213         ldb_build_mod_req(&req, ldb, ctx, NULL, NULL, NULL, NULL, NULL);
214         reply = talloc_zero(ctx, struct ldb_reply);
215         assert_string_equal("Reset", get_password_action(req, reply));
216         TALLOC_FREE(req);
217         TALLOC_FREE(reply);
218
219         /*
220          * dsdb_control_password_acl_validation reset = false, expect "Change"
221          */
222         ldb_build_mod_req(&req, ldb, ctx, NULL, NULL, NULL, NULL, NULL);
223         reply = talloc_zero(ctx, struct ldb_reply);
224         pav = talloc_zero(req, struct dsdb_control_password_acl_validation);
225
226         ldb_reply_add_control(
227                 reply,
228                 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID,
229                 false,
230                 pav);
231         assert_string_equal("Change", get_password_action(req, reply));
232         TALLOC_FREE(req);
233         TALLOC_FREE(reply);
234
235         /*
236          * dsdb_control_password_acl_validation reset = true, expect "Reset"
237          */
238         ldb_build_mod_req(&req, ldb, ctx, NULL, NULL, NULL, NULL, NULL);
239         reply = talloc_zero(ctx, struct ldb_reply);
240         pav = talloc_zero(req, struct dsdb_control_password_acl_validation);
241         pav->pwd_reset = true;
242
243         ldb_reply_add_control(
244                 reply,
245                 DSDB_CONTROL_PASSWORD_ACL_VALIDATION_OID,
246                 false,
247                 pav);
248         assert_string_equal("Reset", get_password_action(req, reply));
249         TALLOC_FREE(req);
250         TALLOC_FREE(reply);
251
252         TALLOC_FREE(ctx);
253 }
254
255 /*
256  * Test helper to validate a version object.
257  */
258 static void check_version(struct json_t *version, int major, int minor)
259 {
260         struct json_t *v = NULL;
261
262         assert_true(json_is_object(version));
263         assert_int_equal(2, json_object_size(version));
264
265         v = json_object_get(version, "major");
266         assert_non_null(v);
267         assert_int_equal(major, json_integer_value(v));
268
269         v = json_object_get(version, "minor");
270         assert_non_null(v);
271         assert_int_equal(minor, json_integer_value(v));
272 }
273
274 /*
275  * minimal unit test of operation_json, that ensures that all the expected
276  * attributes and objects are in the json object.
277  */
278 static void test_operation_json_empty(void **state)
279 {
280         struct ldb_context *ldb = NULL;
281         struct ldb_module  *module = NULL;
282         struct ldb_request *req = NULL;
283         struct ldb_reply *reply = NULL;
284         struct audit_context *ac = NULL;
285
286         struct json_object json;
287         json_t *audit = NULL;
288         json_t *v = NULL;
289         json_t *o = NULL;
290         time_t before;
291
292
293         TALLOC_CTX *ctx = talloc_new(NULL);
294
295         ldb = talloc_zero(ctx, struct ldb_context);
296         ac = talloc_zero(ctx, struct audit_context);
297
298         module = talloc_zero(ctx, struct ldb_module);
299         module->ldb = ldb;
300         ldb_module_set_private(module, ac);
301
302         req = talloc_zero(ctx, struct ldb_request);
303         reply = talloc_zero(ctx, struct ldb_reply);
304         reply->error = LDB_SUCCESS;
305
306         before = time(NULL);
307         json = operation_json(module, req, reply);
308         assert_int_equal(3, json_object_size(json.root));
309
310
311         v = json_object_get(json.root, "type");
312         assert_non_null(v);
313         assert_string_equal("dsdbChange", json_string_value(v));
314
315         v = json_object_get(json.root, "timestamp");
316         assert_non_null(v);
317         assert_true(json_is_string(v));
318         check_timestamp(before, json_string_value(v));
319
320         audit = json_object_get(json.root, "dsdbChange");
321         assert_non_null(audit);
322         assert_true(json_is_object(audit));
323         assert_int_equal(10, json_object_size(audit));
324
325         o = json_object_get(audit, "version");
326         assert_non_null(o);
327         check_version(o, OPERATION_MAJOR, OPERATION_MINOR);
328
329         v = json_object_get(audit, "statusCode");
330         assert_non_null(v);
331         assert_true(json_is_integer(v));
332         assert_int_equal(LDB_SUCCESS, json_integer_value(v));
333
334         v = json_object_get(audit, "status");
335         assert_non_null(v);
336         assert_true(json_is_string(v));
337         assert_string_equal("Success", json_string_value(v));
338
339         v = json_object_get(audit, "operation");
340         assert_non_null(v);
341         assert_true(json_is_string(v));
342         /*
343          * Search operation constant is zero
344          */
345         assert_string_equal("Search", json_string_value(v));
346
347         v = json_object_get(audit, "remoteAddress");
348         assert_non_null(v);
349         assert_true(json_is_null(v));
350
351         v = json_object_get(audit, "userSid");
352         assert_non_null(v);
353         assert_true(json_is_null(v));
354
355         v = json_object_get(audit, "performedAsSystem");
356         assert_non_null(v);
357         assert_true(json_is_boolean(v));
358         assert_true(json_is_false(v));
359
360
361         v = json_object_get(audit, "dn");
362         assert_non_null(v);
363         assert_true(json_is_null(v));
364
365         v = json_object_get(audit, "transactionId");
366         assert_non_null(v);
367         assert_true(json_is_string(v));
368         assert_string_equal(
369                 "00000000-0000-0000-0000-000000000000",
370                 json_string_value(v));
371
372         v = json_object_get(audit, "sessionId");
373         assert_non_null(v);
374         assert_true(json_is_null(v));
375
376         json_free(&json);
377         TALLOC_FREE(ctx);
378
379 }
380
381 /*
382  * unit test of operation_json, that ensures that all the expected
383  * attributes and objects are in the json object.
384  */
385 static void test_operation_json(void **state)
386 {
387         struct ldb_context *ldb = NULL;
388         struct ldb_module  *module = NULL;
389         struct ldb_request *req = NULL;
390         struct ldb_reply *reply = NULL;
391         struct audit_context *ac = NULL;
392
393         struct tsocket_address *ts = NULL;
394
395         struct auth_session_info *sess = NULL;
396         struct security_token *token = NULL;
397         struct dom_sid sid;
398         const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
399         const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
400         struct GUID session_id;
401
402         struct GUID transaction_id;
403         const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
404
405         struct ldb_dn *dn = NULL;
406         const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
407
408         struct ldb_message *msg = NULL;
409
410         struct json_object json;
411         json_t *audit = NULL;
412         json_t *v = NULL;
413         json_t *o = NULL;
414         json_t *a = NULL;
415         json_t *b = NULL;
416         json_t *c = NULL;
417         json_t *d = NULL;
418         json_t *e = NULL;
419         json_t *f = NULL;
420         json_t *g = NULL;
421         time_t before;
422
423
424         TALLOC_CTX *ctx = talloc_new(NULL);
425
426         ldb = talloc_zero(ctx, struct ldb_context);
427
428         ac = talloc_zero(ctx, struct audit_context);
429         GUID_from_string(TRANSACTION, &transaction_id);
430         ac->transaction_guid = transaction_id;
431
432         module = talloc_zero(ctx, struct ldb_module);
433         module->ldb = ldb;
434         ldb_module_set_private(module, ac);
435
436         tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
437         ldb_set_opaque(ldb, "remoteAddress", ts);
438
439         sess = talloc_zero(ctx, struct auth_session_info);
440         token = talloc_zero(ctx, struct security_token);
441         string_to_sid(&sid, SID);
442         token->num_sids = 1;
443         token->sids = &sid;
444         sess->security_token = token;
445         GUID_from_string(SESSION, &session_id);
446         sess->unique_session_token = session_id;
447         ldb_set_opaque(ldb, "sessionInfo", sess);
448
449         msg = talloc_zero(ctx, struct ldb_message);
450         dn = ldb_dn_new(ctx, ldb, DN);
451         msg->dn = dn;
452         ldb_msg_add_string(msg, "attribute", "the-value");
453
454         req = talloc_zero(ctx, struct ldb_request);
455         req->operation =  LDB_ADD;
456         req->op.add.message = msg;
457
458         reply = talloc_zero(ctx, struct ldb_reply);
459         reply->error = LDB_ERR_OPERATIONS_ERROR;
460
461         before = time(NULL);
462         json = operation_json(module, req, reply);
463         assert_int_equal(3, json_object_size(json.root));
464
465         v = json_object_get(json.root, "type");
466         assert_non_null(v);
467         assert_string_equal("dsdbChange", json_string_value(v));
468
469         v = json_object_get(json.root, "timestamp");
470         assert_non_null(v);
471         assert_true(json_is_string(v));
472         check_timestamp(before, json_string_value(v));
473
474         audit = json_object_get(json.root, "dsdbChange");
475         assert_non_null(audit);
476         assert_true(json_is_object(audit));
477         assert_int_equal(11, json_object_size(audit));
478
479         o = json_object_get(audit, "version");
480         assert_non_null(o);
481         check_version(o, OPERATION_MAJOR, OPERATION_MINOR);
482
483         v = json_object_get(audit, "statusCode");
484         assert_non_null(v);
485         assert_true(json_is_integer(v));
486         assert_int_equal(LDB_ERR_OPERATIONS_ERROR, json_integer_value(v));
487
488         v = json_object_get(audit, "status");
489         assert_non_null(v);
490         assert_true(json_is_string(v));
491         assert_string_equal("Operations error", json_string_value(v));
492
493         v = json_object_get(audit, "operation");
494         assert_non_null(v);
495         assert_true(json_is_string(v));
496         assert_string_equal("Add", json_string_value(v));
497
498         v = json_object_get(audit, "remoteAddress");
499         assert_non_null(v);
500         assert_true(json_is_string(v));
501         assert_string_equal("ipv4:127.0.0.1:0", json_string_value(v));
502
503         v = json_object_get(audit, "userSid");
504         assert_non_null(v);
505         assert_true(json_is_string(v));
506         assert_string_equal(SID, json_string_value(v));
507
508         v = json_object_get(audit, "performedAsSystem");
509         assert_non_null(v);
510         assert_true(json_is_boolean(v));
511         assert_true(json_is_false(v));
512
513         v = json_object_get(audit, "dn");
514         assert_non_null(v);
515         assert_true(json_is_string(v));
516         assert_string_equal(DN, json_string_value(v));
517
518         v = json_object_get(audit, "transactionId");
519         assert_non_null(v);
520         assert_true(json_is_string(v));
521         assert_string_equal(TRANSACTION, json_string_value(v));
522
523         v = json_object_get(audit, "sessionId");
524         assert_non_null(v);
525         assert_true(json_is_string(v));
526         assert_string_equal(SESSION, json_string_value(v));
527
528         o = json_object_get(audit, "attributes");
529         assert_non_null(v);
530         assert_true(json_is_object(o));
531         assert_int_equal(1, json_object_size(o));
532
533         a = json_object_get(o, "attribute");
534         assert_non_null(a);
535         assert_true(json_is_object(a));
536
537         b = json_object_get(a, "actions");
538         assert_non_null(b);
539         assert_true(json_is_array(b));
540         assert_int_equal(1, json_array_size(b));
541
542         c = json_array_get(b, 0);
543         assert_non_null(c);
544         assert_true(json_is_object(c));
545
546         d = json_object_get(c, "action");
547         assert_non_null(d);
548         assert_true(json_is_string(d));
549         assert_string_equal("add", json_string_value(d));
550
551         e = json_object_get(c, "values");
552         assert_non_null(b);
553         assert_true(json_is_array(e));
554         assert_int_equal(1, json_array_size(e));
555
556         f = json_array_get(e, 0);
557         assert_non_null(f);
558         assert_true(json_is_object(f));
559         assert_int_equal(1, json_object_size(f));
560
561         g = json_object_get(f, "value");
562         assert_non_null(g);
563         assert_true(json_is_string(g));
564         assert_string_equal("the-value", json_string_value(g));
565
566         json_free(&json);
567         TALLOC_FREE(ctx);
568
569 }
570
571 /*
572  * unit test of operation_json, that ensures that all the expected
573  * attributes and objects are in the json object.
574  * In this case for an operation performed as the system user.
575  */
576 static void test_as_system_operation_json(void **state)
577 {
578         struct ldb_context *ldb = NULL;
579         struct ldb_module  *module = NULL;
580         struct ldb_request *req = NULL;
581         struct ldb_reply *reply = NULL;
582         struct audit_context *ac = NULL;
583
584         struct tsocket_address *ts = NULL;
585
586         struct auth_session_info *sess = NULL;
587         struct auth_session_info *sys_sess = NULL;
588         struct security_token *token = NULL;
589         struct security_token *sys_token = NULL;
590         struct dom_sid sid;
591         const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
592         const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
593         const char * const SYS_SESSION = "7130cb06-2062-6a1b-409e-3514c26b1998";
594         struct GUID session_id;
595         struct GUID sys_session_id;
596
597         struct GUID transaction_id;
598         const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
599
600         struct ldb_dn *dn = NULL;
601         const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
602
603         struct ldb_message *msg = NULL;
604
605         struct json_object json;
606         json_t *audit = NULL;
607         json_t *v = NULL;
608         json_t *o = NULL;
609         json_t *a = NULL;
610         json_t *b = NULL;
611         json_t *c = NULL;
612         json_t *d = NULL;
613         json_t *e = NULL;
614         json_t *f = NULL;
615         json_t *g = NULL;
616         time_t before;
617
618
619         TALLOC_CTX *ctx = talloc_new(NULL);
620
621         ldb = talloc_zero(ctx, struct ldb_context);
622
623         ac = talloc_zero(ctx, struct audit_context);
624         GUID_from_string(TRANSACTION, &transaction_id);
625         ac->transaction_guid = transaction_id;
626
627         module = talloc_zero(ctx, struct ldb_module);
628         module->ldb = ldb;
629         ldb_module_set_private(module, ac);
630
631         tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
632         ldb_set_opaque(ldb, "remoteAddress", ts);
633
634         sess = talloc_zero(ctx, struct auth_session_info);
635         token = talloc_zero(ctx, struct security_token);
636         string_to_sid(&sid, SID);
637         token->num_sids = 1;
638         token->sids = &sid;
639         sess->security_token = token;
640         GUID_from_string(SESSION, &session_id);
641         sess->unique_session_token = session_id;
642         ldb_set_opaque(ldb, "networkSessionInfo", sess);
643
644         sys_sess = talloc_zero(ctx, struct auth_session_info);
645         sys_token = talloc_zero(ctx, struct security_token);
646         sys_token->num_sids = 1;
647         sys_token->sids = discard_const(&global_sid_System);
648         sys_sess->security_token = sys_token;
649         GUID_from_string(SYS_SESSION, &sys_session_id);
650         sess->unique_session_token = sys_session_id;
651         ldb_set_opaque(ldb, "sessionInfo", sys_sess);
652
653         msg = talloc_zero(ctx, struct ldb_message);
654         dn = ldb_dn_new(ctx, ldb, DN);
655         msg->dn = dn;
656         ldb_msg_add_string(msg, "attribute", "the-value");
657
658         req = talloc_zero(ctx, struct ldb_request);
659         req->operation =  LDB_ADD;
660         req->op.add.message = msg;
661
662         reply = talloc_zero(ctx, struct ldb_reply);
663         reply->error = LDB_ERR_OPERATIONS_ERROR;
664
665         before = time(NULL);
666         json = operation_json(module, req, reply);
667         assert_int_equal(3, json_object_size(json.root));
668
669         v = json_object_get(json.root, "type");
670         assert_non_null(v);
671         assert_string_equal("dsdbChange", json_string_value(v));
672
673         v = json_object_get(json.root, "timestamp");
674         assert_non_null(v);
675         assert_true(json_is_string(v));
676         check_timestamp(before, json_string_value(v));
677
678         audit = json_object_get(json.root, "dsdbChange");
679         assert_non_null(audit);
680         assert_true(json_is_object(audit));
681         assert_int_equal(11, json_object_size(audit));
682
683         o = json_object_get(audit, "version");
684         assert_non_null(o);
685         check_version(o, OPERATION_MAJOR, OPERATION_MINOR);
686
687         v = json_object_get(audit, "statusCode");
688         assert_non_null(v);
689         assert_true(json_is_integer(v));
690         assert_int_equal(LDB_ERR_OPERATIONS_ERROR, json_integer_value(v));
691
692         v = json_object_get(audit, "status");
693         assert_non_null(v);
694         assert_true(json_is_string(v));
695         assert_string_equal("Operations error", json_string_value(v));
696
697         v = json_object_get(audit, "operation");
698         assert_non_null(v);
699         assert_true(json_is_string(v));
700         assert_string_equal("Add", json_string_value(v));
701
702         v = json_object_get(audit, "remoteAddress");
703         assert_non_null(v);
704         assert_true(json_is_string(v));
705         assert_string_equal("ipv4:127.0.0.1:0", json_string_value(v));
706
707         v = json_object_get(audit, "userSid");
708         assert_non_null(v);
709         assert_true(json_is_string(v));
710         assert_string_equal(SID, json_string_value(v));
711
712         v = json_object_get(audit, "performedAsSystem");
713         assert_non_null(v);
714         assert_true(json_is_boolean(v));
715         assert_true(json_is_true(v));
716
717         v = json_object_get(audit, "dn");
718         assert_non_null(v);
719         assert_true(json_is_string(v));
720         assert_string_equal(DN, json_string_value(v));
721
722         v = json_object_get(audit, "transactionId");
723         assert_non_null(v);
724         assert_true(json_is_string(v));
725         assert_string_equal(TRANSACTION, json_string_value(v));
726
727         v = json_object_get(audit, "sessionId");
728         assert_non_null(v);
729         assert_true(json_is_string(v));
730         assert_string_equal(SYS_SESSION, json_string_value(v));
731
732         o = json_object_get(audit, "attributes");
733         assert_non_null(v);
734         assert_true(json_is_object(o));
735         assert_int_equal(1, json_object_size(o));
736
737         a = json_object_get(o, "attribute");
738         assert_non_null(a);
739         assert_true(json_is_object(a));
740
741         b = json_object_get(a, "actions");
742         assert_non_null(b);
743         assert_true(json_is_array(b));
744         assert_int_equal(1, json_array_size(b));
745
746         c = json_array_get(b, 0);
747         assert_non_null(c);
748         assert_true(json_is_object(c));
749
750         d = json_object_get(c, "action");
751         assert_non_null(d);
752         assert_true(json_is_string(d));
753         assert_string_equal("add", json_string_value(d));
754
755         e = json_object_get(c, "values");
756         assert_non_null(b);
757         assert_true(json_is_array(e));
758         assert_int_equal(1, json_array_size(e));
759
760         f = json_array_get(e, 0);
761         assert_non_null(f);
762         assert_true(json_is_object(f));
763         assert_int_equal(1, json_object_size(f));
764
765         g = json_object_get(f, "value");
766         assert_non_null(g);
767         assert_true(json_is_string(g));
768         assert_string_equal("the-value", json_string_value(g));
769
770         json_free(&json);
771         TALLOC_FREE(ctx);
772
773 }
774
775 /*
776  * minimal unit test of password_change_json, that ensures that all the expected
777  * attributes and objects are in the json object.
778  */
779 static void test_password_change_json_empty(void **state)
780 {
781         struct ldb_context *ldb = NULL;
782         struct ldb_module  *module = NULL;
783         struct ldb_request *req = NULL;
784         struct ldb_reply *reply = NULL;
785         struct audit_context *ac = NULL;
786
787         struct json_object json;
788         json_t *audit = NULL;
789         json_t *v = NULL;
790         json_t *o = NULL;
791         time_t before;
792
793
794         TALLOC_CTX *ctx = talloc_new(NULL);
795
796         ldb = talloc_zero(ctx, struct ldb_context);
797         ac = talloc_zero(ctx, struct audit_context);
798
799         module = talloc_zero(ctx, struct ldb_module);
800         module->ldb = ldb;
801         ldb_module_set_private(module, ac);
802
803         req = talloc_zero(ctx, struct ldb_request);
804         reply = talloc_zero(ctx, struct ldb_reply);
805         reply->error = LDB_SUCCESS;
806
807         before = time(NULL);
808         json = password_change_json(module, req, reply);
809         assert_int_equal(3, json_object_size(json.root));
810
811
812         v = json_object_get(json.root, "type");
813         assert_non_null(v);
814         assert_string_equal("passwordChange", json_string_value(v));
815
816         v = json_object_get(json.root, "timestamp");
817         assert_non_null(v);
818         assert_true(json_is_string(v));
819         check_timestamp(before, json_string_value(v));
820
821         audit = json_object_get(json.root, "passwordChange");
822         assert_non_null(audit);
823         assert_true(json_is_object(audit));
824         assert_int_equal(9, json_object_size(audit));
825
826         o = json_object_get(audit, "version");
827         assert_non_null(o);
828
829         v = json_object_get(audit, "statusCode");
830         assert_non_null(v);
831
832         v = json_object_get(audit, "status");
833         assert_non_null(v);
834
835         v = json_object_get(audit, "remoteAddress");
836         assert_non_null(v);
837
838         v = json_object_get(audit, "userSid");
839         assert_non_null(v);
840
841         v = json_object_get(audit, "dn");
842         assert_non_null(v);
843
844         v = json_object_get(audit, "transactionId");
845         assert_non_null(v);
846
847         v = json_object_get(audit, "sessionId");
848         assert_non_null(v);
849
850         v = json_object_get(audit, "action");
851         assert_non_null(v);
852
853         json_free(&json);
854         TALLOC_FREE(ctx);
855
856 }
857
858 /*
859  * minimal unit test of password_change_json, that ensures that all the expected
860  * attributes and objects are in the json object.
861  */
862 static void test_password_change_json(void **state)
863 {
864         struct ldb_context *ldb = NULL;
865         struct ldb_module  *module = NULL;
866         struct ldb_request *req = NULL;
867         struct ldb_reply *reply = NULL;
868         struct audit_context *ac = NULL;
869
870         struct tsocket_address *ts = NULL;
871
872         struct auth_session_info *sess = NULL;
873         struct security_token *token = NULL;
874         struct dom_sid sid;
875         const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
876         const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
877         struct GUID session_id;
878
879         struct GUID transaction_id;
880         const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
881
882         struct ldb_dn *dn = NULL;
883         const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
884
885         struct ldb_message *msg = NULL;
886
887         struct json_object json;
888         json_t *audit = NULL;
889         json_t *v = NULL;
890         json_t *o = NULL;
891         time_t before;
892
893         TALLOC_CTX *ctx = talloc_new(NULL);
894
895         ldb = talloc_zero(ctx, struct ldb_context);
896
897         ac = talloc_zero(ctx, struct audit_context);
898         GUID_from_string(TRANSACTION, &transaction_id);
899         ac->transaction_guid = transaction_id;
900
901         module = talloc_zero(ctx, struct ldb_module);
902         module->ldb = ldb;
903         ldb_module_set_private(module, ac);
904
905         tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
906         ldb_set_opaque(ldb, "remoteAddress", ts);
907
908         sess = talloc_zero(ctx, struct auth_session_info);
909         token = talloc_zero(ctx, struct security_token);
910         string_to_sid(&sid, SID);
911         token->num_sids = 1;
912         token->sids = &sid;
913         sess->security_token = token;
914         GUID_from_string(SESSION, &session_id);
915         sess->unique_session_token = session_id;
916         ldb_set_opaque(ldb, "sessionInfo", sess);
917
918         msg = talloc_zero(ctx, struct ldb_message);
919         dn = ldb_dn_new(ctx, ldb, DN);
920         msg->dn = dn;
921         ldb_msg_add_string(msg, "planTextPassword", "super-secret");
922
923         req = talloc_zero(ctx, struct ldb_request);
924         req->operation =  LDB_ADD;
925         req->op.add.message = msg;
926         reply = talloc_zero(ctx, struct ldb_reply);
927         reply->error = LDB_SUCCESS;
928
929         before = time(NULL);
930         json = password_change_json(module, req, reply);
931         assert_int_equal(3, json_object_size(json.root));
932
933
934         v = json_object_get(json.root, "type");
935         assert_non_null(v);
936         assert_string_equal("passwordChange", json_string_value(v));
937
938         v = json_object_get(json.root, "timestamp");
939         assert_non_null(v);
940         assert_true(json_is_string(v));
941         check_timestamp(before, json_string_value(v));
942
943         audit = json_object_get(json.root, "passwordChange");
944         assert_non_null(audit);
945         assert_true(json_is_object(audit));
946         assert_int_equal(9, json_object_size(audit));
947
948         o = json_object_get(audit, "version");
949         assert_non_null(o);
950         check_version(o, PASSWORD_MAJOR,PASSWORD_MINOR);
951
952         v = json_object_get(audit, "statusCode");
953         assert_non_null(v);
954         assert_true(json_is_integer(v));
955         assert_int_equal(LDB_SUCCESS, json_integer_value(v));
956
957         v = json_object_get(audit, "status");
958         assert_non_null(v);
959         assert_true(json_is_string(v));
960         assert_string_equal("Success", json_string_value(v));
961
962         v = json_object_get(audit, "remoteAddress");
963         assert_non_null(v);
964         assert_true(json_is_string(v));
965         assert_string_equal("ipv4:127.0.0.1:0", json_string_value(v));
966
967         v = json_object_get(audit, "userSid");
968         assert_non_null(v);
969         assert_true(json_is_string(v));
970         assert_string_equal(SID, json_string_value(v));
971
972         v = json_object_get(audit, "dn");
973         assert_non_null(v);
974         assert_true(json_is_string(v));
975         assert_string_equal(DN, json_string_value(v));
976
977         v = json_object_get(audit, "transactionId");
978         assert_non_null(v);
979         assert_true(json_is_string(v));
980         assert_string_equal(TRANSACTION, json_string_value(v));
981
982         v = json_object_get(audit, "sessionId");
983         assert_non_null(v);
984         assert_true(json_is_string(v));
985         assert_string_equal(SESSION, json_string_value(v));
986
987         v = json_object_get(audit, "action");
988         assert_non_null(v);
989         assert_true(json_is_string(v));
990         assert_string_equal("Reset", json_string_value(v));
991
992         json_free(&json);
993         TALLOC_FREE(ctx);
994
995 }
996
997
998 /*
999  * minimal unit test of transaction_json, that ensures that all the expected
1000  * attributes and objects are in the json object.
1001  */
1002 static void test_transaction_json(void **state)
1003 {
1004
1005         struct GUID guid;
1006         const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
1007
1008         struct json_object json;
1009         json_t *audit = NULL;
1010         json_t *v = NULL;
1011         json_t *o = NULL;
1012         time_t before;
1013
1014         GUID_from_string(GUID, &guid);
1015
1016         before = time(NULL);
1017         json = transaction_json("delete", &guid);
1018
1019         assert_int_equal(3, json_object_size(json.root));
1020
1021
1022         v = json_object_get(json.root, "type");
1023         assert_non_null(v);
1024         assert_string_equal("dsdbTransaction", json_string_value(v));
1025
1026         v = json_object_get(json.root, "timestamp");
1027         assert_non_null(v);
1028         assert_true(json_is_string(v));
1029         check_timestamp(before, json_string_value(v));
1030
1031         audit = json_object_get(json.root, "dsdbTransaction");
1032         assert_non_null(audit);
1033         assert_true(json_is_object(audit));
1034         assert_int_equal(3, json_object_size(audit));
1035
1036         o = json_object_get(audit, "version");
1037         assert_non_null(o);
1038         check_version(o, TRANSACTION_MAJOR, TRANSACTION_MINOR);
1039
1040         v = json_object_get(audit, "transactionId");
1041         assert_non_null(v);
1042         assert_true(json_is_string(v));
1043         assert_string_equal(GUID, json_string_value(v));
1044
1045         v = json_object_get(audit, "action");
1046         assert_non_null(v);
1047         assert_true(json_is_string(v));
1048         assert_string_equal("delete", json_string_value(v));
1049
1050         json_free(&json);
1051
1052 }
1053
1054 /*
1055  * minimal unit test of commit_failure_json, that ensures that all the
1056  * expected attributes and objects are in the json object.
1057  */
1058 static void test_commit_failure_json(void **state)
1059 {
1060
1061         struct GUID guid;
1062         const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
1063
1064         struct json_object json;
1065         json_t *audit = NULL;
1066         json_t *v = NULL;
1067         json_t *o = NULL;
1068         time_t before;
1069
1070         GUID_from_string(GUID, &guid);
1071
1072         before = time(NULL);
1073         json = commit_failure_json(
1074                 "prepare",
1075                 LDB_ERR_OPERATIONS_ERROR,
1076                 "because",
1077                 &guid);
1078
1079         assert_int_equal(3, json_object_size(json.root));
1080
1081
1082         v = json_object_get(json.root, "type");
1083         assert_non_null(v);
1084         assert_string_equal("dsdbTransaction", json_string_value(v));
1085
1086         v = json_object_get(json.root, "timestamp");
1087         assert_non_null(v);
1088         assert_true(json_is_string(v));
1089         check_timestamp(before, json_string_value(v));
1090
1091         audit = json_object_get(json.root, "dsdbTransaction");
1092         assert_non_null(audit);
1093         assert_true(json_is_object(audit));
1094         assert_int_equal(6, json_object_size(audit));
1095
1096         o = json_object_get(audit, "version");
1097         assert_non_null(o);
1098         check_version(o, TRANSACTION_MAJOR, TRANSACTION_MINOR);
1099
1100         v = json_object_get(audit, "transactionId");
1101         assert_non_null(v);
1102         assert_true(json_is_string(v));
1103         assert_string_equal(GUID, json_string_value(v));
1104
1105         v = json_object_get(audit, "action");
1106         assert_non_null(v);
1107         assert_true(json_is_string(v));
1108         assert_string_equal("prepare", json_string_value(v));
1109
1110         v = json_object_get(audit, "statusCode");
1111         assert_non_null(v);
1112         assert_true(json_is_integer(v));
1113         assert_int_equal(LDB_ERR_OPERATIONS_ERROR, json_integer_value(v));
1114
1115         v = json_object_get(audit, "status");
1116         assert_non_null(v);
1117         assert_true(json_is_string(v));
1118         assert_string_equal("Operations error", json_string_value(v));
1119         v = json_object_get(audit, "status");
1120         assert_non_null(v);
1121
1122         v = json_object_get(audit, "reason");
1123         assert_non_null(v);
1124         assert_true(json_is_string(v));
1125         assert_string_equal("because", json_string_value(v));
1126
1127         json_free(&json);
1128
1129 }
1130
1131 /*
1132  * minimal unit test of replicated_update_json, that ensures that all the
1133  * expected attributes and objects are in the json object.
1134  */
1135 static void test_replicated_update_json_empty(void **state)
1136 {
1137         struct ldb_context *ldb = NULL;
1138         struct ldb_module  *module = NULL;
1139         struct ldb_request *req = NULL;
1140         struct ldb_reply *reply = NULL;
1141         struct audit_context *ac = NULL;
1142         struct dsdb_extended_replicated_objects *ro = NULL;
1143         struct repsFromTo1 *source_dsa = NULL;
1144
1145         struct json_object json;
1146         json_t *audit = NULL;
1147         json_t *v = NULL;
1148         json_t *o = NULL;
1149         time_t before;
1150
1151
1152         TALLOC_CTX *ctx = talloc_new(NULL);
1153
1154         ldb = talloc_zero(ctx, struct ldb_context);
1155         ac = talloc_zero(ctx, struct audit_context);
1156
1157         module = talloc_zero(ctx, struct ldb_module);
1158         module->ldb = ldb;
1159         ldb_module_set_private(module, ac);
1160
1161         source_dsa = talloc_zero(ctx, struct repsFromTo1);
1162         ro = talloc_zero(ctx, struct dsdb_extended_replicated_objects);
1163         ro->source_dsa = source_dsa;
1164         req = talloc_zero(ctx, struct ldb_request);
1165         req->op.extended.data = ro;
1166         req->operation = LDB_EXTENDED;
1167         reply = talloc_zero(ctx, struct ldb_reply);
1168         reply->error = LDB_SUCCESS;
1169
1170         before = time(NULL);
1171         json = replicated_update_json(module, req, reply);
1172         assert_int_equal(3, json_object_size(json.root));
1173
1174
1175         v = json_object_get(json.root, "type");
1176         assert_non_null(v);
1177         assert_string_equal("replicatedUpdate", json_string_value(v));
1178
1179         v = json_object_get(json.root, "timestamp");
1180         assert_non_null(v);
1181         assert_true(json_is_string(v));
1182         check_timestamp(before, json_string_value(v));
1183
1184         audit = json_object_get(json.root, "replicatedUpdate");
1185         assert_non_null(audit);
1186         assert_true(json_is_object(audit));
1187         assert_int_equal(11, json_object_size(audit));
1188
1189         o = json_object_get(audit, "version");
1190         assert_non_null(o);
1191         check_version(o, REPLICATION_MAJOR, REPLICATION_MINOR);
1192
1193         v = json_object_get(audit, "statusCode");
1194         assert_non_null(v);
1195         assert_true(json_is_integer(v));
1196         assert_int_equal(LDB_SUCCESS, json_integer_value(v));
1197
1198         v = json_object_get(audit, "status");
1199         assert_non_null(v);
1200         assert_true(json_is_string(v));
1201         assert_string_equal("Success", json_string_value(v));
1202
1203         v = json_object_get(audit, "transactionId");
1204         assert_non_null(v);
1205         assert_true(json_is_string(v));
1206         assert_string_equal(
1207                 "00000000-0000-0000-0000-000000000000",
1208                 json_string_value(v));
1209
1210         v = json_object_get(audit, "objectCount");
1211         assert_non_null(v);
1212         assert_true(json_is_integer(v));
1213         assert_int_equal(0, json_integer_value(v));
1214
1215         v = json_object_get(audit, "linkCount");
1216         assert_non_null(v);
1217         assert_true(json_is_integer(v));
1218         assert_int_equal(0, json_integer_value(v));
1219
1220         v = json_object_get(audit, "partitionDN");
1221         assert_non_null(v);
1222         assert_true(json_is_null(v));
1223
1224         v = json_object_get(audit, "error");
1225         assert_non_null(v);
1226         assert_true(json_is_string(v));
1227         assert_string_equal(
1228                 "The operation completed successfully.",
1229                 json_string_value(v));
1230
1231         v = json_object_get(audit, "errorCode");
1232         assert_non_null(v);
1233         assert_true(json_is_integer(v));
1234         assert_int_equal(0, json_integer_value(v));
1235
1236         v = json_object_get(audit, "sourceDsa");
1237         assert_non_null(v);
1238         assert_true(json_is_string(v));
1239         assert_string_equal(
1240                 "00000000-0000-0000-0000-000000000000",
1241                 json_string_value(v));
1242
1243         v = json_object_get(audit, "invocationId");
1244         assert_non_null(v);
1245         assert_true(json_is_string(v));
1246         assert_string_equal(
1247                 "00000000-0000-0000-0000-000000000000",
1248                 json_string_value(v));
1249
1250         json_free(&json);
1251         TALLOC_FREE(ctx);
1252
1253 }
1254
1255 /*
1256  * unit test of replicated_update_json, that ensures that all the expected
1257  * attributes and objects are in the json object.
1258  */
1259 static void test_replicated_update_json(void **state)
1260 {
1261         struct ldb_context *ldb = NULL;
1262         struct ldb_module  *module = NULL;
1263         struct ldb_request *req = NULL;
1264         struct ldb_reply *reply = NULL;
1265         struct audit_context *ac = NULL;
1266         struct dsdb_extended_replicated_objects *ro = NULL;
1267         struct repsFromTo1 *source_dsa = NULL;
1268
1269         struct GUID transaction_id;
1270         const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1271
1272         struct ldb_dn *dn = NULL;
1273         const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
1274
1275         struct GUID source_dsa_obj_guid;
1276         const char *const SOURCE_DSA = "7130cb06-2062-6a1b-409e-3514c26b1793";
1277
1278         struct GUID invocation_id;
1279         const char *const INVOCATION_ID =
1280                 "7130cb06-2062-6a1b-409e-3514c26b1893";
1281         struct json_object json;
1282         json_t *audit = NULL;
1283         json_t *v = NULL;
1284         json_t *o = NULL;
1285         time_t before;
1286
1287
1288         TALLOC_CTX *ctx = talloc_new(NULL);
1289
1290         ldb = talloc_zero(ctx, struct ldb_context);
1291
1292         ac = talloc_zero(ctx, struct audit_context);
1293         GUID_from_string(TRANSACTION, &transaction_id);
1294         ac->transaction_guid = transaction_id;
1295
1296         module = talloc_zero(ctx, struct ldb_module);
1297         module->ldb = ldb;
1298         ldb_module_set_private(module, ac);
1299
1300         dn = ldb_dn_new(ctx, ldb, DN);
1301         GUID_from_string(SOURCE_DSA, &source_dsa_obj_guid);
1302         GUID_from_string(INVOCATION_ID, &invocation_id);
1303         source_dsa = talloc_zero(ctx, struct repsFromTo1);
1304         source_dsa->source_dsa_obj_guid = source_dsa_obj_guid;
1305         source_dsa->source_dsa_invocation_id = invocation_id;
1306
1307         ro = talloc_zero(ctx, struct dsdb_extended_replicated_objects);
1308         ro->source_dsa = source_dsa;
1309         ro->num_objects = 808;
1310         ro->linked_attributes_count = 2910;
1311         ro->partition_dn = dn;
1312         ro->error = WERR_NOT_SUPPORTED;
1313
1314
1315         req = talloc_zero(ctx, struct ldb_request);
1316         req->op.extended.data = ro;
1317         req->operation = LDB_EXTENDED;
1318
1319         reply = talloc_zero(ctx, struct ldb_reply);
1320         reply->error = LDB_ERR_NO_SUCH_OBJECT;
1321
1322         before = time(NULL);
1323         json = replicated_update_json(module, req, reply);
1324         assert_int_equal(3, json_object_size(json.root));
1325
1326
1327         v = json_object_get(json.root, "type");
1328         assert_non_null(v);
1329         assert_string_equal("replicatedUpdate", json_string_value(v));
1330
1331         v = json_object_get(json.root, "timestamp");
1332         assert_non_null(v);
1333         assert_true(json_is_string(v));
1334         check_timestamp(before, json_string_value(v));
1335
1336         audit = json_object_get(json.root, "replicatedUpdate");
1337         assert_non_null(audit);
1338         assert_true(json_is_object(audit));
1339         assert_int_equal(11, json_object_size(audit));
1340
1341         o = json_object_get(audit, "version");
1342         assert_non_null(o);
1343         check_version(o, REPLICATION_MAJOR, REPLICATION_MINOR);
1344
1345         v = json_object_get(audit, "statusCode");
1346         assert_non_null(v);
1347         assert_true(json_is_integer(v));
1348         assert_int_equal(LDB_ERR_NO_SUCH_OBJECT, json_integer_value(v));
1349
1350         v = json_object_get(audit, "status");
1351         assert_non_null(v);
1352         assert_true(json_is_string(v));
1353         assert_string_equal("No such object", json_string_value(v));
1354
1355         v = json_object_get(audit, "transactionId");
1356         assert_non_null(v);
1357         assert_true(json_is_string(v));
1358         assert_string_equal(TRANSACTION, json_string_value(v));
1359
1360         v = json_object_get(audit, "objectCount");
1361         assert_non_null(v);
1362         assert_true(json_is_integer(v));
1363         assert_int_equal(808, json_integer_value(v));
1364
1365         v = json_object_get(audit, "linkCount");
1366         assert_non_null(v);
1367         assert_true(json_is_integer(v));
1368         assert_int_equal(2910, json_integer_value(v));
1369
1370         v = json_object_get(audit, "partitionDN");
1371         assert_non_null(v);
1372         assert_true(json_is_string(v));
1373         assert_string_equal(DN, json_string_value(v));
1374
1375         v = json_object_get(audit, "error");
1376         assert_non_null(v);
1377         assert_true(json_is_string(v));
1378         assert_string_equal(
1379                 "The request is not supported.",
1380                 json_string_value(v));
1381
1382         v = json_object_get(audit, "errorCode");
1383         assert_non_null(v);
1384         assert_true(json_is_integer(v));
1385         assert_int_equal(W_ERROR_V(WERR_NOT_SUPPORTED), json_integer_value(v));
1386
1387         v = json_object_get(audit, "sourceDsa");
1388         assert_non_null(v);
1389         assert_true(json_is_string(v));
1390         assert_string_equal(SOURCE_DSA, json_string_value(v));
1391
1392         v = json_object_get(audit, "invocationId");
1393         assert_non_null(v);
1394         assert_true(json_is_string(v));
1395         assert_string_equal(INVOCATION_ID, json_string_value(v));
1396
1397         json_free(&json);
1398         TALLOC_FREE(ctx);
1399
1400 }
1401
1402 /*
1403  * minimal unit test of operation_human_readable, that ensures that all the
1404  * expected attributes and objects are in the json object.
1405  */
1406 static void test_operation_hr_empty(void **state)
1407 {
1408         struct ldb_context *ldb = NULL;
1409         struct ldb_module  *module = NULL;
1410         struct ldb_request *req = NULL;
1411         struct ldb_reply *reply = NULL;
1412         struct audit_context *ac = NULL;
1413
1414         char *line = NULL;
1415         const char *rs = NULL;
1416         regex_t regex;
1417
1418         int ret;
1419
1420         TALLOC_CTX *ctx = talloc_new(NULL);
1421
1422         ldb = talloc_zero(ctx, struct ldb_context);
1423         ac = talloc_zero(ctx, struct audit_context);
1424
1425         module = talloc_zero(ctx, struct ldb_module);
1426         module->ldb = ldb;
1427         ldb_module_set_private(module, ac);
1428
1429         req = talloc_zero(ctx, struct ldb_request);
1430         reply = talloc_zero(ctx, struct ldb_reply);
1431         reply->error = LDB_SUCCESS;
1432
1433         line = operation_human_readable(ctx, module, req, reply);
1434         assert_non_null(line);
1435
1436         /*
1437          * We ignore the timestamp to make this test a little easier
1438          * to write.
1439          */
1440         rs =    "\\[Search] at \\["
1441                 "[^[]*"
1442                 "\\] status \\[Success\\] remote host \\[Unknown\\]"
1443                 " SID \\[(NULL SID)\\] DN \\[(null)\\]";
1444
1445         ret = regcomp(&regex, rs, 0);
1446         assert_int_equal(0, ret);
1447
1448         ret = regexec(&regex, line, 0, NULL, 0);
1449         assert_int_equal(0, ret);
1450
1451         regfree(&regex);
1452         TALLOC_FREE(ctx);
1453
1454 }
1455
1456 /*
1457  * unit test of operation_json, that ensures that all the expected
1458  * attributes and objects are in the json object.
1459  */
1460 static void test_operation_hr(void **state)
1461 {
1462         struct ldb_context *ldb = NULL;
1463         struct ldb_module  *module = NULL;
1464         struct ldb_request *req = NULL;
1465         struct ldb_reply *reply = NULL;
1466         struct audit_context *ac = NULL;
1467
1468         struct tsocket_address *ts = NULL;
1469
1470         struct auth_session_info *sess = NULL;
1471         struct security_token *token = NULL;
1472         struct dom_sid sid;
1473         const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1474         const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1475         struct GUID session_id;
1476
1477         struct GUID transaction_id;
1478         const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1479
1480         struct ldb_dn *dn = NULL;
1481         const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
1482
1483         struct ldb_message *msg = NULL;
1484
1485         char *line = NULL;
1486         const char *rs = NULL;
1487         regex_t regex;
1488
1489         int ret;
1490
1491
1492         TALLOC_CTX *ctx = talloc_new(NULL);
1493
1494         ldb = talloc_zero(ctx, struct ldb_context);
1495
1496         ac = talloc_zero(ctx, struct audit_context);
1497         GUID_from_string(TRANSACTION, &transaction_id);
1498         ac->transaction_guid = transaction_id;
1499
1500         module = talloc_zero(ctx, struct ldb_module);
1501         module->ldb = ldb;
1502         ldb_module_set_private(module, ac);
1503
1504         tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
1505         ldb_set_opaque(ldb, "remoteAddress", ts);
1506
1507         sess = talloc_zero(ctx, struct auth_session_info);
1508         token = talloc_zero(ctx, struct security_token);
1509         string_to_sid(&sid, SID);
1510         token->num_sids = 1;
1511         token->sids = &sid;
1512         sess->security_token = token;
1513         GUID_from_string(SESSION, &session_id);
1514         sess->unique_session_token = session_id;
1515         ldb_set_opaque(ldb, "sessionInfo", sess);
1516
1517         msg = talloc_zero(ctx, struct ldb_message);
1518         dn = ldb_dn_new(ctx, ldb, DN);
1519         msg->dn = dn;
1520         ldb_msg_add_string(msg, "attribute", "the-value");
1521
1522         req = talloc_zero(ctx, struct ldb_request);
1523         req->operation =  LDB_ADD;
1524         req->op.add.message = msg;
1525         reply = talloc_zero(ctx, struct ldb_reply);
1526         reply->error = LDB_SUCCESS;
1527
1528         line = operation_human_readable(ctx, module, req, reply);
1529         assert_non_null(line);
1530
1531         /*
1532          * We ignore the timestamp to make this test a little easier
1533          * to write.
1534          */
1535         rs =    "\\[Add\\] at \\["
1536                 "[^]]*"
1537                 "\\] status \\[Success\\] "
1538                 "remote host \\[ipv4:127.0.0.1:0\\] "
1539                 "SID \\[S-1-5-21-2470180966-3899876309-2637894779\\] "
1540                 "DN \\[dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG\\] "
1541                 "attributes \\[attribute \\[the-value\\]\\]";
1542
1543         ret = regcomp(&regex, rs, 0);
1544         assert_int_equal(0, ret);
1545
1546         ret = regexec(&regex, line, 0, NULL, 0);
1547         assert_int_equal(0, ret);
1548
1549         regfree(&regex);
1550         TALLOC_FREE(ctx);
1551 }
1552
1553 /*
1554  * unit test of operation_json, that ensures that all the expected
1555  * attributes and objects are in the json object.
1556  * In this case the operation is being performed in a system session.
1557  */
1558 static void test_as_system_operation_hr(void **state)
1559 {
1560         struct ldb_context *ldb = NULL;
1561         struct ldb_module  *module = NULL;
1562         struct ldb_request *req = NULL;
1563         struct ldb_reply *reply = NULL;
1564         struct audit_context *ac = NULL;
1565
1566         struct tsocket_address *ts = NULL;
1567
1568         struct auth_session_info *sess = NULL;
1569         struct auth_session_info *sys_sess = NULL;
1570         struct security_token *token = NULL;
1571         struct security_token *sys_token = NULL;
1572         struct dom_sid sid;
1573         const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1574         const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1575         const char * const SYS_SESSION = "7130cb06-2062-6a1b-409e-3514c26b1999";
1576         struct GUID session_id;
1577         struct GUID sys_session_id;
1578
1579         struct GUID transaction_id;
1580         const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1581
1582         struct ldb_dn *dn = NULL;
1583         const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
1584
1585         struct ldb_message *msg = NULL;
1586
1587         char *line = NULL;
1588         const char *rs = NULL;
1589         regex_t regex;
1590
1591         int ret;
1592
1593
1594         TALLOC_CTX *ctx = talloc_new(NULL);
1595
1596         ldb = talloc_zero(ctx, struct ldb_context);
1597
1598         ac = talloc_zero(ctx, struct audit_context);
1599         GUID_from_string(TRANSACTION, &transaction_id);
1600         ac->transaction_guid = transaction_id;
1601
1602         module = talloc_zero(ctx, struct ldb_module);
1603         module->ldb = ldb;
1604         ldb_module_set_private(module, ac);
1605
1606         tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
1607         ldb_set_opaque(ldb, "remoteAddress", ts);
1608
1609         sess = talloc_zero(ctx, struct auth_session_info);
1610         token = talloc_zero(ctx, struct security_token);
1611         string_to_sid(&sid, SID);
1612         token->num_sids = 1;
1613         token->sids = &sid;
1614         sess->security_token = token;
1615         GUID_from_string(SESSION, &session_id);
1616         sess->unique_session_token = session_id;
1617         ldb_set_opaque(ldb, "networkSessionInfo", sess);
1618
1619         sys_sess = talloc_zero(ctx, struct auth_session_info);
1620         sys_token = talloc_zero(ctx, struct security_token);
1621         sys_token->num_sids = 1;
1622         sys_token->sids = discard_const(&global_sid_System);
1623         sys_sess->security_token = sys_token;
1624         GUID_from_string(SYS_SESSION, &sys_session_id);
1625         sess->unique_session_token = sys_session_id;
1626         ldb_set_opaque(ldb, "sessionInfo", sys_sess);
1627
1628         msg = talloc_zero(ctx, struct ldb_message);
1629         dn = ldb_dn_new(ctx, ldb, DN);
1630         msg->dn = dn;
1631         ldb_msg_add_string(msg, "attribute", "the-value");
1632
1633         req = talloc_zero(ctx, struct ldb_request);
1634         req->operation =  LDB_ADD;
1635         req->op.add.message = msg;
1636         reply = talloc_zero(ctx, struct ldb_reply);
1637         reply->error = LDB_SUCCESS;
1638
1639         line = operation_human_readable(ctx, module, req, reply);
1640         assert_non_null(line);
1641
1642         /*
1643          * We ignore the timestamp to make this test a little easier
1644          * to write.
1645          */
1646         rs =    "\\[Add\\] at \\["
1647                 "[^]]*"
1648                 "\\] status \\[Success\\] "
1649                 "remote host \\[ipv4:127.0.0.1:0\\] "
1650                 "SID \\[S-1-5-21-2470180966-3899876309-2637894779\\] "
1651                 "DN \\[dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG\\] "
1652                 "attributes \\[attribute \\[the-value\\]\\]";
1653
1654         ret = regcomp(&regex, rs, 0);
1655         assert_int_equal(0, ret);
1656
1657         ret = regexec(&regex, line, 0, NULL, 0);
1658         assert_int_equal(0, ret);
1659
1660         regfree(&regex);
1661         TALLOC_FREE(ctx);
1662 }
1663
1664 /*
1665  * minimal unit test of password_change_json, that ensures that all the expected
1666  * attributes and objects are in the json object.
1667  */
1668 static void test_password_change_hr_empty(void **state)
1669 {
1670         struct ldb_context *ldb = NULL;
1671         struct ldb_module  *module = NULL;
1672         struct ldb_request *req = NULL;
1673         struct ldb_reply *reply = NULL;
1674         struct audit_context *ac = NULL;
1675
1676         char *line = NULL;
1677         const char *rs = NULL;
1678         regex_t regex;
1679         int ret;
1680
1681         TALLOC_CTX *ctx = talloc_new(NULL);
1682
1683         ldb = talloc_zero(ctx, struct ldb_context);
1684         ac = talloc_zero(ctx, struct audit_context);
1685
1686         module = talloc_zero(ctx, struct ldb_module);
1687         module->ldb = ldb;
1688         ldb_module_set_private(module, ac);
1689
1690         req = talloc_zero(ctx, struct ldb_request);
1691         reply = talloc_zero(ctx, struct ldb_reply);
1692         reply->error = LDB_SUCCESS;
1693
1694         line = password_change_human_readable(ctx, module, req, reply);
1695         assert_non_null(line);
1696
1697         /*
1698          * We ignore the timestamp to make this test a little easier
1699          * to write.
1700          */
1701         rs =    "\\[Reset] at \\["
1702                 "[^[]*"
1703                 "\\] status \\[Success\\] remote host \\[Unknown\\]"
1704                 " SID \\[(NULL SID)\\] DN \\[(null)\\]";
1705
1706         ret = regcomp(&regex, rs, 0);
1707         assert_int_equal(0, ret);
1708
1709         ret = regexec(&regex, line, 0, NULL, 0);
1710         assert_int_equal(0, ret);
1711
1712         regfree(&regex);
1713         TALLOC_FREE(ctx);
1714 }
1715
1716 /*
1717  * minimal unit test of password_change_json, that ensures that all the expected
1718  * attributes and objects are in the json object.
1719  */
1720 static void test_password_change_hr(void **state)
1721 {
1722         struct ldb_context *ldb = NULL;
1723         struct ldb_module  *module = NULL;
1724         struct ldb_request *req = NULL;
1725         struct ldb_reply *reply = NULL;
1726         struct audit_context *ac = NULL;
1727
1728         struct tsocket_address *ts = NULL;
1729
1730         struct auth_session_info *sess = NULL;
1731         struct security_token *token = NULL;
1732         struct dom_sid sid;
1733         const char *const SID = "S-1-5-21-2470180966-3899876309-2637894779";
1734         const char * const SESSION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1735         struct GUID session_id;
1736
1737         struct GUID transaction_id;
1738         const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
1739
1740         struct ldb_dn *dn = NULL;
1741         const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
1742
1743         struct ldb_message *msg = NULL;
1744
1745         char *line = NULL;
1746         const char *rs = NULL;
1747         regex_t regex;
1748         int ret;
1749
1750         TALLOC_CTX *ctx = talloc_new(NULL);
1751
1752         ldb = talloc_zero(ctx, struct ldb_context);
1753
1754         ac = talloc_zero(ctx, struct audit_context);
1755         GUID_from_string(TRANSACTION, &transaction_id);
1756         ac->transaction_guid = transaction_id;
1757
1758         module = talloc_zero(ctx, struct ldb_module);
1759         module->ldb = ldb;
1760         ldb_module_set_private(module, ac);
1761
1762         tsocket_address_inet_from_strings(ctx, "ip", "127.0.0.1", 0, &ts);
1763         ldb_set_opaque(ldb, "remoteAddress", ts);
1764
1765         sess = talloc_zero(ctx, struct auth_session_info);
1766         token = talloc_zero(ctx, struct security_token);
1767         string_to_sid(&sid, SID);
1768         token->num_sids = 1;
1769         token->sids = &sid;
1770         sess->security_token = token;
1771         GUID_from_string(SESSION, &session_id);
1772         sess->unique_session_token = session_id;
1773         ldb_set_opaque(ldb, "sessionInfo", sess);
1774
1775         msg = talloc_zero(ctx, struct ldb_message);
1776         dn = ldb_dn_new(ctx, ldb, DN);
1777         msg->dn = dn;
1778         ldb_msg_add_string(msg, "planTextPassword", "super-secret");
1779
1780         req = talloc_zero(ctx, struct ldb_request);
1781         req->operation =  LDB_ADD;
1782         req->op.add.message = msg;
1783         reply = talloc_zero(ctx, struct ldb_reply);
1784         reply->error = LDB_SUCCESS;
1785
1786         line = password_change_human_readable(ctx, module, req, reply);
1787         assert_non_null(line);
1788
1789         /*
1790          * We ignore the timestamp to make this test a little easier
1791          * to write.
1792          */
1793         rs =    "\\[Reset\\] at \\["
1794                 "[^[]*"
1795                 "\\] status \\[Success\\] "
1796                 "remote host \\[ipv4:127.0.0.1:0\\] "
1797                 "SID \\[S-1-5-21-2470180966-3899876309-2637894779\\] "
1798                 "DN \\[dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG\\]";
1799
1800         ret = regcomp(&regex, rs, 0);
1801         assert_int_equal(0, ret);
1802
1803         ret = regexec(&regex, line, 0, NULL, 0);
1804         assert_int_equal(0, ret);
1805
1806         regfree(&regex);
1807         TALLOC_FREE(ctx);
1808
1809 }
1810
1811 /*
1812  * minimal unit test of transaction_json, that ensures that all the expected
1813  * attributes and objects are in the json object.
1814  */
1815 static void test_transaction_hr(void **state)
1816 {
1817
1818         struct GUID guid;
1819         const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
1820
1821         char *line = NULL;
1822         const char *rs = NULL;
1823         regex_t regex;
1824         int ret;
1825
1826         TALLOC_CTX *ctx = talloc_new(NULL);
1827
1828         GUID_from_string(GUID, &guid);
1829
1830         line = transaction_human_readable(ctx, "delete");
1831         assert_non_null(line);
1832
1833         /*
1834          * We ignore the timestamp to make this test a little easier
1835          * to write.
1836          */
1837         rs = "\\[delete] at \\[[^[]*\\]";
1838
1839         ret = regcomp(&regex, rs, 0);
1840         assert_int_equal(0, ret);
1841
1842         ret = regexec(&regex, line, 0, NULL, 0);
1843         assert_int_equal(0, ret);
1844
1845         regfree(&regex);
1846         TALLOC_FREE(ctx);
1847
1848 }
1849
1850 /*
1851  * minimal unit test of commit_failure_hr, that ensures
1852  * that all the expected conten is in the log entry.
1853  */
1854 static void test_commit_failure_hr(void **state)
1855 {
1856
1857         struct GUID guid;
1858         const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
1859
1860         char *line = NULL;
1861         const char *rs = NULL;
1862         regex_t regex;
1863         int ret;
1864
1865         TALLOC_CTX *ctx = talloc_new(NULL);
1866
1867         GUID_from_string(GUID, &guid);
1868
1869         line = commit_failure_human_readable(
1870                 ctx,
1871                 "commit",
1872                 LDB_ERR_OPERATIONS_ERROR,
1873                 "because");
1874
1875         assert_non_null(line);
1876
1877         /*
1878          * We ignore the timestamp to make this test a little easier
1879          * to write.
1880          */
1881         rs = "\\[commit\\] at \\[[^[]*\\] status \\[1\\] reason \\[because\\]";
1882
1883         ret = regcomp(&regex, rs, 0);
1884         assert_int_equal(0, ret);
1885
1886         ret = regexec(&regex, line, 0, NULL, 0);
1887         assert_int_equal(0, ret);
1888
1889         regfree(&regex);
1890         TALLOC_FREE(ctx);
1891 }
1892
1893 static void test_add_transaction_id(void **state)
1894 {
1895         struct ldb_module  *module = NULL;
1896         struct ldb_request *req = NULL;
1897         struct audit_context *ac = NULL;
1898         struct GUID guid;
1899         const char * const GUID = "7130cb06-2062-6a1b-409e-3514c26b1773";
1900         struct ldb_control * control = NULL;
1901         int status;
1902
1903         TALLOC_CTX *ctx = talloc_new(NULL);
1904
1905         ac = talloc_zero(ctx, struct audit_context);
1906         GUID_from_string(GUID, &guid);
1907         ac->transaction_guid = guid;
1908
1909         module = talloc_zero(ctx, struct ldb_module);
1910         ldb_module_set_private(module, ac);
1911
1912         req = talloc_zero(ctx, struct ldb_request);
1913
1914         status = add_transaction_id(module, req);
1915         assert_int_equal(LDB_SUCCESS, status);
1916
1917         control = ldb_request_get_control(
1918                 req,
1919                 DSDB_CONTROL_TRANSACTION_IDENTIFIER_OID);
1920         assert_non_null(control);
1921         assert_memory_equal(
1922                 &ac->transaction_guid,
1923                 control->data,
1924                 sizeof(struct GUID));
1925
1926         TALLOC_FREE(ctx);
1927 }
1928
1929 static void test_log_attributes(void **state)
1930 {
1931         struct ldb_message *msg = NULL;
1932
1933         char *buf = NULL;
1934         char *str = NULL;
1935         char lv[MAX_LENGTH+2];
1936         char ex[MAX_LENGTH+80];
1937
1938         TALLOC_CTX *ctx = talloc_new(NULL);
1939
1940
1941         /*
1942          * Test an empty message
1943          * Should get empty attributes representation.
1944          */
1945         buf = talloc_zero(ctx, char);
1946         msg = talloc_zero(ctx, struct ldb_message);
1947
1948         str = log_attributes(ctx, buf, LDB_ADD, msg);
1949         assert_string_equal("", str);
1950
1951         TALLOC_FREE(str);
1952         TALLOC_FREE(msg);
1953
1954         /*
1955          * Test a message with a single secret attribute
1956          */
1957         buf = talloc_zero(ctx, char);
1958         msg = talloc_zero(ctx, struct ldb_message);
1959         ldb_msg_add_string(msg, "clearTextPassword", "secret");
1960
1961         str = log_attributes(ctx, buf, LDB_ADD, msg);
1962         assert_string_equal(
1963                 "clearTextPassword [REDACTED SECRET ATTRIBUTE]",
1964                 str);
1965         TALLOC_FREE(str);
1966         /*
1967          * Test as a modify message, should add an action
1968          * action will be unknown as there are no ACL's set
1969          */
1970         buf = talloc_zero(ctx, char);
1971         str = log_attributes(ctx, buf, LDB_MODIFY, msg);
1972         assert_string_equal(
1973                 "unknown: clearTextPassword [REDACTED SECRET ATTRIBUTE]",
1974                 str);
1975
1976         TALLOC_FREE(str);
1977         TALLOC_FREE(msg);
1978
1979         /*
1980          * Test a message with a single attribute, single valued attribute
1981          */
1982         buf = talloc_zero(ctx, char);
1983         msg = talloc_zero(ctx, struct ldb_message);
1984         ldb_msg_add_string(msg, "attribute", "value");
1985
1986         str = log_attributes(ctx, buf, LDB_ADD, msg);
1987         assert_string_equal(
1988                 "attribute [value]",
1989                 str);
1990
1991         TALLOC_FREE(str);
1992         TALLOC_FREE(msg);
1993
1994         /*
1995          * Test a message with a single attribute, single valued attribute
1996          * And as a modify
1997          */
1998         buf = talloc_zero(ctx, char);
1999         msg = talloc_zero(ctx, struct ldb_message);
2000         ldb_msg_add_string(msg, "attribute", "value");
2001
2002         str = log_attributes(ctx, buf, LDB_MODIFY, msg);
2003         assert_string_equal(
2004                 "unknown: attribute [value]",
2005                 str);
2006
2007         TALLOC_FREE(str);
2008         TALLOC_FREE(msg);
2009
2010         /*
2011          * Test a message with multiple attributes and a multi-valued attribute
2012          *
2013          */
2014         buf = talloc_zero(ctx, char);
2015         msg = talloc_zero(ctx, struct ldb_message);
2016         ldb_msg_add_string(msg, "attribute01", "value01");
2017         ldb_msg_add_string(msg, "attribute02", "value02");
2018         ldb_msg_add_string(msg, "attribute02", "value03");
2019
2020         str = log_attributes(ctx, buf, LDB_MODIFY, msg);
2021         assert_string_equal(
2022                 "unknown: attribute01 [value01] "
2023                 "unknown: attribute02 [value02] [value03]",
2024                 str);
2025
2026         TALLOC_FREE(str);
2027         TALLOC_FREE(msg);
2028
2029         /*
2030          * Test a message with a single attribute, single valued attribute
2031          * with a non printable character. Should be base64 encoded
2032          */
2033         buf = talloc_zero(ctx, char);
2034         msg = talloc_zero(ctx, struct ldb_message);
2035         ldb_msg_add_string(msg, "attribute", "value\n");
2036
2037         str = log_attributes(ctx, buf, LDB_ADD, msg);
2038         assert_string_equal("attribute {dmFsdWUK}", str);
2039
2040         TALLOC_FREE(str);
2041         TALLOC_FREE(msg);
2042
2043         /*
2044          * Test a message with a single valued attribute
2045          * with more than MAX_LENGTH characters, should be truncated with
2046          * trailing ...
2047          */
2048         buf = talloc_zero(ctx, char);
2049         msg = talloc_zero(ctx, struct ldb_message);
2050         memset(lv, '\0', sizeof(lv));
2051         memset(lv, 'x', MAX_LENGTH+1);
2052         ldb_msg_add_string(msg, "attribute", lv);
2053
2054         str = log_attributes(ctx, buf, LDB_ADD, msg);
2055         snprintf(ex, sizeof(ex), "attribute [%.*s...]", MAX_LENGTH, lv);
2056         assert_string_equal(ex, str);
2057
2058         TALLOC_FREE(str);
2059         TALLOC_FREE(msg);
2060
2061         TALLOC_FREE(ctx);
2062 }
2063
2064 /*
2065  * minimal unit test of replicated_update_human_readable
2066  */
2067 static void test_replicated_update_hr_empty(void **state)
2068 {
2069         struct ldb_context *ldb = NULL;
2070         struct ldb_module  *module = NULL;
2071         struct ldb_request *req = NULL;
2072         struct ldb_reply *reply = NULL;
2073         struct audit_context *ac = NULL;
2074         struct dsdb_extended_replicated_objects *ro = NULL;
2075         struct repsFromTo1 *source_dsa = NULL;
2076
2077         const char* line = NULL;
2078         const char *rs = NULL;
2079         regex_t regex;
2080         int ret;
2081
2082         TALLOC_CTX *ctx = talloc_new(NULL);
2083
2084         ldb = talloc_zero(ctx, struct ldb_context);
2085         ac = talloc_zero(ctx, struct audit_context);
2086
2087         module = talloc_zero(ctx, struct ldb_module);
2088         module->ldb = ldb;
2089         ldb_module_set_private(module, ac);
2090
2091         source_dsa = talloc_zero(ctx, struct repsFromTo1);
2092         ro = talloc_zero(ctx, struct dsdb_extended_replicated_objects);
2093         ro->source_dsa = source_dsa;
2094         req = talloc_zero(ctx, struct ldb_request);
2095         req->op.extended.data = ro;
2096         req->operation = LDB_EXTENDED;
2097         reply = talloc_zero(ctx, struct ldb_reply);
2098         reply->error = LDB_SUCCESS;
2099
2100         line = replicated_update_human_readable(ctx, module, req, reply);
2101         assert_non_null(line);
2102         /*
2103          * We ignore the timestamp to make this test a little easier
2104          * to write.
2105          */
2106         rs =    "at \\[[^[]*\\] "
2107                 "status \\[Success\\] "
2108                 "error \\[The operation completed successfully.\\] "
2109                 "partition \\[(null)\\] objects \\[0\\] links \\[0\\] "
2110                 "object \\[00000000-0000-0000-0000-000000000000\\] "
2111                 "invocation \\[00000000-0000-0000-0000-000000000000\\]";
2112
2113         ret = regcomp(&regex, rs, 0);
2114         assert_int_equal(0, ret);
2115
2116         ret = regexec(&regex, line, 0, NULL, 0);
2117         assert_int_equal(0, ret);
2118
2119         regfree(&regex);
2120         TALLOC_FREE(ctx);
2121
2122 }
2123
2124 /*
2125  * unit test of replicated_update_human_readable
2126  */
2127 static void test_replicated_update_hr(void **state)
2128 {
2129         struct ldb_context *ldb = NULL;
2130         struct ldb_module  *module = NULL;
2131         struct ldb_request *req = NULL;
2132         struct ldb_reply *reply = NULL;
2133         struct audit_context *ac = NULL;
2134         struct dsdb_extended_replicated_objects *ro = NULL;
2135         struct repsFromTo1 *source_dsa = NULL;
2136
2137         struct GUID transaction_id;
2138         const char *const TRANSACTION = "7130cb06-2062-6a1b-409e-3514c26b1773";
2139
2140         struct ldb_dn *dn = NULL;
2141         const char *const DN = "dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG";
2142
2143         struct GUID source_dsa_obj_guid;
2144         const char *const SOURCE_DSA = "7130cb06-2062-6a1b-409e-3514c26b1793";
2145
2146         struct GUID invocation_id;
2147         const char *const INVOCATION_ID =
2148                 "7130cb06-2062-6a1b-409e-3514c26b1893";
2149
2150         const char* line = NULL;
2151         const char *rs = NULL;
2152         regex_t regex;
2153         int ret;
2154
2155
2156         TALLOC_CTX *ctx = talloc_new(NULL);
2157
2158         ldb = talloc_zero(ctx, struct ldb_context);
2159
2160         ac = talloc_zero(ctx, struct audit_context);
2161         GUID_from_string(TRANSACTION, &transaction_id);
2162         ac->transaction_guid = transaction_id;
2163
2164         module = talloc_zero(ctx, struct ldb_module);
2165         module->ldb = ldb;
2166         ldb_module_set_private(module, ac);
2167
2168         dn = ldb_dn_new(ctx, ldb, DN);
2169         GUID_from_string(SOURCE_DSA, &source_dsa_obj_guid);
2170         GUID_from_string(INVOCATION_ID, &invocation_id);
2171         source_dsa = talloc_zero(ctx, struct repsFromTo1);
2172         source_dsa->source_dsa_obj_guid = source_dsa_obj_guid;
2173         source_dsa->source_dsa_invocation_id = invocation_id;
2174
2175         ro = talloc_zero(ctx, struct dsdb_extended_replicated_objects);
2176         ro->source_dsa = source_dsa;
2177         ro->num_objects = 808;
2178         ro->linked_attributes_count = 2910;
2179         ro->partition_dn = dn;
2180         ro->error = WERR_NOT_SUPPORTED;
2181
2182
2183         req = talloc_zero(ctx, struct ldb_request);
2184         req->op.extended.data = ro;
2185         req->operation = LDB_EXTENDED;
2186
2187         reply = talloc_zero(ctx, struct ldb_reply);
2188         reply->error = LDB_ERR_NO_SUCH_OBJECT;
2189
2190         line = replicated_update_human_readable(ctx, module, req, reply);
2191         assert_non_null(line);
2192
2193         /*
2194          * We ignore the timestamp to make this test a little easier
2195          * to write.
2196          */
2197         rs =    "at \\[[^[]*\\] "
2198                 "status \\[No such object\\] "
2199                 "error \\[The request is not supported.\\] "
2200                 "partition \\[dn=CN=USER,CN=Users,DC=SAMBA,DC=ORG\\] "
2201                 "objects \\[808\\] links \\[2910\\] "
2202                 "object \\[7130cb06-2062-6a1b-409e-3514c26b1793\\] "
2203                 "invocation \\[7130cb06-2062-6a1b-409e-3514c26b1893\\]";
2204
2205         ret = regcomp(&regex, rs, 0);
2206         assert_int_equal(0, ret);
2207
2208         ret = regexec(&regex, line, 0, NULL, 0);
2209         assert_int_equal(0, ret);
2210
2211         regfree(&regex);
2212         TALLOC_FREE(ctx);
2213 }
2214
2215 int main(void) {
2216         const struct CMUnitTest tests[] = {
2217                 cmocka_unit_test(test_has_password_changed),
2218                 cmocka_unit_test(test_get_password_action),
2219                 cmocka_unit_test(test_operation_json_empty),
2220                 cmocka_unit_test(test_operation_json),
2221                 cmocka_unit_test(test_as_system_operation_json),
2222                 cmocka_unit_test(test_password_change_json_empty),
2223                 cmocka_unit_test(test_password_change_json),
2224                 cmocka_unit_test(test_transaction_json),
2225                 cmocka_unit_test(test_commit_failure_json),
2226                 cmocka_unit_test(test_replicated_update_json_empty),
2227                 cmocka_unit_test(test_replicated_update_json),
2228                 cmocka_unit_test(test_add_transaction_id),
2229                 cmocka_unit_test(test_operation_hr_empty),
2230                 cmocka_unit_test(test_operation_hr),
2231                 cmocka_unit_test(test_as_system_operation_hr),
2232                 cmocka_unit_test(test_password_change_hr_empty),
2233                 cmocka_unit_test(test_password_change_hr),
2234                 cmocka_unit_test(test_transaction_hr),
2235                 cmocka_unit_test(test_commit_failure_hr),
2236                 cmocka_unit_test(test_log_attributes),
2237                 cmocka_unit_test(test_replicated_update_hr_empty),
2238                 cmocka_unit_test(test_replicated_update_hr),
2239         };
2240
2241         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
2242         return cmocka_run_group_tests(tests, NULL, NULL);
2243 }