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