Line data Source code
1 : /*
2 : common routines for audit logging
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 : * Error handling:
22 : *
23 : */
24 :
25 : #include "includes.h"
26 :
27 : #include "librpc/ndr/libndr.h"
28 : #include "lib/tsocket/tsocket.h"
29 : #include "libcli/security/dom_sid.h"
30 : #include "libcli/security/security_token.h"
31 : #include "lib/messaging/messaging.h"
32 : #include "auth/common_auth.h"
33 : #include "audit_logging.h"
34 : #include "auth/authn_policy.h"
35 :
36 : /*
37 : * @brief Get a human readable timestamp.
38 : *
39 : * Returns the current time formatted as
40 : * "Tue, 14 Mar 2017 08:38:42.209028 NZDT"
41 : *
42 : * The returned string is allocated by talloc in the supplied context.
43 : * It is the callers responsibility to free it.
44 : *
45 : * @param mem_ctx talloc memory context that owns the returned string.
46 : *
47 : * @return a human readable time stamp, or NULL in the event of an error.
48 : *
49 : */
50 11 : char* audit_get_timestamp(TALLOC_CTX *frame)
51 : {
52 11 : char buffer[40]; /* formatted time less usec and timezone */
53 11 : char tz[10]; /* formatted time zone */
54 11 : struct tm* tm_info; /* current local time */
55 11 : struct timeval tv; /* current system time */
56 11 : int ret; /* response code */
57 11 : char * ts; /* formatted time stamp */
58 :
59 11 : ret = gettimeofday(&tv, NULL);
60 11 : if (ret != 0) {
61 0 : DBG_ERR("Unable to get time of day: (%d) %s\n",
62 : errno,
63 : strerror(errno));
64 0 : return NULL;
65 : }
66 :
67 11 : tm_info = localtime(&tv.tv_sec);
68 11 : if (tm_info == NULL) {
69 0 : DBG_ERR("Unable to determine local time\n");
70 0 : return NULL;
71 : }
72 :
73 11 : strftime(buffer, sizeof(buffer)-1, "%a, %d %b %Y %H:%M:%S", tm_info);
74 11 : strftime(tz, sizeof(tz)-1, "%Z", tm_info);
75 11 : ts = talloc_asprintf(frame, "%s.%06ld %s", buffer, (long)tv.tv_usec, tz);
76 11 : if (ts == NULL) {
77 0 : DBG_ERR("Out of memory formatting time stamp\n");
78 : }
79 0 : return ts;
80 : }
81 :
82 : /*
83 : * @brief write an audit message to the audit logs.
84 : *
85 : * Write a human readable text audit message to the samba logs.
86 : *
87 : * @param prefix Text to be printed at the start of the log line
88 : * @param message The content of the log line.
89 : * @param debub_class The debug class to log the message with.
90 : * @param debug_level The debug level to log the message with.
91 : */
92 0 : void audit_log_human_text(const char* prefix,
93 : const char* message,
94 : int debug_class,
95 : int debug_level)
96 : {
97 0 : DEBUGC(debug_class, debug_level, ("%s %s\n", prefix, message));
98 0 : }
99 :
100 : #ifdef HAVE_JANSSON
101 : /*
102 : * Constant for empty json object initialisation
103 : */
104 : const struct json_object json_empty_object = {.valid = false, .root = NULL};
105 : /*
106 : * @brief write a json object to the samba audit logs.
107 : *
108 : * Write the json object to the audit logs as a formatted string
109 : *
110 : * @param message The content of the log line.
111 : * @param debub_class The debug class to log the message with.
112 : * @param debug_level The debug level to log the message with.
113 : */
114 725344 : void audit_log_json(struct json_object* message,
115 : int debug_class,
116 : int debug_level)
117 : {
118 725344 : TALLOC_CTX *frame = NULL;
119 725344 : char *s = NULL;
120 :
121 725344 : if (json_is_invalid(message)) {
122 0 : DBG_ERR("Invalid JSON object, unable to log\n");
123 0 : return;
124 : }
125 :
126 725344 : frame = talloc_stackframe();
127 725344 : s = json_to_string(frame, message);
128 725344 : if (s == NULL) {
129 0 : DBG_ERR("json_to_string returned NULL, "
130 : "JSON audit message could not written\n");
131 0 : TALLOC_FREE(frame);
132 0 : return;
133 : }
134 : /*
135 : * This is very strange, but we call this routine to get a log
136 : * output without the header. JSON logs all have timestamps
137 : * so this only makes parsing harder.
138 : *
139 : * We push out the raw JSON blob without a prefix, consumers
140 : * can find such lines by the leading {
141 : */
142 725344 : DEBUGADDC(debug_class, debug_level, ("%s\n", s));
143 725344 : TALLOC_FREE(frame);
144 : }
145 :
146 : /*
147 : * @brief get a connection to the messaging event server.
148 : *
149 : * Get a connection to the messaging event server registered by server_name.
150 : *
151 : * @param msg_ctx a valid imessaging_context.
152 : * @param server_name name of messaging event server to connect to.
153 : * @param server_id The event server details to populate
154 : *
155 : * @return NTSTATUS
156 : */
157 725333 : static NTSTATUS get_event_server(
158 : struct imessaging_context *msg_ctx,
159 : const char *server_name,
160 : struct server_id *event_server)
161 : {
162 18210 : NTSTATUS status;
163 725333 : TALLOC_CTX *frame = talloc_stackframe();
164 18210 : unsigned num_servers, i;
165 18210 : struct server_id *servers;
166 :
167 725333 : status = irpc_servers_byname(
168 : msg_ctx,
169 : frame,
170 : server_name,
171 : &num_servers,
172 : &servers);
173 :
174 725333 : if (!NT_STATUS_IS_OK(status)) {
175 722826 : DBG_DEBUG("Failed to find the target '%s' on the message bus "
176 : "to send JSON audit events to: %s\n",
177 : server_name,
178 : nt_errstr(status));
179 722826 : TALLOC_FREE(frame);
180 722826 : return status;
181 : }
182 :
183 : /*
184 : * Select the first server that is listening, because we get
185 : * connection refused as NT_STATUS_OBJECT_NAME_NOT_FOUND
186 : * without waiting
187 : */
188 2507 : for (i = 0; i < num_servers; i++) {
189 2507 : status = imessaging_send(
190 : msg_ctx,
191 2507 : servers[i],
192 : MSG_PING,
193 : &data_blob_null);
194 2507 : if (NT_STATUS_IS_OK(status)) {
195 2507 : *event_server = servers[i];
196 2507 : TALLOC_FREE(frame);
197 2507 : return NT_STATUS_OK;
198 : }
199 : }
200 0 : DBG_NOTICE(
201 : "Failed to find '%s' registered on the message bus to "
202 : "send JSON audit events to: %s\n",
203 : server_name,
204 : nt_errstr(status));
205 0 : TALLOC_FREE(frame);
206 0 : return NT_STATUS_OBJECT_NAME_NOT_FOUND;
207 : }
208 :
209 : /*
210 : * @brief send an audit message to a messaging event server.
211 : *
212 : * Send the message to a registered and listening event server.
213 : * Note: Any errors are logged, and the message is not sent. This is to ensure
214 : * that a poorly behaved event server does not impact Samba.
215 : *
216 : * As it is possible to lose messages, especially during server
217 : * shut down, currently this function is primarily intended for use
218 : * in integration tests.
219 : *
220 : * @param msg_ctx an imessaging_context, can be NULL in which case no message
221 : * will be sent.
222 : * @param server_name the naname of the event server to send the message to.
223 : * @param messag_type A message type defined in librpc/idl/messaging.idl
224 : * @param message The message to send.
225 : *
226 : */
227 725333 : void audit_message_send(
228 : struct imessaging_context *msg_ctx,
229 : const char *server_name,
230 : uint32_t message_type,
231 : struct json_object *message)
232 : {
233 725333 : struct server_id event_server = {
234 : .pid = 0,
235 : };
236 18210 : NTSTATUS status;
237 :
238 725333 : const char *message_string = NULL;
239 725333 : DATA_BLOB message_blob = data_blob_null;
240 725333 : TALLOC_CTX *ctx = NULL;
241 :
242 725333 : if (json_is_invalid(message)) {
243 0 : DBG_ERR("Invalid JSON object, unable to send\n");
244 722826 : return;
245 : }
246 725333 : if (msg_ctx == NULL) {
247 0 : DBG_DEBUG("No messaging context\n");
248 0 : return;
249 : }
250 :
251 725333 : ctx = talloc_new(NULL);
252 725333 : if (ctx == NULL) {
253 0 : DBG_ERR("Out of memory creating temporary context\n");
254 0 : return;
255 : }
256 :
257 : /* Need to refetch the address each time as the destination server may
258 : * have disconnected and reconnected in the interim, in which case
259 : * messages may get lost
260 : */
261 725333 : status = get_event_server(msg_ctx, server_name, &event_server);
262 725333 : if (!NT_STATUS_IS_OK(status)) {
263 722826 : TALLOC_FREE(ctx);
264 722826 : return;
265 : }
266 :
267 2507 : message_string = json_to_string(ctx, message);
268 2507 : message_blob = data_blob_string_const(message_string);
269 2507 : status = imessaging_send(
270 : msg_ctx,
271 : event_server,
272 : message_type,
273 : &message_blob);
274 :
275 : /*
276 : * If the server crashed, try to find it again
277 : */
278 2507 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
279 0 : status = get_event_server(msg_ctx, server_name, &event_server);
280 0 : if (!NT_STATUS_IS_OK(status)) {
281 0 : TALLOC_FREE(ctx);
282 0 : return;
283 : }
284 0 : imessaging_send(
285 : msg_ctx,
286 : event_server,
287 : message_type,
288 : &message_blob);
289 : }
290 2507 : TALLOC_FREE(ctx);
291 : }
292 :
293 : /*
294 : * @brief Create a new struct json_object, wrapping a JSON Object.
295 : *
296 : * Create a new json object, the json_object wraps the underlying json
297 : * implementations JSON Object representation.
298 : *
299 : * Free with a call to json_free_object, note that the jansson implementation
300 : * allocates memory with malloc and not talloc.
301 : *
302 : * @return a struct json_object, valid will be set to false if the object
303 : * could not be created.
304 : *
305 : */
306 8363911 : struct json_object json_new_object(void) {
307 :
308 8363911 : struct json_object object = json_empty_object;
309 :
310 8363911 : object.root = json_object();
311 8363911 : if (object.root == NULL) {
312 1 : object.valid = false;
313 1 : DBG_ERR("Unable to create JSON object\n");
314 1 : return object;
315 : }
316 8363910 : object.valid = true;
317 8363910 : return object;
318 : }
319 :
320 : /*
321 : * @brief Create a new struct json_object wrapping a JSON Array.
322 : *
323 : * Create a new json object, the json_object wraps the underlying json
324 : * implementations JSON Array representation.
325 : *
326 : * Free with a call to json_free_object, note that the jansson implementation
327 : * allocates memory with malloc and not talloc.
328 : *
329 : * @return a struct json_object, error will be set to true if the array
330 : * could not be created.
331 : *
332 : */
333 3474982 : struct json_object json_new_array(void) {
334 :
335 3474982 : struct json_object array = json_empty_object;
336 :
337 3474982 : array.root = json_array();
338 3474982 : if (array.root == NULL) {
339 1 : array.valid = false;
340 1 : DBG_ERR("Unable to create JSON array\n");
341 1 : return array;
342 : }
343 3474981 : array.valid = true;
344 3474981 : return array;
345 : }
346 :
347 :
348 : /*
349 : * @brief free and invalidate a previously created JSON object.
350 : *
351 : * Release any resources owned by a json_object, and then mark the structure
352 : * as invalid. It is safe to call this multiple times on an object.
353 : *
354 : */
355 725502 : void json_free(struct json_object *object)
356 : {
357 725502 : if (object->root != NULL) {
358 725475 : json_decref(object->root);
359 : }
360 725502 : object->root = NULL;
361 725502 : object->valid = false;
362 725502 : }
363 :
364 : /*
365 : * @brief is the current JSON object invalid?
366 : *
367 : * Check the state of the object to determine if it is invalid.
368 : *
369 : * @return is the object valid?
370 : *
371 : */
372 66965820 : bool json_is_invalid(const struct json_object *object)
373 : {
374 66965820 : return !object->valid;
375 : }
376 :
377 : /*
378 : * @brief Add an integer value to a JSON object.
379 : *
380 : * Add an integer value named 'name' to the json object.
381 : *
382 : * @param object the JSON object to be updated.
383 : * @param name the name of the value.
384 : * @param value the value.
385 : *
386 : * @return 0 the operation was successful
387 : * -1 the operation failed
388 : *
389 : */
390 2284114 : int json_add_int(struct json_object *object, const char *name, const json_int_t value)
391 : {
392 2284114 : int ret = 0;
393 2284114 : json_t *integer = NULL;
394 :
395 2284114 : if (json_is_invalid(object)) {
396 2 : DBG_ERR("Unable to add int [%s] value [%jd], "
397 : "target object is invalid\n",
398 : name,
399 : (intmax_t)value);
400 2 : return JSON_ERROR;
401 : }
402 :
403 2284112 : integer = json_integer(value);
404 2284112 : if (integer == NULL) {
405 1 : DBG_ERR("Unable to create integer value [%s] value [%jd]\n",
406 : name,
407 : (intmax_t)value);
408 1 : return JSON_ERROR;
409 : }
410 :
411 2284111 : ret = json_object_set_new(object->root, name, integer);
412 2284111 : if (ret != 0) {
413 4 : json_decref(integer);
414 4 : DBG_ERR("Unable to add int [%s] value [%jd]\n",
415 : name,
416 : (intmax_t)value);
417 : }
418 2224245 : return ret;
419 : }
420 :
421 : /*
422 : * @brief Add a boolean value to a JSON object.
423 : *
424 : * Add a boolean value named 'name' to the json object.
425 : *
426 : * @param object the JSON object to be updated.
427 : * @param name the name.
428 : * @param value the value.
429 : *
430 : * @return 0 the operation was successful
431 : * -1 the operation failed
432 : *
433 : */
434 739568 : int json_add_bool(struct json_object *object,
435 : const char *name,
436 : const bool value)
437 : {
438 739568 : int ret = 0;
439 :
440 739568 : if (json_is_invalid(object)) {
441 2 : DBG_ERR("Unable to add boolean [%s] value [%d], "
442 : "target object is invalid\n",
443 : name,
444 : value);
445 2 : return JSON_ERROR;
446 : }
447 :
448 739566 : ret = json_object_set_new(object->root, name, json_boolean(value));
449 739566 : if (ret != 0) {
450 1 : DBG_ERR("Unable to add boolean [%s] value [%d]\n", name, value);
451 : }
452 711230 : return ret;
453 : }
454 :
455 : /*
456 : * @brief Add an optional boolean value to a JSON object.
457 : *
458 : * Add an optional boolean value named 'name' to the json object.
459 : *
460 : * @param object the JSON object to be updated.
461 : * @param name the name.
462 : * @param value the value.
463 : *
464 : * @return 0 the operation was successful
465 : * -1 the operation failed
466 : *
467 : */
468 768 : int json_add_optional_bool(struct json_object *object,
469 : const char *name,
470 : const bool *value)
471 : {
472 768 : int ret = 0;
473 :
474 768 : if (json_is_invalid(object)) {
475 0 : DBG_ERR("Unable to add boolean [%s] value [%d], "
476 : "target object is invalid\n",
477 : name,
478 : *value);
479 0 : return JSON_ERROR;
480 : }
481 :
482 768 : if (value != NULL) {
483 768 : ret = json_object_set_new(object->root, name, json_boolean(*value));
484 768 : if (ret != 0) {
485 0 : DBG_ERR("Unable to add boolean [%s] value [%d]\n", name, *value);
486 0 : return ret;
487 : }
488 : } else {
489 0 : ret = json_object_set_new(object->root, name, json_null());
490 0 : if (ret != 0) {
491 0 : DBG_ERR("Unable to add null boolean [%s]\n", name);
492 0 : return ret;
493 : }
494 : }
495 :
496 768 : return ret;
497 : }
498 :
499 : /*
500 : * @brief Add a string value to a JSON object.
501 : *
502 : * Add a string value named 'name' to the json object.
503 : *
504 : * @param object the JSON object to be updated.
505 : * @param name the name.
506 : * @param value the value.
507 : *
508 : * @return 0 the operation was successful
509 : * -1 the operation failed
510 : *
511 : */
512 8443495 : int json_add_string(struct json_object *object,
513 : const char *name,
514 : const char *value)
515 : {
516 8443495 : int ret = 0;
517 :
518 8443495 : if (json_is_invalid(object)) {
519 2 : DBG_ERR("Unable to add string [%s], target object is invalid\n",
520 : name);
521 2 : return JSON_ERROR;
522 : }
523 8443493 : if (value) {
524 8305881 : json_t *string = json_string(value);
525 8305881 : if (string == NULL) {
526 2 : DBG_ERR("Unable to add string [%s], "
527 : "could not create string object\n",
528 : name);
529 2 : return JSON_ERROR;
530 : }
531 8305879 : ret = json_object_set_new(object->root, name, string);
532 8305879 : if (ret != 0) {
533 5 : json_decref(string);
534 5 : DBG_ERR("Unable to add string [%s]\n", name);
535 5 : return ret;
536 : }
537 : } else {
538 137612 : ret = json_object_set_new(object->root, name, json_null());
539 137612 : if (ret != 0) {
540 1 : DBG_ERR("Unable to add null string [%s]\n", name);
541 1 : return ret;
542 : }
543 : }
544 8154791 : return ret;
545 : }
546 :
547 : /*
548 : * @brief Assert that the current JSON object is an array.
549 : *
550 : * Check that the current object is a JSON array, and if not
551 : * invalidate the object. We also log an error message as this indicates
552 : * bug in the calling code.
553 : *
554 : * @param object the JSON object to be validated.
555 : */
556 2394282 : void json_assert_is_array(struct json_object *array) {
557 :
558 2394282 : if (json_is_invalid(array)) {
559 0 : return;
560 : }
561 :
562 2394282 : if (json_is_array(array->root) == false) {
563 1 : DBG_ERR("JSON object is not an array\n");
564 1 : array->valid = false;
565 1 : return;
566 : }
567 : }
568 :
569 : /*
570 : * @brief Add a JSON object to a JSON object.
571 : *
572 : * Add a JSON object named 'name' to the json object.
573 : *
574 : * @param object the JSON object to be updated.
575 : * @param name the name.
576 : * @param value the value.
577 : *
578 : * @return 0 the operation was successful
579 : * -1 the operation failed
580 : *
581 : */
582 11351020 : int json_add_object(struct json_object *object,
583 : const char *name,
584 : struct json_object *value)
585 : {
586 11351020 : int ret = 0;
587 11351020 : json_t *jv = NULL;
588 :
589 11351020 : if (value != NULL && json_is_invalid(value)) {
590 2 : DBG_ERR("Invalid JSON object [%s] supplied\n", name);
591 2 : return JSON_ERROR;
592 : }
593 11351018 : if (json_is_invalid(object)) {
594 4 : DBG_ERR("Unable to add object [%s], target object is invalid\n",
595 : name);
596 4 : return JSON_ERROR;
597 : }
598 :
599 11351014 : jv = value == NULL ? json_null() : value->root;
600 :
601 11351014 : if (json_is_array(object->root)) {
602 4139475 : ret = json_array_append_new(object->root, jv);
603 7211539 : } else if (json_is_object(object->root)) {
604 7211539 : ret = json_object_set_new(object->root, name, jv);
605 : } else {
606 0 : DBG_ERR("Invalid JSON object type\n");
607 0 : ret = JSON_ERROR;
608 : }
609 11351014 : if (ret != 0) {
610 4 : DBG_ERR("Unable to add object [%s]\n", name);
611 : }
612 10845865 : return ret;
613 : }
614 :
615 : /*
616 : * @brief Add a string to a JSON object, truncating if necessary.
617 : *
618 : *
619 : * Add a string value named 'name' to the json object, the string will be
620 : * truncated if it is more than len characters long. If len is 0 the value
621 : * is encoded as a JSON null.
622 : *
623 : *
624 : * @param object the JSON object to be updated.
625 : * @param name the name.
626 : * @param value the value.
627 : * @param len the maximum number of characters to be copied.
628 : *
629 : * @return 0 the operation was successful
630 : * -1 the operation failed
631 : *
632 : */
633 2028322 : int json_add_stringn(struct json_object *object,
634 : const char *name,
635 : const char *value,
636 : const size_t len)
637 : {
638 :
639 2028322 : int ret = 0;
640 2028322 : if (json_is_invalid(object)) {
641 2 : DBG_ERR("Unable to add string [%s], target object is invalid\n",
642 : name);
643 2 : return JSON_ERROR;
644 : }
645 :
646 3957073 : if (value != NULL && len > 0) {
647 2028314 : json_t *string = json_stringn(value, len);
648 2028314 : if (string == NULL) {
649 1 : DBG_ERR("Unable to add string [%s], "
650 : "could not create string object\n",
651 : name);
652 1 : return JSON_ERROR;
653 : }
654 2028313 : ret = json_object_set_new(object->root, name, string);
655 2028313 : if (ret != 0) {
656 1 : json_decref(string);
657 1 : DBG_ERR("Unable to add string [%s]\n", name);
658 1 : return ret;
659 : }
660 : } else {
661 6 : ret = json_object_set_new(object->root, name, json_null());
662 6 : if (ret != 0) {
663 2 : DBG_ERR("Unable to add null string [%s]\n", name);
664 2 : return ret;
665 : }
666 : }
667 1928753 : return ret;
668 : }
669 :
670 : /*
671 : * @brief Add a version object to a JSON object
672 : *
673 : * Add a version object to the JSON object
674 : * "version":{"major":1, "minor":0}
675 : *
676 : * The version tag is intended to aid the processing of the JSON messages
677 : * The major version number should change when an attribute is:
678 : * - renamed
679 : * - removed
680 : * - its meaning changes
681 : * - its contents change format
682 : * The minor version should change whenever a new attribute is added and for
683 : * minor bug fixes to an attributes content.
684 : *
685 : *
686 : * @param object the JSON object to be updated.
687 : * @param major the major version number
688 : * @param minor the minor version number
689 : *
690 : * @return 0 the operation was successful
691 : * -1 the operation failed
692 : */
693 725381 : int json_add_version(struct json_object *object, int major, int minor)
694 : {
695 725381 : int ret = 0;
696 18258 : struct json_object version;
697 :
698 725381 : if (json_is_invalid(object)) {
699 2 : DBG_ERR("Unable to add version, target object is invalid\n");
700 2 : return JSON_ERROR;
701 : }
702 :
703 725379 : version = json_new_object();
704 725379 : if (json_is_invalid(&version)) {
705 1 : DBG_ERR("Unable to add version, failed to create object\n");
706 1 : return JSON_ERROR;
707 : }
708 725378 : ret = json_add_int(&version, "major", major);
709 725378 : if (ret != 0) {
710 1 : json_free(&version);
711 1 : return ret;
712 : }
713 725377 : ret = json_add_int(&version, "minor", minor);
714 725377 : if (ret != 0) {
715 2 : json_free(&version);
716 2 : return ret;
717 : }
718 725375 : ret = json_add_object(object, "version", &version);
719 725375 : if (ret != 0) {
720 0 : json_free(&version);
721 0 : return ret;
722 : }
723 707123 : return ret;
724 : }
725 :
726 : /*
727 : * @brief add an ISO 8601 timestamp to the object.
728 : *
729 : * Add a date and time as a timestamp in ISO 8601 format to a JSON object
730 : *
731 : * "time":"2017-03-06T17:18:04.455081+1300"
732 : *
733 : *
734 : * @param object the JSON object to be updated.
735 : * @param name the name.
736 : * @param time the value to set.
737 : *
738 : * @return 0 the operation was successful
739 : * -1 the operation failed
740 : */
741 758405 : int json_add_time(struct json_object *object, const char *name, const struct timeval tv)
742 : {
743 19901 : char buffer[40]; /* formatted time less usec and timezone */
744 19901 : char timestamp[65]; /* the formatted ISO 8601 time stamp */
745 19901 : char tz[10]; /* formatted time zone */
746 19901 : struct tm* tm_info; /* current local time */
747 19901 : int ret; /* return code from json operations */
748 :
749 758405 : if (json_is_invalid(object)) {
750 0 : DBG_ERR("Unable to add time, target object is invalid\n");
751 0 : return JSON_ERROR;
752 : }
753 :
754 758405 : tm_info = localtime(&tv.tv_sec);
755 758405 : if (tm_info == NULL) {
756 1 : DBG_ERR("Unable to determine local time\n");
757 1 : return JSON_ERROR;
758 : }
759 :
760 758404 : strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info);
761 758404 : strftime(tz, sizeof(tz)-1, "%z", tm_info);
762 758404 : snprintf(
763 : timestamp,
764 : sizeof(timestamp),
765 : "%s.%06ld%s",
766 : buffer,
767 758404 : tv.tv_usec,
768 : tz);
769 758404 : ret = json_add_string(object, name, timestamp);
770 758404 : if (ret != 0) {
771 2 : DBG_ERR("Unable to add time to JSON object\n");
772 : }
773 738504 : return ret;
774 : }
775 :
776 : /*
777 : * @brief add an ISO 8601 timestamp to the object.
778 : *
779 : * Add the current date and time as a timestamp in ISO 8601 format
780 : * to a JSON object
781 : *
782 : * "timestamp":"2017-03-06T17:18:04.455081+1300"
783 : *
784 : *
785 : * @param object the JSON object to be updated.
786 : *
787 : * @return 0 the operation was successful
788 : * -1 the operation failed
789 : */
790 725387 : int json_add_timestamp(struct json_object *object)
791 : {
792 18246 : struct timeval tv; /* current system time */
793 18246 : int r; /* response code from gettimeofday */
794 :
795 725387 : if (json_is_invalid(object)) {
796 2 : DBG_ERR("Unable to add time stamp, target object is invalid\n");
797 2 : return JSON_ERROR;
798 : }
799 :
800 725385 : r = gettimeofday(&tv, NULL);
801 725385 : if (r) {
802 1 : DBG_ERR("Unable to get time of day: (%d) %s\n",
803 : errno,
804 : strerror(errno));
805 1 : return JSON_ERROR;
806 : }
807 :
808 725384 : return json_add_time(object, "timestamp", tv);
809 : }
810 :
811 : /*
812 : *@brief Add a tsocket_address to a JSON object
813 : *
814 : * Add the string representation of a Samba tsocket_address to the object.
815 : *
816 : * "localAddress":"ipv6::::0"
817 : *
818 : *
819 : * @param object the JSON object to be updated.
820 : * @param name the name.
821 : * @param address the tsocket_address.
822 : *
823 : * @return 0 the operation was successful
824 : * -1 the operation failed
825 : *
826 : */
827 691896 : int json_add_address(struct json_object *object,
828 : const char *name,
829 : const struct tsocket_address *address)
830 : {
831 691896 : int ret = 0;
832 :
833 691896 : if (json_is_invalid(object)) {
834 2 : DBG_ERR("Unable to add address [%s], "
835 : "target object is invalid\n",
836 : name);
837 2 : return JSON_ERROR;
838 : }
839 :
840 691894 : if (address == NULL) {
841 277108 : ret = json_object_set_new(object->root, name, json_null());
842 277108 : if (ret != 0) {
843 1 : DBG_ERR("Unable to add null address [%s]\n", name);
844 1 : return JSON_ERROR;
845 : }
846 : } else {
847 414786 : TALLOC_CTX *ctx = talloc_new(NULL);
848 414786 : char *s = NULL;
849 :
850 414786 : if (ctx == NULL) {
851 1 : DBG_ERR("Out of memory adding address [%s]\n", name);
852 1 : return JSON_ERROR;
853 : }
854 :
855 414785 : s = tsocket_address_string(address, ctx);
856 414785 : if (s == NULL) {
857 1 : DBG_ERR("Out of memory adding address [%s]\n", name);
858 1 : TALLOC_FREE(ctx);
859 1 : return JSON_ERROR;
860 : }
861 414784 : ret = json_add_string(object, name, s);
862 414784 : if (ret != 0) {
863 1 : DBG_ERR(
864 : "Unable to add address [%s] value [%s]\n", name, s);
865 1 : TALLOC_FREE(ctx);
866 1 : return JSON_ERROR;
867 : }
868 414783 : TALLOC_FREE(ctx);
869 : }
870 669206 : return ret;
871 : }
872 :
873 : /*
874 : * @brief Add a formatted string representation of a sid to a json object.
875 : *
876 : * Add the string representation of a Samba sid to the object.
877 : *
878 : * "sid":"S-1-5-18"
879 : *
880 : *
881 : * @param object the JSON object to be updated.
882 : * @param name the name.
883 : * @param sid the sid
884 : *
885 : * @return 0 the operation was successful
886 : * -1 the operation failed
887 : *
888 : */
889 606258 : int json_add_sid(struct json_object *object,
890 : const char *name,
891 : const struct dom_sid *sid)
892 : {
893 606258 : int ret = 0;
894 :
895 606258 : if (json_is_invalid(object)) {
896 2 : DBG_ERR("Unable to add SID [%s], "
897 : "target object is invalid\n",
898 : name);
899 2 : return JSON_ERROR;
900 : }
901 :
902 606256 : if (sid == NULL) {
903 40618 : ret = json_object_set_new(object->root, name, json_null());
904 40618 : if (ret != 0) {
905 1 : DBG_ERR("Unable to add null SID [%s]\n", name);
906 1 : return ret;
907 : }
908 : } else {
909 17785 : struct dom_sid_buf sid_buf;
910 :
911 565638 : ret = json_add_string(
912 565638 : object, name, dom_sid_str_buf(sid, &sid_buf));
913 565638 : if (ret != 0) {
914 1 : DBG_ERR("Unable to add SID [%s] value [%s]\n",
915 : name,
916 : sid_buf.buf);
917 1 : return ret;
918 : }
919 : }
920 587014 : return ret;
921 : }
922 :
923 : /*
924 : * @brief Add a formatted string representation of a guid to a json object.
925 : *
926 : * Add the string representation of a Samba GUID to the object.
927 : *
928 : * "guid":"1fb9f2ee-2a4d-4bf8-af8b-cb9d4529a9ab"
929 : *
930 : *
931 : * @param object the JSON object to be updated.
932 : * @param name the name.
933 : * @param guid the guid.
934 : *
935 : * @return 0 the operation was successful
936 : * -1 the operation failed
937 : *
938 : *
939 : */
940 1060847 : int json_add_guid(struct json_object *object,
941 : const char *name,
942 : const struct GUID *guid)
943 : {
944 :
945 1060847 : int ret = 0;
946 :
947 1060847 : if (json_is_invalid(object)) {
948 2 : DBG_ERR("Unable to add GUID [%s], "
949 : "target object is invalid\n",
950 : name);
951 2 : return JSON_ERROR;
952 : }
953 :
954 1060845 : if (guid == NULL) {
955 4530 : ret = json_object_set_new(object->root, name, json_null());
956 4530 : if (ret != 0) {
957 1 : DBG_ERR("Unable to add null GUID [%s]\n", name);
958 1 : return ret;
959 : }
960 : } else {
961 23959 : char *guid_str;
962 23959 : struct GUID_txt_buf guid_buff;
963 :
964 1056315 : guid_str = GUID_buf_string(guid, &guid_buff);
965 1056315 : ret = json_add_string(object, name, guid_str);
966 1056315 : if (ret != 0) {
967 1 : DBG_ERR("Unable to add GUID [%s] value [%s]\n",
968 : name,
969 : guid_str);
970 1 : return ret;
971 : }
972 : }
973 1036878 : return ret;
974 : }
975 :
976 : /*
977 : * @brief Add a hex-formatted string representation of a 32-bit integer to a
978 : * json object.
979 : *
980 : * Add a hex-formatted string representation of a 32-bit flags integer to the
981 : * object.
982 : *
983 : * "accountFlags":"0x12345678"
984 : *
985 : *
986 : * @param object the JSON object to be updated.
987 : * @param name the name.
988 : * @param flags the flags.
989 : *
990 : * @return 0 the operation was successful
991 : * -1 the operation failed
992 : *
993 : *
994 : */
995 104215 : int json_add_flags32(struct json_object *object,
996 : const char *name,
997 : const uint32_t flags)
998 : {
999 104215 : int ret = 0;
1000 4596 : char buf[sizeof("0x12345678")];
1001 :
1002 104215 : if (json_is_invalid(object)) {
1003 0 : DBG_ERR("Unable to add flags [%s], "
1004 : "target object is invalid\n",
1005 : name);
1006 0 : return JSON_ERROR;
1007 : }
1008 :
1009 104215 : ret = snprintf(buf, sizeof (buf), "0x%08X", flags);
1010 104215 : if (ret != sizeof (buf) - 1) {
1011 0 : DBG_ERR("Unable to format flags [%s] value [0x%08X]\n",
1012 : name,
1013 : flags);
1014 0 : return JSON_ERROR;
1015 : }
1016 :
1017 104215 : ret = json_add_string(object, name, buf);
1018 104215 : if (ret != 0) {
1019 0 : DBG_ERR("Unable to add flags [%s] value [%s]\n",
1020 : name,
1021 : buf);
1022 : }
1023 :
1024 99619 : return ret;
1025 : }
1026 :
1027 : /*
1028 : * @brief Replaces the object for a given key with a given json object.
1029 : *
1030 : * If key already exists, the value will be replaced. Otherwise the given
1031 : * value will be added under the given key.
1032 : *
1033 : * @param object the JSON object to be updated.
1034 : * @param key the key which will be updated.
1035 : * @param new_obj the new value object to be inserted.
1036 : *
1037 : * @return 0 the operation was successful
1038 : * -1 the operation failed (e.j. if one of the parameters is invalid)
1039 : */
1040 1776 : int json_update_object(struct json_object *object,
1041 : const char *key,
1042 : struct json_object *new_obj)
1043 : {
1044 1776 : int ret = 0;
1045 :
1046 1776 : if (json_is_invalid(object)) {
1047 0 : DBG_ERR("Unable to update key [%s], "
1048 : "target object is invalid\n",
1049 : key);
1050 0 : return JSON_ERROR;
1051 : }
1052 1776 : if (json_is_invalid(new_obj)) {
1053 0 : DBG_ERR("Unable to update key [%s], "
1054 : "new object is invalid\n",
1055 : key);
1056 0 : return JSON_ERROR;
1057 : }
1058 :
1059 1776 : if (key == NULL) {
1060 0 : DBG_ERR("Unable to add null String as key\n");
1061 0 : return JSON_ERROR;
1062 : }
1063 :
1064 1776 : ret = json_object_set(object->root, key, new_obj->root);
1065 1776 : if (ret != 0) {
1066 0 : DBG_ERR("Unable to update object\n");
1067 0 : return ret;
1068 : }
1069 :
1070 1776 : return ret;
1071 : }
1072 :
1073 : /*
1074 : * @brief Convert a JSON object into a string
1075 : *
1076 : * Convert the json object into a string suitable for printing on a log line,
1077 : * i.e. with no embedded line breaks.
1078 : *
1079 : * If the object is invalid it logs an error and returns NULL.
1080 : *
1081 : * @param mem_ctx the talloc memory context owning the returned string
1082 : * @param object the json object.
1083 : *
1084 : * @return A string representation of the object or NULL if the object
1085 : * is invalid.
1086 : */
1087 727867 : char *json_to_string(TALLOC_CTX *mem_ctx, const struct json_object *object)
1088 : {
1089 727867 : char *json = NULL;
1090 727867 : char *json_string = NULL;
1091 :
1092 727867 : if (json_is_invalid(object)) {
1093 1 : DBG_ERR("Invalid JSON object, unable to convert to string\n");
1094 1 : return NULL;
1095 : }
1096 :
1097 727866 : if (object->root == NULL) {
1098 0 : return NULL;
1099 : }
1100 :
1101 : /*
1102 : * json_dumps uses malloc, so need to call free(json) to release
1103 : * the memory
1104 : */
1105 727865 : json = json_dumps(object->root, 0);
1106 727865 : if (json == NULL) {
1107 1 : DBG_ERR("Unable to convert JSON object to string\n");
1108 1 : return NULL;
1109 : }
1110 :
1111 727864 : json_string = talloc_strdup(mem_ctx, json);
1112 727864 : if (json_string == NULL) {
1113 1 : free(json);
1114 1 : DBG_ERR("Unable to copy JSON object string to talloc string\n");
1115 1 : return NULL;
1116 : }
1117 727863 : free(json);
1118 :
1119 727863 : return json_string;
1120 : }
1121 :
1122 : /*
1123 : * @brief get a json array named "name" from the json object.
1124 : *
1125 : * Get the array attribute named name, creating it if it does not exist.
1126 : *
1127 : * @param object the json object.
1128 : * @param name the name of the array attribute
1129 : *
1130 : * @return The array object, will be created if it did not exist.
1131 : */
1132 1745193 : struct json_object json_get_array(struct json_object *object, const char *name)
1133 : {
1134 :
1135 1745193 : struct json_object array = json_empty_object;
1136 1745193 : json_t *a = NULL;
1137 1745193 : int ret = 0;
1138 :
1139 1745193 : if (json_is_invalid(object)) {
1140 1 : DBG_ERR("Invalid JSON object, unable to get array [%s]\n",
1141 : name);
1142 1 : json_free(&array);
1143 1 : return array;
1144 : }
1145 :
1146 1745192 : array = json_new_array();
1147 1745192 : if (json_is_invalid(&array)) {
1148 1 : DBG_ERR("Unable to create new array for [%s]\n", name);
1149 1 : return array;
1150 : }
1151 :
1152 1745191 : a = json_object_get(object->root, name);
1153 1745191 : if (a == NULL) {
1154 1684881 : return array;
1155 : }
1156 :
1157 60310 : ret = json_array_extend(array.root, a);
1158 60310 : if (ret != 0) {
1159 1 : DBG_ERR("Unable to get array [%s]\n", name);
1160 1 : json_free(&array);
1161 1 : return array;
1162 : }
1163 :
1164 60309 : return array;
1165 : }
1166 :
1167 : /*
1168 : * @brief get a json object named "name" from the json object.
1169 : *
1170 : * Get the object attribute named name, creating it if it does not exist.
1171 : *
1172 : * @param object the json object.
1173 : * @param name the name of the object attribute
1174 : *
1175 : * @return The object, will be created if it did not exist.
1176 : */
1177 1746967 : struct json_object json_get_object(struct json_object *object, const char *name)
1178 : {
1179 :
1180 1746967 : struct json_object o = json_new_object();
1181 1746967 : json_t *v = NULL;
1182 1746967 : int ret = 0;
1183 :
1184 1746967 : if (json_is_invalid(&o)) {
1185 0 : DBG_ERR("Unable to get object [%s]\n", name);
1186 0 : json_free(&o);
1187 0 : return o;
1188 : }
1189 :
1190 1746967 : if (json_is_invalid(object)) {
1191 1 : DBG_ERR("Invalid JSON object, unable to get object [%s]\n",
1192 : name);
1193 1 : json_free(&o);
1194 1 : return o;
1195 : }
1196 :
1197 1746966 : v = json_object_get(object->root, name);
1198 1746966 : if (v == NULL) {
1199 1685279 : return o;
1200 : }
1201 61687 : ret = json_object_update(o.root, v);
1202 61687 : if (ret != 0) {
1203 1 : DBG_ERR("Unable to get object [%s]\n", name);
1204 1 : json_free(&o);
1205 1 : return o;
1206 : }
1207 61686 : return o;
1208 : }
1209 :
1210 : /*
1211 : * @brief Return the JSON null object.
1212 : *
1213 : * @return the JSON null object.
1214 : */
1215 240121 : _WARN_UNUSED_RESULT_ struct json_object json_null_object(void)
1216 : {
1217 240121 : struct json_object object = json_empty_object;
1218 :
1219 240121 : object.root = json_null();
1220 240121 : if (object.root != NULL) {
1221 240121 : object.valid = true;
1222 : }
1223 :
1224 240121 : return object;
1225 : }
1226 :
1227 : /*
1228 : * @brief Create a JSON object from a structure containing audit information.
1229 : *
1230 : * @param audit_info the audit information from which to create a JSON object.
1231 : *
1232 : * @return the JSON object (which may be valid or not)
1233 : *
1234 : *
1235 : */
1236 768 : struct json_object json_from_audit_info(const struct authn_audit_info *audit_info)
1237 : {
1238 768 : struct json_object object = json_new_object();
1239 0 : enum auth_event_id_type auth_event_id;
1240 768 : const struct auth_user_info_dc *client_info = NULL;
1241 768 : const char *policy_name = NULL;
1242 768 : const char *silo_name = NULL;
1243 768 : const bool *policy_enforced = NULL;
1244 0 : NTSTATUS policy_status;
1245 0 : struct authn_int64_optional tgt_lifetime_mins;
1246 768 : const char *location = NULL;
1247 768 : const char *audit_event = NULL;
1248 768 : const char *audit_reason = NULL;
1249 768 : int rc = 0;
1250 :
1251 768 : if (json_is_invalid(&object)) {
1252 0 : goto failure;
1253 : }
1254 :
1255 768 : auth_event_id = authn_audit_info_event_id(audit_info);
1256 768 : rc = json_add_int(&object, "eventId", auth_event_id);
1257 768 : if (rc != 0) {
1258 0 : goto failure;
1259 : }
1260 :
1261 768 : policy_name = authn_audit_info_policy_name(audit_info);
1262 768 : rc = json_add_string(&object, "policyName", policy_name);
1263 768 : if (rc != 0) {
1264 0 : goto failure;
1265 : }
1266 :
1267 768 : silo_name = authn_audit_info_silo_name(audit_info);
1268 768 : rc = json_add_string(&object, "siloName", silo_name);
1269 768 : if (rc != 0) {
1270 0 : goto failure;
1271 : }
1272 :
1273 768 : policy_enforced = authn_audit_info_policy_enforced(audit_info);
1274 768 : rc = json_add_optional_bool(&object, "policyEnforced", policy_enforced);
1275 768 : if (rc != 0) {
1276 0 : goto failure;
1277 : }
1278 :
1279 768 : policy_status = authn_audit_info_policy_status(audit_info);
1280 768 : rc = json_add_string(&object, "status", nt_errstr(policy_status));
1281 768 : if (rc != 0) {
1282 0 : goto failure;
1283 : }
1284 :
1285 768 : tgt_lifetime_mins = authn_audit_info_policy_tgt_lifetime_mins(audit_info);
1286 768 : if (tgt_lifetime_mins.is_present) {
1287 394 : rc = json_add_int(&object, "tgtLifetime", tgt_lifetime_mins.val);
1288 394 : if (rc != 0) {
1289 0 : goto failure;
1290 : }
1291 : }
1292 :
1293 768 : location = authn_audit_info_location(audit_info);
1294 768 : rc = json_add_string(&object, "location", location);
1295 768 : if (rc != 0) {
1296 0 : goto failure;
1297 : }
1298 :
1299 768 : audit_event = authn_audit_info_event(audit_info);
1300 768 : rc = json_add_string(&object, "auditEvent", audit_event);
1301 768 : if (rc != 0) {
1302 0 : goto failure;
1303 : }
1304 :
1305 768 : audit_reason = authn_audit_info_reason(audit_info);
1306 768 : rc = json_add_string(&object, "reason", audit_reason);
1307 768 : if (rc != 0) {
1308 0 : goto failure;
1309 : }
1310 :
1311 768 : client_info = authn_audit_info_client_info(audit_info);
1312 768 : if (client_info != NULL) {
1313 665 : const struct auth_user_info *client_user_info = NULL;
1314 :
1315 665 : client_user_info = client_info->info;
1316 665 : if (client_user_info != NULL) {
1317 665 : rc = json_add_string(&object, "checkedDomain", client_user_info->domain_name);
1318 665 : if (rc != 0) {
1319 0 : goto failure;
1320 : }
1321 :
1322 665 : rc = json_add_string(&object, "checkedAccount", client_user_info->account_name);
1323 665 : if (rc != 0) {
1324 0 : goto failure;
1325 : }
1326 :
1327 665 : rc = json_add_string(&object, "checkedLogonServer", client_user_info->logon_server);
1328 665 : if (rc != 0) {
1329 0 : goto failure;
1330 : }
1331 :
1332 665 : rc = json_add_flags32(&object, "checkedAccountFlags", client_user_info->acct_flags);
1333 665 : if (rc != 0) {
1334 0 : goto failure;
1335 : }
1336 : }
1337 :
1338 665 : if (client_info->num_sids) {
1339 665 : const struct dom_sid *policy_checked_sid = NULL;
1340 :
1341 665 : policy_checked_sid = &client_info->sids[PRIMARY_USER_SID_INDEX].sid;
1342 665 : rc = json_add_sid(&object, "checkedSid", policy_checked_sid);
1343 665 : if (rc != 0) {
1344 0 : goto failure;
1345 : }
1346 : }
1347 : }
1348 :
1349 768 : return object;
1350 :
1351 0 : failure:
1352 0 : json_free(&object);
1353 0 : return object;
1354 : }
1355 :
1356 : #endif
|