auth logging: Extract common audit logging code
[metze/samba/wip.git] / lib / audit_logging / tests / audit_logging_test.c
1 /*
2  * Unit tests for the audit_logging library.
3  *
4  *  Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 /*
22  * from cmocka.c:
23  * These headers or their equivalents should be included prior to
24  * including
25  * this header file.
26  *
27  * #include <stdarg.h>
28  * #include <stddef.h>
29  * #include <setjmp.h>
30  *
31  * This allows test applications to use custom definitions of C standard
32  * library functions and types.
33  *
34  */
35
36 /*
37  * Note that the messaging routines (audit_message_send and get_event_server)
38  * are not tested by these unit tests.  Currently they are for integration
39  * test support, and as such are exercised by the integration tests.
40  */
41 #include <stdarg.h>
42 #include <stddef.h>
43 #include <setjmp.h>
44 #include <cmocka.h>
45
46 #include <string.h>
47 #include <time.h>
48 #include <tevent.h>
49 #include <config.h>
50 #include <talloc.h>
51 #include "lib/util/talloc_stack.h"
52
53 #include "lib/util/data_blob.h"
54 #include "lib/util/time.h"
55 #include "libcli/util/werror.h"
56 #include "lib/param/loadparm.h"
57 #include "libcli/security/dom_sid.h"
58 #include "librpc/ndr/libndr.h"
59
60 #include "lib/audit_logging/audit_logging.h"
61
62 #ifdef HAVE_JANSSON
63 static void test_json_add_int(void **state)
64 {
65         struct json_object object;
66         struct json_t *value = NULL;
67         double n;
68
69         object = json_new_object();
70         json_add_int(&object, "positive_one", 1);
71         json_add_int(&object, "zero", 0);
72         json_add_int(&object, "negative_one", -1);
73
74
75         assert_int_equal(3, json_object_size(object.root));
76
77         value = json_object_get(object.root, "positive_one");
78         assert_true(json_is_integer(value));
79         n = json_number_value(value);
80         assert_true(n == 1.0);
81
82         value = json_object_get(object.root, "zero");
83         assert_true(json_is_integer(value));
84         n = json_number_value(value);
85         assert_true(n == 0.0);
86
87         value = json_object_get(object.root, "negative_one");
88         assert_true(json_is_integer(value));
89         n = json_number_value(value);
90         assert_true(n == -1.0);
91
92         json_free(&object);
93 }
94
95 static void test_json_add_bool(void **state)
96 {
97         struct json_object object;
98         struct json_t *value = NULL;
99
100         object = json_new_object();
101         json_add_bool(&object, "true", true);
102         json_add_bool(&object, "false", false);
103
104
105         assert_int_equal(2, json_object_size(object.root));
106
107         value = json_object_get(object.root, "true");
108         assert_true(json_is_boolean(value));
109         assert_true(value == json_true());
110
111         value = json_object_get(object.root, "false");
112         assert_true(json_is_boolean(value));
113         assert_true(value == json_false());
114
115         json_free(&object);
116 }
117
118 static void test_json_add_string(void **state)
119 {
120         struct json_object object;
121         struct json_t *value = NULL;
122         const char *s = NULL;
123
124         object = json_new_object();
125         json_add_string(&object, "null", NULL);
126         json_add_string(&object, "empty", "");
127         json_add_string(&object, "name", "value");
128
129
130
131         assert_int_equal(3, json_object_size(object.root));
132
133         value = json_object_get(object.root, "null");
134         assert_true(json_is_null(value));
135
136         value = json_object_get(object.root, "empty");
137         assert_true(json_is_string(value));
138         s = json_string_value(value);
139         assert_string_equal("", s);
140
141         value = json_object_get(object.root, "name");
142         assert_true(json_is_string(value));
143         s = json_string_value(value);
144         assert_string_equal("value", s);
145         json_free(&object);
146 }
147
148 static void test_json_add_object(void **state)
149 {
150         struct json_object object;
151         struct json_object other;
152         struct json_t *value = NULL;
153
154         object = json_new_object();
155         other  = json_new_object();
156         json_add_object(&object, "null", NULL);
157         json_add_object(&object, "other", &other);
158
159
160
161         assert_int_equal(2, json_object_size(object.root));
162
163         value = json_object_get(object.root, "null");
164         assert_true(json_is_null(value));
165
166         value = json_object_get(object.root, "other");
167         assert_true(json_is_object(value));
168         assert_ptr_equal(other.root, value);
169
170         json_free(&object);
171 }
172
173 static void test_json_add_to_array(void **state)
174 {
175         struct json_object array;
176         struct json_object o1;
177         struct json_object o2;
178         struct json_object o3;
179         struct json_t *value = NULL;
180
181         array = json_new_array();
182         assert_true(json_is_array(array.root));
183
184         o1 = json_new_object();
185         o2 = json_new_object();
186         o3 = json_new_object();
187
188         json_add_object(&array, NULL, &o3);
189         json_add_object(&array, "", &o2);
190         json_add_object(&array, "will-be-ignored", &o1);
191         json_add_object(&array, NULL, NULL);
192
193         assert_int_equal(4, json_array_size(array.root));
194
195         value = json_array_get(array.root, 0);
196         assert_ptr_equal(o3.root, value);
197
198         value = json_array_get(array.root, 1);
199         assert_ptr_equal(o2.root, value);
200
201         value = json_array_get(array.root, 2);
202         assert_ptr_equal(o1.root, value);
203
204         value = json_array_get(array.root, 3);
205         assert_true(json_is_null(value));
206
207         json_free(&array);
208
209 }
210
211 static void test_json_add_timestamp(void **state)
212 {
213         struct json_object object;
214         struct json_t *ts = NULL;
215         const char *t = NULL;
216         int rc;
217         int usec, tz;
218         char c[2];
219         struct tm tm;
220         time_t before;
221         time_t after;
222         time_t actual;
223
224
225         object = json_new_object();
226         before = time(NULL);
227         json_add_timestamp(&object);
228         after = time(NULL);
229
230         ts = json_object_get(object.root, "timestamp");
231         assert_true(json_is_string(ts));
232
233         /*
234          * Convert the returned ISO 8601 timestamp into a time_t
235          * Note for convenience we ignore the value of the microsecond
236          * part of the time stamp.
237          */
238         t = json_string_value(ts);
239         rc = sscanf(
240                 t,
241                 "%4d-%2d-%2dT%2d:%2d:%2d.%6d%1c%4d",
242                 &tm.tm_year,
243                 &tm.tm_mon,
244                 &tm.tm_mday,
245                 &tm.tm_hour,
246                 &tm.tm_min,
247                 &tm.tm_sec,
248                 &usec,
249                 c,
250                 &tz);
251         assert_int_equal(9, rc);
252         tm.tm_year = tm.tm_year - 1900;
253         tm.tm_mon = tm.tm_mon - 1;
254         tm.tm_isdst = -1;
255         actual = mktime(&tm);
256
257         /*
258          * The timestamp should be before <= actual <= after
259          */
260         assert_true(difftime(actual, before) >= 0);
261         assert_true(difftime(after, actual) >= 0);
262
263         json_free(&object);
264 }
265
266 static void test_json_add_stringn(void **state)
267 {
268         struct json_object object;
269         struct json_t *value = NULL;
270         const char *s = NULL;
271
272         object = json_new_object();
273         json_add_stringn(&object, "null", NULL, 10);
274         json_add_stringn(&object, "null-zero-len", NULL, 0);
275         json_add_stringn(&object, "empty", "", 1);
276         json_add_stringn(&object, "empty-zero-len", "", 0);
277         json_add_stringn(&object, "value-less-than-len", "123456", 7);
278         json_add_stringn(&object, "value-greater-than-len", "abcd", 3);
279         json_add_stringn(&object, "value-equal-len", "ZYX", 3);
280         json_add_stringn(&object, "value-len-is-zero", "this will be null", 0);
281
282
283         assert_int_equal(8, json_object_size(object.root));
284
285         value = json_object_get(object.root, "null");
286         assert_true(json_is_null(value));
287
288         value = json_object_get(object.root, "null-zero-len");
289         assert_true(json_is_null(value));
290
291         value = json_object_get(object.root, "empty");
292         assert_true(json_is_string(value));
293         s = json_string_value(value);
294         assert_string_equal("", s);
295
296         value = json_object_get(object.root, "empty-zero-len");
297         assert_true(json_is_null(value));
298
299         value = json_object_get(object.root, "value-greater-than-len");
300         assert_true(json_is_string(value));
301         s = json_string_value(value);
302         assert_string_equal("abc", s);
303         assert_int_equal(3, strlen(s));
304
305         value = json_object_get(object.root, "value-equal-len");
306         assert_true(json_is_string(value));
307         s = json_string_value(value);
308         assert_string_equal("ZYX", s);
309         assert_int_equal(3, strlen(s));
310
311         value = json_object_get(object.root, "value-len-is-zero");
312         assert_true(json_is_null(value));
313
314         json_free(&object);
315 }
316
317 static void test_json_add_version(void **state)
318 {
319         struct json_object object;
320         struct json_t *version = NULL;
321         struct json_t *v = NULL;
322         double n;
323
324         object = json_new_object();
325         json_add_version(&object, 3, 1);
326
327         assert_int_equal(1, json_object_size(object.root));
328
329         version = json_object_get(object.root, "version");
330         assert_true(json_is_object(version));
331         assert_int_equal(2, json_object_size(version));
332
333         v = json_object_get(version, "major");
334         assert_true(json_is_integer(v));
335         n = json_number_value(v);
336         assert_true(n == 3.0);
337
338         v = json_object_get(version, "minor");
339         assert_true(json_is_integer(v));
340         n = json_number_value(v);
341         assert_true(n == 1.0);
342
343         json_free(&object);
344 }
345
346 static void test_json_add_address(void **state)
347 {
348         struct json_object object;
349         struct json_t *value = NULL;
350         struct tsocket_address *ip4  = NULL;
351         struct tsocket_address *ip6  = NULL;
352         struct tsocket_address *pipe = NULL;
353         const char *s = NULL;
354         int rc;
355
356         TALLOC_CTX *ctx = talloc_new(NULL);
357
358         object = json_new_object();
359
360         json_add_address(&object, "null", NULL);
361
362         rc = tsocket_address_inet_from_strings(
363                 ctx,
364                 "ip",
365                 "127.0.0.1",
366                 21,
367                 &ip4);
368         assert_int_equal(0, rc);
369         json_add_address(&object, "ip4", ip4);
370
371         rc = tsocket_address_inet_from_strings(
372                 ctx,
373                 "ip",
374                 "2001:db8:0:0:1:0:0:1",
375                 42,
376                 &ip6);
377         assert_int_equal(0, rc);
378         json_add_address(&object, "ip6", ip6);
379
380         rc = tsocket_address_unix_from_path(ctx, "/samba/pipe", &pipe);
381         assert_int_equal(0, rc);
382         json_add_address(&object, "pipe", pipe);
383
384         assert_int_equal(4, json_object_size(object.root));
385
386         value = json_object_get(object.root, "null");
387         assert_true(json_is_null(value));
388
389         value = json_object_get(object.root, "ip4");
390         assert_true(json_is_string(value));
391         s = json_string_value(value);
392         assert_string_equal("ipv4:127.0.0.1:21", s);
393
394         value = json_object_get(object.root, "ip6");
395         assert_true(json_is_string(value));
396         s = json_string_value(value);
397         assert_string_equal("ipv6:2001:db8::1:0:0:1:42", s);
398
399         value = json_object_get(object.root, "pipe");
400         assert_true(json_is_string(value));
401         s = json_string_value(value);
402         assert_string_equal("unix:/samba/pipe", s);
403
404         json_free(&object);
405         TALLOC_FREE(ctx);
406 }
407
408 static void test_json_add_sid(void **state)
409 {
410         struct json_object object;
411         struct json_t *value = NULL;
412         const char *SID = "S-1-5-21-2470180966-3899876309-2637894779";
413         struct dom_sid sid;
414         const char *s = NULL;
415
416
417         object = json_new_object();
418
419         json_add_sid(&object, "null", NULL);
420
421         assert_true(string_to_sid(&sid, SID));
422         json_add_sid(&object, "sid", &sid);
423
424         assert_int_equal(2, json_object_size(object.root));
425
426         value = json_object_get(object.root, "null");
427         assert_true(json_is_null(value));
428
429         value = json_object_get(object.root, "sid");
430         assert_true(json_is_string(value));
431         s = json_string_value(value);
432         assert_string_equal(SID, s);
433         json_free(&object);
434 }
435
436 static void test_json_add_guid(void **state)
437 {
438         struct json_object object;
439         struct json_t *value = NULL;
440         const char *GUID = "3ab88633-1e57-4c1a-856c-d1bc4b15bbb1";
441         struct GUID guid;
442         const char *s = NULL;
443         NTSTATUS status;
444
445
446         object = json_new_object();
447
448         json_add_guid(&object, "null", NULL);
449
450         status = GUID_from_string(GUID, &guid);
451         assert_true(NT_STATUS_IS_OK(status));
452         json_add_guid(&object, "guid", &guid);
453
454         assert_int_equal(2, json_object_size(object.root));
455
456         value = json_object_get(object.root, "null");
457         assert_true(json_is_null(value));
458
459         value = json_object_get(object.root, "guid");
460         assert_true(json_is_string(value));
461         s = json_string_value(value);
462         assert_string_equal(GUID, s);
463
464         json_free(&object);
465 }
466
467 static void test_json_to_string(void **state)
468 {
469         struct json_object object;
470         char *s = NULL;
471
472         TALLOC_CTX *ctx = talloc_new(NULL);
473
474         object = json_new_object();
475         object.error = true;
476
477         s = json_to_string(ctx, &object);
478         assert_null(s);
479
480         object.error = false;
481         s = json_to_string(ctx, &object);
482         assert_string_equal("{}", s);
483         TALLOC_FREE(s);
484
485         json_add_string(&object, "name", "value");
486         s = json_to_string(ctx, &object);
487         assert_string_equal("{\"name\": \"value\"}", s);
488         TALLOC_FREE(s);
489
490         json_free(&object);
491         TALLOC_FREE(ctx);
492 }
493 #endif
494
495 static void test_audit_get_timestamp(void **state)
496 {
497         const char *t = NULL;
498         char *c;
499         struct tm tm;
500         time_t before;
501         time_t after;
502         time_t actual;
503
504         TALLOC_CTX *ctx = talloc_new(NULL);
505
506         before = time(NULL);
507         t = audit_get_timestamp(ctx);
508         after = time(NULL);
509
510
511         c = strptime(t, "%a, %d %b %Y %H:%M:%S", &tm);
512         tm.tm_isdst = -1;
513         if (c != NULL && *c == '.') {
514                 char *e;
515                 strtod(c, &e);
516                 c = e;
517         }
518         if (c != NULL && *c == ' ') {
519                 struct tm tz;
520                 c = strptime(c, " %Z", &tz);
521         }
522         assert_int_equal(0, strlen(c));
523
524         actual = mktime(&tm);
525
526         /*
527          * The timestamp should be before <= actual <= after
528          */
529         assert_true(difftime(actual, before) >= 0);
530         assert_true(difftime(after, actual) >= 0);
531
532         TALLOC_FREE(ctx);
533 }
534
535 int main(int argc, const char **argv)
536 {
537         const struct CMUnitTest tests[] = {
538 #ifdef HAVE_JANSSON
539                 cmocka_unit_test(test_json_add_int),
540                 cmocka_unit_test(test_json_add_bool),
541                 cmocka_unit_test(test_json_add_string),
542                 cmocka_unit_test(test_json_add_object),
543                 cmocka_unit_test(test_json_add_to_array),
544                 cmocka_unit_test(test_json_add_timestamp),
545                 cmocka_unit_test(test_json_add_stringn),
546                 cmocka_unit_test(test_json_add_version),
547                 cmocka_unit_test(test_json_add_address),
548                 cmocka_unit_test(test_json_add_sid),
549                 cmocka_unit_test(test_json_add_guid),
550                 cmocka_unit_test(test_json_to_string),
551 #endif
552                 cmocka_unit_test(test_audit_get_timestamp),
553         };
554
555         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
556         return cmocka_run_group_tests(tests, NULL, NULL);
557 }