LCOV - code coverage report
Current view: top level - lib/audit_logging - audit_logging.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 432 512 84.4 %
Date: 2024-06-10 12:05:21 Functions: 28 29 96.6 %

          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      727328 : void audit_log_json(struct json_object* message,
     115             :                     int debug_class,
     116             :                     int debug_level)
     117             : {
     118      727328 :         TALLOC_CTX *frame = NULL;
     119      727328 :         char *s = NULL;
     120             : 
     121      727328 :         if (json_is_invalid(message)) {
     122           0 :                 DBG_ERR("Invalid JSON object, unable to log\n");
     123           0 :                 return;
     124             :         }
     125             : 
     126      727328 :         frame = talloc_stackframe();
     127      727328 :         s = json_to_string(frame, message);
     128      727328 :         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      727328 :         DEBUGADDC(debug_class, debug_level, ("%s\n", s));
     143      727328 :         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      727317 : static NTSTATUS get_event_server(
     158             :         struct imessaging_context *msg_ctx,
     159             :         const char *server_name,
     160             :         struct server_id *event_server)
     161             : {
     162       18307 :         NTSTATUS status;
     163      727317 :         TALLOC_CTX *frame = talloc_stackframe();
     164       18307 :         unsigned num_servers, i;
     165       18307 :         struct server_id *servers;
     166             : 
     167      727317 :         status = irpc_servers_byname(
     168             :                 msg_ctx,
     169             :                 frame,
     170             :                 server_name,
     171             :                 &num_servers,
     172             :                 &servers);
     173             : 
     174      727317 :         if (!NT_STATUS_IS_OK(status)) {
     175      724810 :                 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      724810 :                 TALLOC_FREE(frame);
     180      724810 :                 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      727317 : 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      727317 :         struct server_id event_server = {
     234             :                 .pid = 0,
     235             :         };
     236       18307 :         NTSTATUS status;
     237             : 
     238      727317 :         const char *message_string = NULL;
     239      727317 :         DATA_BLOB message_blob = data_blob_null;
     240      727317 :         TALLOC_CTX *ctx = NULL;
     241             : 
     242      727317 :         if (json_is_invalid(message)) {
     243           0 :                 DBG_ERR("Invalid JSON object, unable to send\n");
     244      724810 :                 return;
     245             :         }
     246      727317 :         if (msg_ctx == NULL) {
     247           0 :                 DBG_DEBUG("No messaging context\n");
     248           0 :                 return;
     249             :         }
     250             : 
     251      727317 :         ctx = talloc_new(NULL);
     252      727317 :         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      727317 :         status = get_event_server(msg_ctx, server_name, &event_server);
     262      727317 :         if (!NT_STATUS_IS_OK(status)) {
     263      724810 :                 TALLOC_FREE(ctx);
     264      724810 :                 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     8376233 : struct json_object json_new_object(void) {
     307             : 
     308     8376233 :         struct json_object object = json_empty_object;
     309             : 
     310     8376233 :         object.root = json_object();
     311     8376233 :         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     8376232 :         object.valid = true;
     317     8376232 :         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     3478072 : struct json_object json_new_array(void) {
     334             : 
     335     3478072 :         struct json_object array = json_empty_object;
     336             : 
     337     3478072 :         array.root = json_array();
     338     3478072 :         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     3478071 :         array.valid = true;
     344     3478071 :         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      727495 : void json_free(struct json_object *object)
     356             : {
     357      727495 :         if (object->root != NULL) {
     358      727468 :                 json_decref(object->root);
     359             :         }
     360      727495 :         object->root = NULL;
     361      727495 :         object->valid = false;
     362      727495 : }
     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    67045061 : bool json_is_invalid(const struct json_object *object)
     373             : {
     374    67045061 :         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     2287856 : int json_add_int(struct json_object *object, const char *name, const json_int_t value)
     391             : {
     392     2287856 :         int ret = 0;
     393     2287856 :         json_t *integer = NULL;
     394             : 
     395     2287856 :         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     2287854 :         integer = json_integer(value);
     404     2287854 :         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     2287853 :         ret = json_object_set_new(object->root, name, integer);
     412     2287853 :         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     2227641 :         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      741697 : int json_add_bool(struct json_object *object,
     435             :                   const char *name,
     436             :                   const bool value)
     437             : {
     438      741697 :         int ret = 0;
     439             : 
     440      741697 :         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      741695 :         ret = json_object_set_new(object->root, name, json_boolean(value));
     449      741695 :         if (ret != 0) {
     450           1 :                 DBG_ERR("Unable to add boolean [%s] value [%d]\n", name, value);
     451             :         }
     452      713345 :         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     8449633 : int json_add_string(struct json_object *object,
     513             :                     const char *name,
     514             :                     const char *value)
     515             : {
     516     8449633 :         int ret = 0;
     517             : 
     518     8449633 :         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     8449631 :         if (value) {
     524     8315663 :                 json_t *string = json_string(value);
     525     8315663 :                 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     8315661 :                 ret = json_object_set_new(object->root, name, string);
     532     8315661 :                 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      133968 :                 ret = json_object_set_new(object->root, name, json_null());
     539      133968 :                 if (ret != 0) {
     540           1 :                         DBG_ERR("Unable to add null string [%s]\n", name);
     541           1 :                         return ret;
     542             :                 }
     543             :         }
     544     8159661 :         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     2395488 : void json_assert_is_array(struct json_object *array) {
     557             : 
     558     2395488 :         if (json_is_invalid(array)) {
     559           0 :                 return;
     560             :         }
     561             : 
     562     2395488 :         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    11362153 : int json_add_object(struct json_object *object,
     583             :                     const char *name,
     584             :                     struct json_object *value)
     585             : {
     586    11362153 :         int ret = 0;
     587    11362153 :         json_t *jv = NULL;
     588             : 
     589    11362153 :         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    11362151 :         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    11362147 :         jv = value == NULL ? json_null() : value->root;
     600             : 
     601    11362147 :         if (json_is_array(object->root)) {
     602     4142284 :                 ret = json_array_append_new(object->root, jv);
     603     7219863 :         } else if (json_is_object(object->root)) {
     604     7219863 :                 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    11362147 :         if (ret != 0) {
     610           4 :                 DBG_ERR("Unable to add object [%s]\n", name);
     611             :         }
     612    10856526 :         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     2028747 : int json_add_stringn(struct json_object *object,
     634             :                      const char *name,
     635             :                      const char *value,
     636             :                      const size_t len)
     637             : {
     638             : 
     639     2028747 :         int ret = 0;
     640     2028747 :         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     3957895 :         if (value != NULL && len > 0) {
     647     2028739 :                 json_t *string = json_stringn(value, len);
     648     2028739 :                 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     2028738 :                 ret = json_object_set_new(object->root, name, string);
     655     2028738 :                 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     1929150 :         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      727365 : int json_add_version(struct json_object *object, int major, int minor)
     694             : {
     695      727365 :         int ret = 0;
     696       18355 :         struct json_object version;
     697             : 
     698      727365 :         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      727363 :         version = json_new_object();
     704      727363 :         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      727362 :         ret = json_add_int(&version, "major", major);
     709      727362 :         if (ret != 0) {
     710           1 :                 json_free(&version);
     711           1 :                 return ret;
     712             :         }
     713      727361 :         ret = json_add_int(&version, "minor", minor);
     714      727361 :         if (ret != 0) {
     715           2 :                 json_free(&version);
     716           2 :                 return ret;
     717             :         }
     718      727359 :         ret = json_add_object(object, "version", &version);
     719      727359 :         if (ret != 0) {
     720           0 :                 json_free(&version);
     721           0 :                 return ret;
     722             :         }
     723      709010 :         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      760468 : int json_add_time(struct json_object *object, const char *name, const struct timeval tv)
     742             : {
     743       20012 :         char buffer[40];        /* formatted time less usec and timezone */
     744       20012 :         char timestamp[65];     /* the formatted ISO 8601 time stamp     */
     745       20012 :         char tz[10];            /* formatted time zone                   */
     746       20012 :         struct tm* tm_info;     /* current local time                    */
     747       20012 :         int ret;                /* return code from json operations     */
     748             : 
     749      760468 :         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      760468 :         tm_info = localtime(&tv.tv_sec);
     755      760468 :         if (tm_info == NULL) {
     756           1 :                 DBG_ERR("Unable to determine local time\n");
     757           1 :                 return JSON_ERROR;
     758             :         }
     759             : 
     760      760467 :         strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info);
     761      760467 :         strftime(tz, sizeof(tz)-1, "%z", tm_info);
     762      760467 :         snprintf(
     763             :                 timestamp,
     764             :                 sizeof(timestamp),
     765             :                 "%s.%06ld%s",
     766             :                 buffer,
     767      760467 :                 tv.tv_usec,
     768             :                 tz);
     769      760467 :         ret = json_add_string(object, name, timestamp);
     770      760467 :         if (ret != 0) {
     771           2 :                 DBG_ERR("Unable to add time to JSON object\n");
     772             :         }
     773      740456 :         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      727380 : int json_add_timestamp(struct json_object *object)
     791             : {
     792       18343 :         struct timeval tv;      /* current system time                   */
     793       18343 :         int r;                  /* response code from gettimeofday       */
     794             : 
     795      727380 :         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      727378 :         r = gettimeofday(&tv, NULL);
     801      727378 :         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      727377 :         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      692085 : int json_add_address(struct json_object *object,
     828             :                      const char *name,
     829             :                      const struct tsocket_address *address)
     830             : {
     831      692085 :         int ret = 0;
     832             : 
     833      692085 :         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      692083 :         if (address == NULL) {
     841      277562 :                 ret = json_object_set_new(object->root, name, json_null());
     842      277562 :                 if (ret != 0) {
     843           1 :                         DBG_ERR("Unable to add null address [%s]\n", name);
     844           1 :                         return JSON_ERROR;
     845             :                 }
     846             :         } else {
     847      414521 :                 TALLOC_CTX *ctx = talloc_new(NULL);
     848      414521 :                 char *s = NULL;
     849             : 
     850      414521 :                 if (ctx == NULL) {
     851           1 :                         DBG_ERR("Out of memory adding address [%s]\n", name);
     852           1 :                         return JSON_ERROR;
     853             :                 }
     854             : 
     855      414520 :                 s = tsocket_address_string(address, ctx);
     856      414520 :                 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      414519 :                 ret = json_add_string(object, name, s);
     862      414519 :                 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      414518 :                 TALLOC_FREE(ctx);
     869             :         }
     870      669243 :         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      606222 : int json_add_sid(struct json_object *object,
     890             :                  const char *name,
     891             :                  const struct dom_sid *sid)
     892             : {
     893      606222 :         int ret = 0;
     894             : 
     895      606222 :         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      606220 :         if (sid == NULL) {
     903       39059 :                 ret = json_object_set_new(object->root, name, json_null());
     904       39059 :                 if (ret != 0) {
     905           1 :                         DBG_ERR("Unable to add null SID [%s]\n", name);
     906           1 :                         return ret;
     907             :                 }
     908             :         } else {
     909       17868 :                 struct dom_sid_buf sid_buf;
     910             : 
     911      567161 :                 ret = json_add_string(
     912      567161 :                         object, name, dom_sid_str_buf(sid, &sid_buf));
     913      567161 :                 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      586864 :         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     1065169 : int json_add_guid(struct json_object *object,
     941             :                   const char *name,
     942             :                   const struct GUID *guid)
     943             : {
     944             : 
     945     1065169 :         int ret = 0;
     946             : 
     947     1065169 :         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     1065167 :         if (guid == NULL) {
     955        4588 :                 ret = json_object_set_new(object->root, name, json_null());
     956        4588 :                 if (ret != 0) {
     957           1 :                         DBG_ERR("Unable to add null GUID [%s]\n", name);
     958           1 :                         return ret;
     959             :                 }
     960             :         } else {
     961       24025 :                 char *guid_str;
     962       24025 :                 struct GUID_txt_buf guid_buff;
     963             : 
     964     1060579 :                 guid_str = GUID_buf_string(guid, &guid_buff);
     965     1060579 :                 ret = json_add_string(object, name, guid_str);
     966     1060579 :                 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     1041134 :         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      103481 : int json_add_flags32(struct json_object *object,
     996             :                   const char *name,
     997             :                   const uint32_t flags)
     998             : {
     999      103481 :         int ret = 0;
    1000        4651 :         char buf[sizeof("0x12345678")];
    1001             : 
    1002      103481 :         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      103481 :         ret = snprintf(buf, sizeof (buf), "0x%08X", flags);
    1010      103481 :         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      103481 :         ret = json_add_string(object, name, buf);
    1018      103481 :         if (ret != 0) {
    1019           0 :                 DBG_ERR("Unable to add flags [%s] value [%s]\n",
    1020             :                         name,
    1021             :                         buf);
    1022             :         }
    1023             : 
    1024       98830 :         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        2664 : int json_update_object(struct json_object *object,
    1041             :                        const char *key,
    1042             :                        struct json_object *new_obj)
    1043             : {
    1044        2664 :         int ret = 0;
    1045             : 
    1046        2664 :         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        2664 :         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        2664 :         if (key == NULL) {
    1060           0 :                 DBG_ERR("Unable to add null String as key\n");
    1061           0 :                 return JSON_ERROR;
    1062             :         }
    1063             : 
    1064        2664 :         ret = json_object_set(object->root, key, new_obj->root);
    1065        2664 :         if (ret != 0) {
    1066           0 :                 DBG_ERR("Unable to update object\n");
    1067           0 :                 return ret;
    1068             :         }
    1069             : 
    1070        2664 :         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      729854 : char *json_to_string(TALLOC_CTX *mem_ctx, const struct json_object *object)
    1088             : {
    1089      729854 :         char *json = NULL;
    1090      729854 :         char *json_string = NULL;
    1091             : 
    1092      729854 :         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      729853 :         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      729852 :         json = json_dumps(object->root, 0);
    1106      729852 :         if (json == NULL) {
    1107           1 :                 DBG_ERR("Unable to convert JSON object to string\n");
    1108           1 :                 return NULL;
    1109             :         }
    1110             : 
    1111      729851 :         json_string = talloc_strdup(mem_ctx, json);
    1112      729851 :         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      729850 :         free(json);
    1118             : 
    1119      729850 :         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     1746796 : struct json_object json_get_array(struct json_object *object, const char *name)
    1133             : {
    1134             : 
    1135     1746796 :         struct json_object array = json_empty_object;
    1136     1746796 :         json_t *a = NULL;
    1137     1746796 :         int ret = 0;
    1138             : 
    1139     1746796 :         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     1746795 :         array = json_new_array();
    1147     1746795 :         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     1746794 :         a = json_object_get(object->root, name);
    1153     1746794 :         if (a == NULL) {
    1154     1686167 :                 return array;
    1155             :         }
    1156             : 
    1157       60627 :         ret = json_array_extend(array.root, a);
    1158       60627 :         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       60626 :         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     1749458 : struct json_object json_get_object(struct json_object *object, const char *name)
    1178             : {
    1179             : 
    1180     1749458 :         struct json_object o = json_new_object();
    1181     1749458 :         json_t *v = NULL;
    1182     1749458 :         int ret = 0;
    1183             : 
    1184     1749458 :         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     1749458 :         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     1749457 :         v = json_object_get(object->root, name);
    1198     1749457 :         if (v == NULL) {
    1199     1686764 :                 return o;
    1200             :         }
    1201       62693 :         ret = json_object_update(o.root, v);
    1202       62693 :         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       62692 :         return o;
    1208             : }
    1209             : 
    1210             : /*
    1211             :  * @brief Return the JSON null object.
    1212             :  *
    1213             :  * @return the JSON null object.
    1214             :  */
    1215      238723 : _WARN_UNUSED_RESULT_ struct json_object json_null_object(void)
    1216             : {
    1217      238723 :         struct json_object object = json_empty_object;
    1218             : 
    1219      238723 :         object.root = json_null();
    1220      238723 :         if (object.root != NULL) {
    1221      238723 :                 object.valid = true;
    1222             :         }
    1223             : 
    1224      238723 :         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

Generated by: LCOV version 1.14