profile: issues info message with lower log level
[Samba.git] / lib / audit_logging / audit_logging.c
blob496e347659c1423204b286d49740001af8f78643
1 /*
2 common routines for audit logging
4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
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.
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.
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/>.
21 * Error handling:
25 #include "includes.h"
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"
37 * @brief Get a human readable timestamp.
39 * Returns the current time formatted as
40 * "Tue, 14 Mar 2017 08:38:42.209028 NZDT"
42 * The returned string is allocated by talloc in the supplied context.
43 * It is the callers responsibility to free it.
45 * @param mem_ctx talloc memory context that owns the returned string.
47 * @return a human readable time stamp, or NULL in the event of an error.
50 char* audit_get_timestamp(TALLOC_CTX *frame)
52 char buffer[40]; /* formatted time less usec and timezone */
53 char tz[10]; /* formatted time zone */
54 struct tm* tm_info; /* current local time */
55 struct timeval tv; /* current system time */
56 int ret; /* response code */
57 char * ts; /* formatted time stamp */
59 ret = gettimeofday(&tv, NULL);
60 if (ret != 0) {
61 DBG_ERR("Unable to get time of day: (%d) %s\n",
62 errno,
63 strerror(errno));
64 return NULL;
67 tm_info = localtime(&tv.tv_sec);
68 if (tm_info == NULL) {
69 DBG_ERR("Unable to determine local time\n");
70 return NULL;
73 strftime(buffer, sizeof(buffer)-1, "%a, %d %b %Y %H:%M:%S", tm_info);
74 strftime(tz, sizeof(tz)-1, "%Z", tm_info);
75 ts = talloc_asprintf(frame, "%s.%06ld %s", buffer, (long)tv.tv_usec, tz);
76 if (ts == NULL) {
77 DBG_ERR("Out of memory formatting time stamp\n");
79 return ts;
83 * @brief write an audit message to the audit logs.
85 * Write a human readable text audit message to the samba logs.
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.
92 void audit_log_human_text(const char* prefix,
93 const char* message,
94 int debug_class,
95 int debug_level)
97 DEBUGC(debug_class, debug_level, ("%s %s\n", prefix, message));
100 #ifdef HAVE_JANSSON
102 * Constant for empty json object initialisation
104 const struct json_object json_empty_object = {.valid = false, .root = NULL};
106 * @brief write a json object to the samba audit logs.
108 * Write the json object to the audit logs as a formatted string
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.
114 void audit_log_json(struct json_object* message,
115 int debug_class,
116 int debug_level)
118 TALLOC_CTX *frame = NULL;
119 char *s = NULL;
121 if (json_is_invalid(message)) {
122 DBG_ERR("Invalid JSON object, unable to log\n");
123 return;
126 frame = talloc_stackframe();
127 s = json_to_string(frame, message);
128 if (s == NULL) {
129 DBG_ERR("json_to_string returned NULL, "
130 "JSON audit message could not written\n");
131 TALLOC_FREE(frame);
132 return;
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.
139 * We push out the raw JSON blob without a prefix, consumers
140 * can find such lines by the leading {
142 DEBUGADDC(debug_class, debug_level, ("%s\n", s));
143 TALLOC_FREE(frame);
147 * @brief get a connection to the messaging event server.
149 * Get a connection to the messaging event server registered by server_name.
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
155 * @return NTSTATUS
157 static NTSTATUS get_event_server(
158 struct imessaging_context *msg_ctx,
159 const char *server_name,
160 struct server_id *event_server)
162 NTSTATUS status;
163 TALLOC_CTX *frame = talloc_stackframe();
164 unsigned num_servers, i;
165 struct server_id *servers;
167 status = irpc_servers_byname(
168 msg_ctx,
169 frame,
170 server_name,
171 &num_servers,
172 &servers);
174 if (!NT_STATUS_IS_OK(status)) {
175 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 TALLOC_FREE(frame);
180 return status;
184 * Select the first server that is listening, because we get
185 * connection refused as NT_STATUS_OBJECT_NAME_NOT_FOUND
186 * without waiting
188 for (i = 0; i < num_servers; i++) {
189 status = imessaging_send(
190 msg_ctx,
191 servers[i],
192 MSG_PING,
193 &data_blob_null);
194 if (NT_STATUS_IS_OK(status)) {
195 *event_server = servers[i];
196 TALLOC_FREE(frame);
197 return NT_STATUS_OK;
200 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 TALLOC_FREE(frame);
206 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
210 * @brief send an audit message to a messaging event server.
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.
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.
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.
227 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)
233 struct server_id event_server = {
234 .pid = 0,
236 NTSTATUS status;
238 const char *message_string = NULL;
239 DATA_BLOB message_blob = data_blob_null;
240 TALLOC_CTX *ctx = NULL;
242 if (json_is_invalid(message)) {
243 DBG_ERR("Invalid JSON object, unable to send\n");
244 return;
246 if (msg_ctx == NULL) {
247 DBG_DEBUG("No messaging context\n");
248 return;
251 ctx = talloc_new(NULL);
252 if (ctx == NULL) {
253 DBG_ERR("Out of memory creating temporary context\n");
254 return;
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
261 status = get_event_server(msg_ctx, server_name, &event_server);
262 if (!NT_STATUS_IS_OK(status)) {
263 TALLOC_FREE(ctx);
264 return;
267 message_string = json_to_string(ctx, message);
268 message_blob = data_blob_string_const(message_string);
269 status = imessaging_send(
270 msg_ctx,
271 event_server,
272 message_type,
273 &message_blob);
276 * If the server crashed, try to find it again
278 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
279 status = get_event_server(msg_ctx, server_name, &event_server);
280 if (!NT_STATUS_IS_OK(status)) {
281 TALLOC_FREE(ctx);
282 return;
284 imessaging_send(
285 msg_ctx,
286 event_server,
287 message_type,
288 &message_blob);
290 TALLOC_FREE(ctx);
294 * @brief Create a new struct json_object, wrapping a JSON Object.
296 * Create a new json object, the json_object wraps the underlying json
297 * implementations JSON Object representation.
299 * Free with a call to json_free_object, note that the jansson implementation
300 * allocates memory with malloc and not talloc.
302 * @return a struct json_object, valid will be set to false if the object
303 * could not be created.
306 struct json_object json_new_object(void) {
308 struct json_object object = json_empty_object;
310 object.root = json_object();
311 if (object.root == NULL) {
312 object.valid = false;
313 DBG_ERR("Unable to create JSON object\n");
314 return object;
316 object.valid = true;
317 return object;
321 * @brief Create a new struct json_object wrapping a JSON Array.
323 * Create a new json object, the json_object wraps the underlying json
324 * implementations JSON Array representation.
326 * Free with a call to json_free_object, note that the jansson implementation
327 * allocates memory with malloc and not talloc.
329 * @return a struct json_object, error will be set to true if the array
330 * could not be created.
333 struct json_object json_new_array(void) {
335 struct json_object array = json_empty_object;
337 array.root = json_array();
338 if (array.root == NULL) {
339 array.valid = false;
340 DBG_ERR("Unable to create JSON array\n");
341 return array;
343 array.valid = true;
344 return array;
349 * @brief free and invalidate a previously created JSON object.
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.
355 void json_free(struct json_object *object)
357 if (object->root != NULL) {
358 json_decref(object->root);
360 object->root = NULL;
361 object->valid = false;
365 * @brief is the current JSON object invalid?
367 * Check the state of the object to determine if it is invalid.
369 * @return is the object valid?
372 bool json_is_invalid(const struct json_object *object)
374 return !object->valid;
378 * @brief Add an integer value to a JSON object.
380 * Add an integer value named 'name' to the json object.
382 * @param object the JSON object to be updated.
383 * @param name the name of the value.
384 * @param value the value.
386 * @return 0 the operation was successful
387 * -1 the operation failed
390 int json_add_int(struct json_object *object, const char *name, const json_int_t value)
392 int ret = 0;
393 json_t *integer = NULL;
395 if (json_is_invalid(object)) {
396 DBG_ERR("Unable to add int [%s] value [%jd], "
397 "target object is invalid\n",
398 name,
399 (intmax_t)value);
400 return JSON_ERROR;
403 integer = json_integer(value);
404 if (integer == NULL) {
405 DBG_ERR("Unable to create integer value [%s] value [%jd]\n",
406 name,
407 (intmax_t)value);
408 return JSON_ERROR;
411 ret = json_object_set_new(object->root, name, integer);
412 if (ret != 0) {
413 json_decref(integer);
414 DBG_ERR("Unable to add int [%s] value [%jd]\n",
415 name,
416 (intmax_t)value);
418 return ret;
422 * @brief Add a boolean value to a JSON object.
424 * Add a boolean value named 'name' to the json object.
426 * @param object the JSON object to be updated.
427 * @param name the name.
428 * @param value the value.
430 * @return 0 the operation was successful
431 * -1 the operation failed
434 int json_add_bool(struct json_object *object,
435 const char *name,
436 const bool value)
438 int ret = 0;
440 if (json_is_invalid(object)) {
441 DBG_ERR("Unable to add boolean [%s] value [%d], "
442 "target object is invalid\n",
443 name,
444 value);
445 return JSON_ERROR;
448 ret = json_object_set_new(object->root, name, json_boolean(value));
449 if (ret != 0) {
450 DBG_ERR("Unable to add boolean [%s] value [%d]\n", name, value);
452 return ret;
456 * @brief Add an optional boolean value to a JSON object.
458 * Add an optional boolean value named 'name' to the json object.
460 * @param object the JSON object to be updated.
461 * @param name the name.
462 * @param value the value.
464 * @return 0 the operation was successful
465 * -1 the operation failed
468 int json_add_optional_bool(struct json_object *object,
469 const char *name,
470 const bool *value)
472 int ret = 0;
474 if (json_is_invalid(object)) {
475 DBG_ERR("Unable to add boolean [%s] value [%d], "
476 "target object is invalid\n",
477 name,
478 *value);
479 return JSON_ERROR;
482 if (value != NULL) {
483 ret = json_object_set_new(object->root, name, json_boolean(*value));
484 if (ret != 0) {
485 DBG_ERR("Unable to add boolean [%s] value [%d]\n", name, *value);
486 return ret;
488 } else {
489 ret = json_object_set_new(object->root, name, json_null());
490 if (ret != 0) {
491 DBG_ERR("Unable to add null boolean [%s]\n", name);
492 return ret;
496 return ret;
500 * @brief Add a string value to a JSON object.
502 * Add a string value named 'name' to the json object.
504 * @param object the JSON object to be updated.
505 * @param name the name.
506 * @param value the value.
508 * @return 0 the operation was successful
509 * -1 the operation failed
512 int json_add_string(struct json_object *object,
513 const char *name,
514 const char *value)
516 int ret = 0;
518 if (json_is_invalid(object)) {
519 DBG_ERR("Unable to add string [%s], target object is invalid\n",
520 name);
521 return JSON_ERROR;
523 if (value) {
524 json_t *string = json_string(value);
525 if (string == NULL) {
526 DBG_ERR("Unable to add string [%s], "
527 "could not create string object\n",
528 name);
529 return JSON_ERROR;
531 ret = json_object_set_new(object->root, name, string);
532 if (ret != 0) {
533 json_decref(string);
534 DBG_ERR("Unable to add string [%s]\n", name);
535 return ret;
537 } else {
538 ret = json_object_set_new(object->root, name, json_null());
539 if (ret != 0) {
540 DBG_ERR("Unable to add null string [%s]\n", name);
541 return ret;
544 return ret;
548 * @brief Assert that the current JSON object is an array.
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.
554 * @param object the JSON object to be validated.
556 void json_assert_is_array(struct json_object *array) {
558 if (json_is_invalid(array)) {
559 return;
562 if (json_is_array(array->root) == false) {
563 DBG_ERR("JSON object is not an array\n");
564 array->valid = false;
565 return;
570 * @brief Add a JSON object to a JSON object.
572 * Add a JSON object named 'name' to the json object.
574 * @param object the JSON object to be updated.
575 * @param name the name.
576 * @param value the value.
578 * @return 0 the operation was successful
579 * -1 the operation failed
582 int json_add_object(struct json_object *object,
583 const char *name,
584 struct json_object *value)
586 int ret = 0;
587 json_t *jv = NULL;
589 if (value != NULL && json_is_invalid(value)) {
590 DBG_ERR("Invalid JSON object [%s] supplied\n", name);
591 return JSON_ERROR;
593 if (json_is_invalid(object)) {
594 DBG_ERR("Unable to add object [%s], target object is invalid\n",
595 name);
596 return JSON_ERROR;
599 jv = value == NULL ? json_null() : value->root;
601 if (json_is_array(object->root)) {
602 ret = json_array_append_new(object->root, jv);
603 } else if (json_is_object(object->root)) {
604 ret = json_object_set_new(object->root, name, jv);
605 } else {
606 DBG_ERR("Invalid JSON object type\n");
607 ret = JSON_ERROR;
609 if (ret != 0) {
610 DBG_ERR("Unable to add object [%s]\n", name);
612 return ret;
616 * @brief Add a string to a JSON object, truncating if necessary.
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.
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.
629 * @return 0 the operation was successful
630 * -1 the operation failed
633 int json_add_stringn(struct json_object *object,
634 const char *name,
635 const char *value,
636 const size_t len)
639 int ret = 0;
640 if (json_is_invalid(object)) {
641 DBG_ERR("Unable to add string [%s], target object is invalid\n",
642 name);
643 return JSON_ERROR;
646 if (value != NULL && len > 0) {
647 json_t *string = NULL;
648 char buffer[len+1];
650 strncpy(buffer, value, len);
651 buffer[len] = '\0';
653 string = json_string(buffer);
654 if (string == NULL) {
655 DBG_ERR("Unable to add string [%s], "
656 "could not create string object\n",
657 name);
658 return JSON_ERROR;
660 ret = json_object_set_new(object->root, name, string);
661 if (ret != 0) {
662 json_decref(string);
663 DBG_ERR("Unable to add string [%s]\n", name);
664 return ret;
666 } else {
667 ret = json_object_set_new(object->root, name, json_null());
668 if (ret != 0) {
669 DBG_ERR("Unable to add null string [%s]\n", name);
670 return ret;
673 return ret;
677 * @brief Add a version object to a JSON object
679 * Add a version object to the JSON object
680 * "version":{"major":1, "minor":0}
682 * The version tag is intended to aid the processing of the JSON messages
683 * The major version number should change when an attribute is:
684 * - renamed
685 * - removed
686 * - its meaning changes
687 * - its contents change format
688 * The minor version should change whenever a new attribute is added and for
689 * minor bug fixes to an attributes content.
692 * @param object the JSON object to be updated.
693 * @param major the major version number
694 * @param minor the minor version number
696 * @return 0 the operation was successful
697 * -1 the operation failed
699 int json_add_version(struct json_object *object, int major, int minor)
701 int ret = 0;
702 struct json_object version;
704 if (json_is_invalid(object)) {
705 DBG_ERR("Unable to add version, target object is invalid\n");
706 return JSON_ERROR;
709 version = json_new_object();
710 if (json_is_invalid(&version)) {
711 DBG_ERR("Unable to add version, failed to create object\n");
712 return JSON_ERROR;
714 ret = json_add_int(&version, "major", major);
715 if (ret != 0) {
716 json_free(&version);
717 return ret;
719 ret = json_add_int(&version, "minor", minor);
720 if (ret != 0) {
721 json_free(&version);
722 return ret;
724 ret = json_add_object(object, "version", &version);
725 if (ret != 0) {
726 json_free(&version);
727 return ret;
729 return ret;
733 * @brief add an ISO 8601 timestamp to the object.
735 * Add a date and time as a timestamp in ISO 8601 format to a JSON object
737 * "time":"2017-03-06T17:18:04.455081+1300"
740 * @param object the JSON object to be updated.
741 * @param name the name.
742 * @param time the value to set.
744 * @return 0 the operation was successful
745 * -1 the operation failed
747 int json_add_time(struct json_object *object, const char *name, const struct timeval tv)
749 char buffer[40]; /* formatted time less usec and timezone */
750 char timestamp[65]; /* the formatted ISO 8601 time stamp */
751 char tz[10]; /* formatted time zone */
752 struct tm* tm_info; /* current local time */
753 int ret; /* return code from json operations */
755 if (json_is_invalid(object)) {
756 DBG_ERR("Unable to add time, target object is invalid\n");
757 return JSON_ERROR;
760 tm_info = localtime(&tv.tv_sec);
761 if (tm_info == NULL) {
762 DBG_ERR("Unable to determine local time\n");
763 return JSON_ERROR;
766 strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info);
767 strftime(tz, sizeof(tz)-1, "%z", tm_info);
768 snprintf(
769 timestamp,
770 sizeof(timestamp),
771 "%s.%06ld%s",
772 buffer,
773 tv.tv_usec,
774 tz);
775 ret = json_add_string(object, name, timestamp);
776 if (ret != 0) {
777 DBG_ERR("Unable to add time to JSON object\n");
779 return ret;
783 * @brief add an ISO 8601 timestamp to the object.
785 * Add the current date and time as a timestamp in ISO 8601 format
786 * to a JSON object
788 * "timestamp":"2017-03-06T17:18:04.455081+1300"
791 * @param object the JSON object to be updated.
793 * @return 0 the operation was successful
794 * -1 the operation failed
796 int json_add_timestamp(struct json_object *object)
798 struct timeval tv; /* current system time */
799 int r; /* response code from gettimeofday */
801 if (json_is_invalid(object)) {
802 DBG_ERR("Unable to add time stamp, target object is invalid\n");
803 return JSON_ERROR;
806 r = gettimeofday(&tv, NULL);
807 if (r) {
808 DBG_ERR("Unable to get time of day: (%d) %s\n",
809 errno,
810 strerror(errno));
811 return JSON_ERROR;
814 return json_add_time(object, "timestamp", tv);
818 *@brief Add a tsocket_address to a JSON object
820 * Add the string representation of a Samba tsocket_address to the object.
822 * "localAddress":"ipv6::::0"
825 * @param object the JSON object to be updated.
826 * @param name the name.
827 * @param address the tsocket_address.
829 * @return 0 the operation was successful
830 * -1 the operation failed
833 int json_add_address(struct json_object *object,
834 const char *name,
835 const struct tsocket_address *address)
837 int ret = 0;
839 if (json_is_invalid(object)) {
840 DBG_ERR("Unable to add address [%s], "
841 "target object is invalid\n",
842 name);
843 return JSON_ERROR;
846 if (address == NULL) {
847 ret = json_object_set_new(object->root, name, json_null());
848 if (ret != 0) {
849 DBG_ERR("Unable to add null address [%s]\n", name);
850 return JSON_ERROR;
852 } else {
853 TALLOC_CTX *ctx = talloc_new(NULL);
854 char *s = NULL;
856 if (ctx == NULL) {
857 DBG_ERR("Out of memory adding address [%s]\n", name);
858 return JSON_ERROR;
861 s = tsocket_address_string(address, ctx);
862 if (s == NULL) {
863 DBG_ERR("Out of memory adding address [%s]\n", name);
864 TALLOC_FREE(ctx);
865 return JSON_ERROR;
867 ret = json_add_string(object, name, s);
868 if (ret != 0) {
869 DBG_ERR(
870 "Unable to add address [%s] value [%s]\n", name, s);
871 TALLOC_FREE(ctx);
872 return JSON_ERROR;
874 TALLOC_FREE(ctx);
876 return ret;
880 * @brief Add a formatted string representation of a sid to a json object.
882 * Add the string representation of a Samba sid to the object.
884 * "sid":"S-1-5-18"
887 * @param object the JSON object to be updated.
888 * @param name the name.
889 * @param sid the sid
891 * @return 0 the operation was successful
892 * -1 the operation failed
895 int json_add_sid(struct json_object *object,
896 const char *name,
897 const struct dom_sid *sid)
899 int ret = 0;
901 if (json_is_invalid(object)) {
902 DBG_ERR("Unable to add SID [%s], "
903 "target object is invalid\n",
904 name);
905 return JSON_ERROR;
908 if (sid == NULL) {
909 ret = json_object_set_new(object->root, name, json_null());
910 if (ret != 0) {
911 DBG_ERR("Unable to add null SID [%s]\n", name);
912 return ret;
914 } else {
915 struct dom_sid_buf sid_buf;
917 ret = json_add_string(
918 object, name, dom_sid_str_buf(sid, &sid_buf));
919 if (ret != 0) {
920 DBG_ERR("Unable to add SID [%s] value [%s]\n",
921 name,
922 sid_buf.buf);
923 return ret;
926 return ret;
930 * @brief Add a formatted string representation of a guid to a json object.
932 * Add the string representation of a Samba GUID to the object.
934 * "guid":"1fb9f2ee-2a4d-4bf8-af8b-cb9d4529a9ab"
937 * @param object the JSON object to be updated.
938 * @param name the name.
939 * @param guid the guid.
941 * @return 0 the operation was successful
942 * -1 the operation failed
946 int json_add_guid(struct json_object *object,
947 const char *name,
948 const struct GUID *guid)
951 int ret = 0;
953 if (json_is_invalid(object)) {
954 DBG_ERR("Unable to add GUID [%s], "
955 "target object is invalid\n",
956 name);
957 return JSON_ERROR;
960 if (guid == NULL) {
961 ret = json_object_set_new(object->root, name, json_null());
962 if (ret != 0) {
963 DBG_ERR("Unable to add null GUID [%s]\n", name);
964 return ret;
966 } else {
967 char *guid_str;
968 struct GUID_txt_buf guid_buff;
970 guid_str = GUID_buf_string(guid, &guid_buff);
971 ret = json_add_string(object, name, guid_str);
972 if (ret != 0) {
973 DBG_ERR("Unable to add GUID [%s] value [%s]\n",
974 name,
975 guid_str);
976 return ret;
979 return ret;
983 * @brief Add a hex-formatted string representation of a 32-bit integer to a
984 * json object.
986 * Add a hex-formatted string representation of a 32-bit flags integer to the
987 * object.
989 * "accountFlags":"0x12345678"
992 * @param object the JSON object to be updated.
993 * @param name the name.
994 * @param flags the flags.
996 * @return 0 the operation was successful
997 * -1 the operation failed
1001 int json_add_flags32(struct json_object *object,
1002 const char *name,
1003 const uint32_t flags)
1005 int ret = 0;
1006 char buf[sizeof("0x12345678")];
1008 if (json_is_invalid(object)) {
1009 DBG_ERR("Unable to add flags [%s], "
1010 "target object is invalid\n",
1011 name);
1012 return JSON_ERROR;
1015 ret = snprintf(buf, sizeof (buf), "0x%08X", flags);
1016 if (ret != sizeof (buf) - 1) {
1017 DBG_ERR("Unable to format flags [%s] value [0x%08X]\n",
1018 name,
1019 flags);
1020 return JSON_ERROR;
1023 ret = json_add_string(object, name, buf);
1024 if (ret != 0) {
1025 DBG_ERR("Unable to add flags [%s] value [%s]\n",
1026 name,
1027 buf);
1030 return ret;
1034 * @brief Replaces the object for a given key with a given json object.
1036 * If key already exists, the value will be replaced. Otherwise the given
1037 * value will be added under the given key.
1039 * @param object the JSON object to be updated.
1040 * @param key the key which will be updated.
1041 * @param new_obj the new value object to be inserted.
1043 * @return 0 the operation was successful
1044 * -1 the operation failed (e.j. if one of the parameters is invalid)
1046 int json_update_object(struct json_object *object,
1047 const char *key,
1048 struct json_object *new_obj)
1050 int ret = 0;
1052 if (json_is_invalid(object)) {
1053 DBG_ERR("Unable to update key [%s], "
1054 "target object is invalid\n",
1055 key);
1056 return JSON_ERROR;
1058 if (json_is_invalid(new_obj)) {
1059 DBG_ERR("Unable to update key [%s], "
1060 "new object is invalid\n",
1061 key);
1062 return JSON_ERROR;
1065 if (key == NULL) {
1066 DBG_ERR("Unable to add null String as key\n");
1067 return JSON_ERROR;
1070 ret = json_object_set(object->root, key, new_obj->root);
1071 if (ret != 0) {
1072 DBG_ERR("Unable to update object\n");
1073 return ret;
1076 return ret;
1080 * @brief Convert a JSON object into a string
1082 * Convert the json object into a string suitable for printing on a log line,
1083 * i.e. with no embedded line breaks.
1085 * If the object is invalid it logs an error and returns NULL.
1087 * @param mem_ctx the talloc memory context owning the returned string
1088 * @param object the json object.
1090 * @return A string representation of the object or NULL if the object
1091 * is invalid.
1093 char *json_to_string(TALLOC_CTX *mem_ctx, const struct json_object *object)
1095 char *json = NULL;
1096 char *json_string = NULL;
1098 if (json_is_invalid(object)) {
1099 DBG_ERR("Invalid JSON object, unable to convert to string\n");
1100 return NULL;
1103 if (object->root == NULL) {
1104 return NULL;
1108 * json_dumps uses malloc, so need to call free(json) to release
1109 * the memory
1111 json = json_dumps(object->root, 0);
1112 if (json == NULL) {
1113 DBG_ERR("Unable to convert JSON object to string\n");
1114 return NULL;
1117 json_string = talloc_strdup(mem_ctx, json);
1118 if (json_string == NULL) {
1119 free(json);
1120 DBG_ERR("Unable to copy JSON object string to talloc string\n");
1121 return NULL;
1123 free(json);
1125 return json_string;
1129 * @brief get a json array named "name" from the json object.
1131 * Get the array attribute named name, creating it if it does not exist.
1133 * @param object the json object.
1134 * @param name the name of the array attribute
1136 * @return The array object, will be created if it did not exist.
1138 struct json_object json_get_array(struct json_object *object, const char *name)
1141 struct json_object array = json_empty_object;
1142 json_t *a = NULL;
1143 int ret = 0;
1145 if (json_is_invalid(object)) {
1146 DBG_ERR("Invalid JSON object, unable to get array [%s]\n",
1147 name);
1148 json_free(&array);
1149 return array;
1152 array = json_new_array();
1153 if (json_is_invalid(&array)) {
1154 DBG_ERR("Unable to create new array for [%s]\n", name);
1155 return array;
1158 a = json_object_get(object->root, name);
1159 if (a == NULL) {
1160 return array;
1163 ret = json_array_extend(array.root, a);
1164 if (ret != 0) {
1165 DBG_ERR("Unable to get array [%s]\n", name);
1166 json_free(&array);
1167 return array;
1170 return array;
1174 * @brief get a json object named "name" from the json object.
1176 * Get the object attribute named name, creating it if it does not exist.
1178 * @param object the json object.
1179 * @param name the name of the object attribute
1181 * @return The object, will be created if it did not exist.
1183 struct json_object json_get_object(struct json_object *object, const char *name)
1186 struct json_object o = json_new_object();
1187 json_t *v = NULL;
1188 int ret = 0;
1190 if (json_is_invalid(&o)) {
1191 DBG_ERR("Unable to get object [%s]\n", name);
1192 json_free(&o);
1193 return o;
1196 if (json_is_invalid(object)) {
1197 DBG_ERR("Invalid JSON object, unable to get object [%s]\n",
1198 name);
1199 json_free(&o);
1200 return o;
1203 v = json_object_get(object->root, name);
1204 if (v == NULL) {
1205 return o;
1207 ret = json_object_update(o.root, v);
1208 if (ret != 0) {
1209 DBG_ERR("Unable to get object [%s]\n", name);
1210 json_free(&o);
1211 return o;
1213 return o;
1217 * @brief Return the JSON null object.
1219 * @return the JSON null object.
1221 _WARN_UNUSED_RESULT_ struct json_object json_null_object(void)
1223 struct json_object object = json_empty_object;
1225 object.root = json_null();
1226 if (object.root != NULL) {
1227 object.valid = true;
1230 return object;
1234 * @brief Create a JSON object from a structure containing audit information.
1236 * @param audit_info the audit information from which to create a JSON object.
1238 * @return the JSON object (which may be valid or not)
1242 struct json_object json_from_audit_info(const struct authn_audit_info *audit_info)
1244 struct json_object object = json_new_object();
1245 enum auth_event_id_type auth_event_id;
1246 const struct auth_user_info_dc *client_info = NULL;
1247 const char *policy_name = NULL;
1248 const char *silo_name = NULL;
1249 const bool *policy_enforced = NULL;
1250 NTSTATUS policy_status;
1251 struct authn_int64_optional tgt_lifetime_mins;
1252 const char *location = NULL;
1253 const char *audit_event = NULL;
1254 const char *audit_reason = NULL;
1255 int rc = 0;
1257 if (json_is_invalid(&object)) {
1258 goto failure;
1261 auth_event_id = authn_audit_info_event_id(audit_info);
1262 rc = json_add_int(&object, "eventId", auth_event_id);
1263 if (rc != 0) {
1264 goto failure;
1267 policy_name = authn_audit_info_policy_name(audit_info);
1268 rc = json_add_string(&object, "policyName", policy_name);
1269 if (rc != 0) {
1270 goto failure;
1273 silo_name = authn_audit_info_silo_name(audit_info);
1274 rc = json_add_string(&object, "siloName", silo_name);
1275 if (rc != 0) {
1276 goto failure;
1279 policy_enforced = authn_audit_info_policy_enforced(audit_info);
1280 rc = json_add_optional_bool(&object, "policyEnforced", policy_enforced);
1281 if (rc != 0) {
1282 goto failure;
1285 policy_status = authn_audit_info_policy_status(audit_info);
1286 rc = json_add_string(&object, "status", nt_errstr(policy_status));
1287 if (rc != 0) {
1288 goto failure;
1291 tgt_lifetime_mins = authn_audit_info_policy_tgt_lifetime_mins(audit_info);
1292 if (tgt_lifetime_mins.is_present) {
1293 rc = json_add_int(&object, "tgtLifetime", tgt_lifetime_mins.val);
1294 if (rc != 0) {
1295 goto failure;
1299 location = authn_audit_info_location(audit_info);
1300 rc = json_add_string(&object, "location", location);
1301 if (rc != 0) {
1302 goto failure;
1305 audit_event = authn_audit_info_event(audit_info);
1306 rc = json_add_string(&object, "auditEvent", audit_event);
1307 if (rc != 0) {
1308 goto failure;
1311 audit_reason = authn_audit_info_reason(audit_info);
1312 rc = json_add_string(&object, "reason", audit_reason);
1313 if (rc != 0) {
1314 goto failure;
1317 client_info = authn_audit_info_client_info(audit_info);
1318 if (client_info != NULL) {
1319 const struct auth_user_info *client_user_info = NULL;
1321 client_user_info = client_info->info;
1322 if (client_user_info != NULL) {
1323 rc = json_add_string(&object, "checkedDomain", client_user_info->domain_name);
1324 if (rc != 0) {
1325 goto failure;
1328 rc = json_add_string(&object, "checkedAccount", client_user_info->account_name);
1329 if (rc != 0) {
1330 goto failure;
1333 rc = json_add_string(&object, "checkedLogonServer", client_user_info->logon_server);
1334 if (rc != 0) {
1335 goto failure;
1338 rc = json_add_flags32(&object, "checkedAccountFlags", client_user_info->acct_flags);
1339 if (rc != 0) {
1340 goto failure;
1344 if (client_info->num_sids) {
1345 const struct dom_sid *policy_checked_sid = NULL;
1347 policy_checked_sid = &client_info->sids[PRIMARY_USER_SID_INDEX].sid;
1348 rc = json_add_sid(&object, "checkedSid", policy_checked_sid);
1349 if (rc != 0) {
1350 goto failure;
1355 return object;
1357 failure:
1358 json_free(&object);
1359 return object;
1362 #endif