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