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 "lib/messaging/messaging.h"
31 #include "auth/common_auth.h"
32 #include "audit_logging.h"
33
34 /*
35 * @brief Get a human readable timestamp.
36 *
37 * Returns the current time formatted as
38 * "Tue, 14 Mar 2017 08:38:42.209028 NZDT"
39 *
40 * The returned string is allocated by talloc in the supplied context.
41 * It is the callers responsibility to free it.
42 *
43 * @param mem_ctx talloc memory context that owns the returned string.
44 *
45 * @return a human readable time stamp, or NULL in the event of an error.
46 *
47 */
audit_get_timestamp(TALLOC_CTX * frame)48 char* audit_get_timestamp(TALLOC_CTX *frame)
49 {
50 char buffer[40]; /* formatted time less usec and timezone */
51 char tz[10]; /* formatted time zone */
52 struct tm* tm_info; /* current local time */
53 struct timeval tv; /* current system time */
54 int ret; /* response code */
55 char * ts; /* formatted time stamp */
56
57 ret = gettimeofday(&tv, NULL);
58 if (ret != 0) {
59 DBG_ERR("Unable to get time of day: (%d) %s\n",
60 errno,
61 strerror(errno));
62 return NULL;
63 }
64
65 tm_info = localtime(&tv.tv_sec);
66 if (tm_info == NULL) {
67 DBG_ERR("Unable to determine local time\n");
68 return NULL;
69 }
70
71 strftime(buffer, sizeof(buffer)-1, "%a, %d %b %Y %H:%M:%S", tm_info);
72 strftime(tz, sizeof(tz)-1, "%Z", tm_info);
73 ts = talloc_asprintf(frame, "%s.%06ld %s", buffer, tv.tv_usec, tz);
74 if (ts == NULL) {
75 DBG_ERR("Out of memory formatting time stamp\n");
76 }
77 return ts;
78 }
79
80 /*
81 * @brief write an audit message to the audit logs.
82 *
83 * Write a human readable text audit message to the samba logs.
84 *
85 * @param prefix Text to be printed at the start of the log line
86 * @param message The content of the log line.
87 * @param debub_class The debug class to log the message with.
88 * @param debug_level The debug level to log the message with.
89 */
audit_log_human_text(const char * prefix,const char * message,int debug_class,int debug_level)90 void audit_log_human_text(const char* prefix,
91 const char* message,
92 int debug_class,
93 int debug_level)
94 {
95 DEBUGC(debug_class, debug_level, ("%s %s\n", prefix, message));
96 }
97
98 #ifdef HAVE_JANSSON
99 /*
100 * Constant for empty json object initialisation
101 */
102 const struct json_object json_empty_object = {.valid = false, .root = NULL};
103 /*
104 * @brief write a json object to the samba audit logs.
105 *
106 * Write the json object to the audit logs as a formatted string
107 *
108 * @param message The content of the log line.
109 * @param debub_class The debug class to log the message with.
110 * @param debug_level The debug level to log the message with.
111 */
audit_log_json(struct json_object * message,int debug_class,int debug_level)112 void audit_log_json(struct json_object* message,
113 int debug_class,
114 int debug_level)
115 {
116 TALLOC_CTX *frame = NULL;
117 char *s = NULL;
118
119 if (json_is_invalid(message)) {
120 DBG_ERR("Invalid JSON object, unable to log\n");
121 return;
122 }
123
124 frame = talloc_stackframe();
125 s = json_to_string(frame, message);
126 if (s == NULL) {
127 DBG_ERR("json_to_string returned NULL, "
128 "JSON audit message could not written\n");
129 TALLOC_FREE(frame);
130 return;
131 }
132 /*
133 * This is very strange, but we call this routine to get a log
134 * output without the header. JSON logs all have timestamps
135 * so this only makes parsing harder.
136 *
137 * We push out the raw JSON blob without a prefix, consumers
138 * can find such lines by the leading {
139 */
140 DEBUGADDC(debug_class, debug_level, ("%s\n", s));
141 TALLOC_FREE(frame);
142 }
143
144 /*
145 * @brief get a connection to the messaging event server.
146 *
147 * Get a connection to the messaging event server registered by server_name.
148 *
149 * @param msg_ctx a valid imessaging_context.
150 * @param server_name name of messaging event server to connect to.
151 * @param server_id The event server details to populate
152 *
153 * @return NTSTATUS
154 */
get_event_server(struct imessaging_context * msg_ctx,const char * server_name,struct server_id * event_server)155 static NTSTATUS get_event_server(
156 struct imessaging_context *msg_ctx,
157 const char *server_name,
158 struct server_id *event_server)
159 {
160 NTSTATUS status;
161 TALLOC_CTX *frame = talloc_stackframe();
162 unsigned num_servers, i;
163 struct server_id *servers;
164
165 status = irpc_servers_byname(
166 msg_ctx,
167 frame,
168 server_name,
169 &num_servers,
170 &servers);
171
172 if (!NT_STATUS_IS_OK(status)) {
173 DBG_DEBUG("Failed to find the target '%s' on the message bus "
174 "to send JSON audit events to: %s\n",
175 server_name,
176 nt_errstr(status));
177 TALLOC_FREE(frame);
178 return status;
179 }
180
181 /*
182 * Select the first server that is listening, because we get
183 * connection refused as NT_STATUS_OBJECT_NAME_NOT_FOUND
184 * without waiting
185 */
186 for (i = 0; i < num_servers; i++) {
187 status = imessaging_send(
188 msg_ctx,
189 servers[i],
190 MSG_PING,
191 &data_blob_null);
192 if (NT_STATUS_IS_OK(status)) {
193 *event_server = servers[i];
194 TALLOC_FREE(frame);
195 return NT_STATUS_OK;
196 }
197 }
198 DBG_NOTICE(
199 "Failed to find '%s' registered on the message bus to "
200 "send JSON audit events to: %s\n",
201 server_name,
202 nt_errstr(status));
203 TALLOC_FREE(frame);
204 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
205 }
206
207 /*
208 * @brief send an audit message to a messaging event server.
209 *
210 * Send the message to a registered and listening event server.
211 * Note: Any errors are logged, and the message is not sent. This is to ensure
212 * that a poorly behaved event server does not impact Samba.
213 *
214 * As it is possible to lose messages, especially during server
215 * shut down, currently this function is primarily intended for use
216 * in integration tests.
217 *
218 * @param msg_ctx an imessaging_context, can be NULL in which case no message
219 * will be sent.
220 * @param server_name the naname of the event server to send the message to.
221 * @param messag_type A message type defined in librpc/idl/messaging.idl
222 * @param message The message to send.
223 *
224 */
audit_message_send(struct imessaging_context * msg_ctx,const char * server_name,uint32_t message_type,struct json_object * message)225 void audit_message_send(
226 struct imessaging_context *msg_ctx,
227 const char *server_name,
228 uint32_t message_type,
229 struct json_object *message)
230 {
231 struct server_id event_server = {
232 .pid = 0,
233 };
234 NTSTATUS status;
235
236 const char *message_string = NULL;
237 DATA_BLOB message_blob = data_blob_null;
238 TALLOC_CTX *ctx = NULL;
239
240 if (json_is_invalid(message)) {
241 DBG_ERR("Invalid JSON object, unable to send\n");
242 return;
243 }
244 if (msg_ctx == NULL) {
245 DBG_DEBUG("No messaging context\n");
246 return;
247 }
248
249 ctx = talloc_new(NULL);
250 if (ctx == NULL) {
251 DBG_ERR("Out of memory creating temporary context\n");
252 return;
253 }
254
255 /* Need to refetch the address each time as the destination server may
256 * have disconnected and reconnected in the interim, in which case
257 * messages may get lost
258 */
259 status = get_event_server(msg_ctx, server_name, &event_server);
260 if (!NT_STATUS_IS_OK(status)) {
261 TALLOC_FREE(ctx);
262 return;
263 }
264
265 message_string = json_to_string(ctx, message);
266 message_blob = data_blob_string_const(message_string);
267 status = imessaging_send(
268 msg_ctx,
269 event_server,
270 message_type,
271 &message_blob);
272
273 /*
274 * If the server crashed, try to find it again
275 */
276 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
277 status = get_event_server(msg_ctx, server_name, &event_server);
278 if (!NT_STATUS_IS_OK(status)) {
279 TALLOC_FREE(ctx);
280 return;
281 }
282 imessaging_send(
283 msg_ctx,
284 event_server,
285 message_type,
286 &message_blob);
287 }
288 TALLOC_FREE(ctx);
289 }
290
291 /*
292 * @brief Create a new struct json_object, wrapping a JSON Object.
293 *
294 * Create a new json object, the json_object wraps the underlying json
295 * implementations JSON Object representation.
296 *
297 * Free with a call to json_free_object, note that the jansson inplementation
298 * allocates memory with malloc and not talloc.
299 *
300 * @return a struct json_object, valid will be set to false if the object
301 * could not be created.
302 *
303 */
json_new_object(void)304 struct json_object json_new_object(void) {
305
306 struct json_object object = json_empty_object;
307
308 object.root = json_object();
309 if (object.root == NULL) {
310 object.valid = false;
311 DBG_ERR("Unable to create JSON object\n");
312 return object;
313 }
314 object.valid = true;
315 return object;
316 }
317
318 /*
319 * @brief Create a new struct json_object wrapping a JSON Array.
320 *
321 * Create a new json object, the json_object wraps the underlying json
322 * implementations JSON Array representation.
323 *
324 * Free with a call to json_free_object, note that the jansson inplementation
325 * allocates memory with malloc and not talloc.
326 *
327 * @return a struct json_object, error will be set to true if the array
328 * could not be created.
329 *
330 */
json_new_array(void)331 struct json_object json_new_array(void) {
332
333 struct json_object array = json_empty_object;
334
335 array.root = json_array();
336 if (array.root == NULL) {
337 array.valid = false;
338 DBG_ERR("Unable to create JSON array\n");
339 return array;
340 }
341 array.valid = true;
342 return array;
343 }
344
345
346 /*
347 * @brief free and invalidate a previously created JSON object.
348 *
349 * Release any resources owned by a json_object, and then mark the structure
350 * as invalid. It is safe to call this multiple times on an object.
351 *
352 */
json_free(struct json_object * object)353 void json_free(struct json_object *object)
354 {
355 if (object->root != NULL) {
356 json_decref(object->root);
357 }
358 object->root = NULL;
359 object->valid = false;
360 }
361
362 /*
363 * @brief is the current JSON object invalid?
364 *
365 * Check the state of the object to determine if it is invalid.
366 *
367 * @return is the object valid?
368 *
369 */
json_is_invalid(const struct json_object * object)370 bool json_is_invalid(const struct json_object *object)
371 {
372 return !object->valid;
373 }
374
375 /*
376 * @brief Add an integer value to a JSON object.
377 *
378 * Add an integer value named 'name' to the json object.
379 *
380 * @param object the JSON object to be updated.
381 * @param name the name of the value.
382 * @param value the value.
383 *
384 * @return 0 the operation was successful
385 * -1 the operation failed
386 *
387 */
json_add_int(struct json_object * object,const char * name,const int value)388 int json_add_int(struct json_object *object, const char *name, const int value)
389 {
390 int ret = 0;
391 json_t *integer = NULL;
392
393 if (json_is_invalid(object)) {
394 DBG_ERR("Unable to add int [%s] value [%d], "
395 "target object is invalid\n",
396 name,
397 value);
398 return JSON_ERROR;
399 }
400
401 integer = json_integer(value);
402 if (integer == NULL) {
403 DBG_ERR("Unable to create integer value [%s] value [%d]\n",
404 name,
405 value);
406 return JSON_ERROR;
407 }
408
409 ret = json_object_set_new(object->root, name, integer);
410 if (ret != 0) {
411 json_decref(integer);
412 DBG_ERR("Unable to add int [%s] value [%d]\n", name, value);
413 }
414 return ret;
415 }
416
417 /*
418 * @brief Add a boolean value to a JSON object.
419 *
420 * Add a boolean value named 'name' to the json object.
421 *
422 * @param object the JSON object to be updated.
423 * @param name the name.
424 * @param value the value.
425 *
426 * @return 0 the operation was successful
427 * -1 the operation failed
428 *
429 */
json_add_bool(struct json_object * object,const char * name,const bool value)430 int json_add_bool(struct json_object *object,
431 const char *name,
432 const bool value)
433 {
434 int ret = 0;
435
436 if (json_is_invalid(object)) {
437 DBG_ERR("Unable to add boolean [%s] value [%d], "
438 "target object is invalid\n",
439 name,
440 value);
441 return JSON_ERROR;
442 }
443
444 ret = json_object_set_new(object->root, name, json_boolean(value));
445 if (ret != 0) {
446 DBG_ERR("Unable to add boolean [%s] value [%d]\n", name, value);
447 }
448 return ret;
449 }
450
451 /*
452 * @brief Add a string value to a JSON object.
453 *
454 * Add a string value named 'name' to the json object.
455 *
456 * @param object the JSON object to be updated.
457 * @param name the name.
458 * @param value the value.
459 *
460 * @return 0 the operation was successful
461 * -1 the operation failed
462 *
463 */
json_add_string(struct json_object * object,const char * name,const char * value)464 int json_add_string(struct json_object *object,
465 const char *name,
466 const char *value)
467 {
468 int ret = 0;
469
470 if (json_is_invalid(object)) {
471 DBG_ERR("Unable to add string [%s], target object is invalid\n",
472 name);
473 return JSON_ERROR;
474 }
475 if (value) {
476 json_t *string = json_string(value);
477 if (string == NULL) {
478 DBG_ERR("Unable to add string [%s], "
479 "could not create string object\n",
480 name);
481 return JSON_ERROR;
482 }
483 ret = json_object_set_new(object->root, name, string);
484 if (ret != 0) {
485 json_decref(string);
486 DBG_ERR("Unable to add string [%s]\n", name);
487 return ret;
488 }
489 } else {
490 ret = json_object_set_new(object->root, name, json_null());
491 if (ret != 0) {
492 DBG_ERR("Unable to add null string [%s]\n", name);
493 return ret;
494 }
495 }
496 return ret;
497 }
498
499 /*
500 * @brief Assert that the current JSON object is an array.
501 *
502 * Check that the current object is a JSON array, and if not
503 * invalidate the object. We also log an error message as this indicates
504 * bug in the calling code.
505 *
506 * @param object the JSON object to be validated.
507 */
json_assert_is_array(struct json_object * array)508 void json_assert_is_array(struct json_object *array) {
509
510 if (json_is_invalid(array)) {
511 return;
512 }
513
514 if (json_is_array(array->root) == false) {
515 DBG_ERR("JSON object is not an array\n");
516 array->valid = false;
517 return;
518 }
519 }
520
521 /*
522 * @brief Add a JSON object to a JSON object.
523 *
524 * Add a JSON object named 'name' to the json object.
525 *
526 * @param object the JSON object to be updated.
527 * @param name the name.
528 * @param value the value.
529 *
530 * @return 0 the operation was successful
531 * -1 the operation failed
532 *
533 */
json_add_object(struct json_object * object,const char * name,struct json_object * value)534 int json_add_object(struct json_object *object,
535 const char *name,
536 struct json_object *value)
537 {
538 int ret = 0;
539 json_t *jv = NULL;
540
541 if (value != NULL && json_is_invalid(value)) {
542 DBG_ERR("Invalid JSON object [%s] supplied\n", name);
543 return JSON_ERROR;
544 }
545 if (json_is_invalid(object)) {
546 DBG_ERR("Unable to add object [%s], target object is invalid\n",
547 name);
548 return JSON_ERROR;
549 }
550
551 jv = value == NULL ? json_null() : value->root;
552
553 if (json_is_array(object->root)) {
554 ret = json_array_append_new(object->root, jv);
555 } else if (json_is_object(object->root)) {
556 ret = json_object_set_new(object->root, name, jv);
557 } else {
558 DBG_ERR("Invalid JSON object type\n");
559 ret = JSON_ERROR;
560 }
561 if (ret != 0) {
562 DBG_ERR("Unable to add object [%s]\n", name);
563 }
564 return ret;
565 }
566
567 /*
568 * @brief Add a string to a JSON object, truncating if necessary.
569 *
570 *
571 * Add a string value named 'name' to the json object, the string will be
572 * truncated if it is more than len characters long. If len is 0 the value
573 * is encoded as a JSON null.
574 *
575 *
576 * @param object the JSON object to be updated.
577 * @param name the name.
578 * @param value the value.
579 * @param len the maximum number of characters to be copied.
580 *
581 * @return 0 the operation was successful
582 * -1 the operation failed
583 *
584 */
json_add_stringn(struct json_object * object,const char * name,const char * value,const size_t len)585 int json_add_stringn(struct json_object *object,
586 const char *name,
587 const char *value,
588 const size_t len)
589 {
590
591 int ret = 0;
592 if (json_is_invalid(object)) {
593 DBG_ERR("Unable to add string [%s], target object is invalid\n",
594 name);
595 return JSON_ERROR;
596 }
597
598 if (value != NULL && len > 0) {
599 json_t *string = NULL;
600 char buffer[len+1];
601
602 strncpy(buffer, value, len);
603 buffer[len] = '\0';
604
605 string = json_string(buffer);
606 if (string == NULL) {
607 DBG_ERR("Unable to add string [%s], "
608 "could not create string object\n",
609 name);
610 return JSON_ERROR;
611 }
612 ret = json_object_set_new(object->root, name, string);
613 if (ret != 0) {
614 json_decref(string);
615 DBG_ERR("Unable to add string [%s]\n", name);
616 return ret;
617 }
618 } else {
619 ret = json_object_set_new(object->root, name, json_null());
620 if (ret != 0) {
621 DBG_ERR("Unable to add null string [%s]\n", name);
622 return ret;
623 }
624 }
625 return ret;
626 }
627
628 /*
629 * @brief Add a version object to a JSON object
630 *
631 * Add a version object to the JSON object
632 * "version":{"major":1, "minor":0}
633 *
634 * The version tag is intended to aid the processing of the JSON messages
635 * The major version number should change when an attribute is:
636 * - renamed
637 * - removed
638 * - its meaning changes
639 * - its contents change format
640 * The minor version should change whenever a new attribute is added and for
641 * minor bug fixes to an attributes content.
642 *
643 *
644 * @param object the JSON object to be updated.
645 * @param major the major version number
646 * @param minor the minor version number
647 *
648 * @return 0 the operation was successful
649 * -1 the operation failed
650 */
json_add_version(struct json_object * object,int major,int minor)651 int json_add_version(struct json_object *object, int major, int minor)
652 {
653 int ret = 0;
654 struct json_object version;
655
656 if (json_is_invalid(object)) {
657 DBG_ERR("Unable to add version, target object is invalid\n");
658 return JSON_ERROR;
659 }
660
661 version = json_new_object();
662 if (json_is_invalid(&version)) {
663 DBG_ERR("Unable to add version, failed to create object\n");
664 return JSON_ERROR;
665 }
666 ret = json_add_int(&version, "major", major);
667 if (ret != 0) {
668 json_free(&version);
669 return ret;
670 }
671 ret = json_add_int(&version, "minor", minor);
672 if (ret != 0) {
673 json_free(&version);
674 return ret;
675 }
676 ret = json_add_object(object, "version", &version);
677 if (ret != 0) {
678 json_free(&version);
679 return ret;
680 }
681 return ret;
682 }
683
684 /*
685 * @brief add an ISO 8601 timestamp to the object.
686 *
687 * Add the current date and time as a timestamp in ISO 8601 format
688 * to a JSON object
689 *
690 * "timestamp":"2017-03-06T17:18:04.455081+1300"
691 *
692 *
693 * @param object the JSON object to be updated.
694 *
695 * @return 0 the operation was successful
696 * -1 the operation failed
697 */
json_add_timestamp(struct json_object * object)698 int json_add_timestamp(struct json_object *object)
699 {
700 char buffer[40]; /* formatted time less usec and timezone */
701 char timestamp[65]; /* the formatted ISO 8601 time stamp */
702 char tz[10]; /* formatted time zone */
703 struct tm* tm_info; /* current local time */
704 struct timeval tv; /* current system time */
705 int r; /* response code from gettimeofday */
706 int ret; /* return code from json operations */
707
708 if (json_is_invalid(object)) {
709 DBG_ERR("Unable to add time stamp, target object is invalid\n");
710 return JSON_ERROR;
711 }
712
713 r = gettimeofday(&tv, NULL);
714 if (r) {
715 DBG_ERR("Unable to get time of day: (%d) %s\n",
716 errno,
717 strerror(errno));
718 return JSON_ERROR;
719 }
720
721 tm_info = localtime(&tv.tv_sec);
722 if (tm_info == NULL) {
723 DBG_ERR("Unable to determine local time\n");
724 return JSON_ERROR;
725 }
726
727 strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info);
728 strftime(tz, sizeof(tz)-1, "%z", tm_info);
729 snprintf(
730 timestamp,
731 sizeof(timestamp),
732 "%s.%06ld%s",
733 buffer,
734 tv.tv_usec,
735 tz);
736 ret = json_add_string(object, "timestamp", timestamp);
737 if (ret != 0) {
738 DBG_ERR("Unable to add time stamp to JSON object\n");
739 }
740 return ret;
741 }
742
743 /*
744 *@brief Add a tsocket_address to a JSON object
745 *
746 * Add the string representation of a Samba tsocket_address to the object.
747 *
748 * "localAddress":"ipv6::::0"
749 *
750 *
751 * @param object the JSON object to be updated.
752 * @param name the name.
753 * @param address the tsocket_address.
754 *
755 * @return 0 the operation was successful
756 * -1 the operation failed
757 *
758 */
json_add_address(struct json_object * object,const char * name,const struct tsocket_address * address)759 int json_add_address(struct json_object *object,
760 const char *name,
761 const struct tsocket_address *address)
762 {
763 int ret = 0;
764
765 if (json_is_invalid(object)) {
766 DBG_ERR("Unable to add address [%s], "
767 "target object is invalid\n",
768 name);
769 return JSON_ERROR;
770 }
771
772 if (address == NULL) {
773 ret = json_object_set_new(object->root, name, json_null());
774 if (ret != 0) {
775 DBG_ERR("Unable to add null address [%s]\n", name);
776 return JSON_ERROR;
777 }
778 } else {
779 TALLOC_CTX *ctx = talloc_new(NULL);
780 char *s = NULL;
781
782 if (ctx == NULL) {
783 DBG_ERR("Out of memory adding address [%s]\n", name);
784 return JSON_ERROR;
785 }
786
787 s = tsocket_address_string(address, ctx);
788 if (s == NULL) {
789 DBG_ERR("Out of memory adding address [%s]\n", name);
790 TALLOC_FREE(ctx);
791 return JSON_ERROR;
792 }
793 ret = json_add_string(object, name, s);
794 if (ret != 0) {
795 DBG_ERR(
796 "Unable to add address [%s] value [%s]\n", name, s);
797 TALLOC_FREE(ctx);
798 return JSON_ERROR;
799 }
800 TALLOC_FREE(ctx);
801 }
802 return ret;
803 }
804
805 /*
806 * @brief Add a formatted string representation of a sid to a json object.
807 *
808 * Add the string representation of a Samba sid to the object.
809 *
810 * "sid":"S-1-5-18"
811 *
812 *
813 * @param object the JSON object to be updated.
814 * @param name the name.
815 * @param sid the sid
816 *
817 * @return 0 the operation was successful
818 * -1 the operation failed
819 *
820 */
json_add_sid(struct json_object * object,const char * name,const struct dom_sid * sid)821 int json_add_sid(struct json_object *object,
822 const char *name,
823 const struct dom_sid *sid)
824 {
825 int ret = 0;
826
827 if (json_is_invalid(object)) {
828 DBG_ERR("Unable to add SID [%s], "
829 "target object is invalid\n",
830 name);
831 return JSON_ERROR;
832 }
833
834 if (sid == NULL) {
835 ret = json_object_set_new(object->root, name, json_null());
836 if (ret != 0) {
837 DBG_ERR("Unable to add null SID [%s]\n", name);
838 return ret;
839 }
840 } else {
841 struct dom_sid_buf sid_buf;
842
843 ret = json_add_string(
844 object, name, dom_sid_str_buf(sid, &sid_buf));
845 if (ret != 0) {
846 DBG_ERR("Unable to add SID [%s] value [%s]\n",
847 name,
848 sid_buf.buf);
849 return ret;
850 }
851 }
852 return ret;
853 }
854
855 /*
856 * @brief Add a formatted string representation of a guid to a json object.
857 *
858 * Add the string representation of a Samba GUID to the object.
859 *
860 * "guid":"1fb9f2ee-2a4d-4bf8-af8b-cb9d4529a9ab"
861 *
862 *
863 * @param object the JSON object to be updated.
864 * @param name the name.
865 * @param guid the guid.
866 *
867 * @return 0 the operation was successful
868 * -1 the operation failed
869 *
870 *
871 */
json_add_guid(struct json_object * object,const char * name,const struct GUID * guid)872 int json_add_guid(struct json_object *object,
873 const char *name,
874 const struct GUID *guid)
875 {
876
877 int ret = 0;
878
879 if (json_is_invalid(object)) {
880 DBG_ERR("Unable to add GUID [%s], "
881 "target object is invalid\n",
882 name);
883 return JSON_ERROR;
884 }
885
886 if (guid == NULL) {
887 ret = json_object_set_new(object->root, name, json_null());
888 if (ret != 0) {
889 DBG_ERR("Unable to add null GUID [%s]\n", name);
890 return ret;
891 }
892 } else {
893 char *guid_str;
894 struct GUID_txt_buf guid_buff;
895
896 guid_str = GUID_buf_string(guid, &guid_buff);
897 ret = json_add_string(object, name, guid_str);
898 if (ret != 0) {
899 DBG_ERR("Unable to guid GUID [%s] value [%s]\n",
900 name,
901 guid_str);
902 return ret;
903 }
904 }
905 return ret;
906 }
907
908 /*
909 * @brief Convert a JSON object into a string
910 *
911 * Convert the jsom object into a string suitable for printing on a log line,
912 * i.e. with no embedded line breaks.
913 *
914 * If the object is invalid it logs an error and returns NULL.
915 *
916 * @param mem_ctx the talloc memory context owning the returned string
917 * @param object the json object.
918 *
919 * @return A string representation of the object or NULL if the object
920 * is invalid.
921 */
json_to_string(TALLOC_CTX * mem_ctx,const struct json_object * object)922 char *json_to_string(TALLOC_CTX *mem_ctx, const struct json_object *object)
923 {
924 char *json = NULL;
925 char *json_string = NULL;
926
927 if (json_is_invalid(object)) {
928 DBG_ERR("Invalid JSON object, unable to convert to string\n");
929 return NULL;
930 }
931
932 if (object->root == NULL) {
933 return NULL;
934 }
935
936 /*
937 * json_dumps uses malloc, so need to call free(json) to release
938 * the memory
939 */
940 json = json_dumps(object->root, 0);
941 if (json == NULL) {
942 DBG_ERR("Unable to convert JSON object to string\n");
943 return NULL;
944 }
945
946 json_string = talloc_strdup(mem_ctx, json);
947 if (json_string == NULL) {
948 free(json);
949 DBG_ERR("Unable to copy JSON object string to talloc string\n");
950 return NULL;
951 }
952 free(json);
953
954 return json_string;
955 }
956
957 /*
958 * @brief get a json array named "name" from the json object.
959 *
960 * Get the array attribute named name, creating it if it does not exist.
961 *
962 * @param object the json object.
963 * @param name the name of the array attribute
964 *
965 * @return The array object, will be created if it did not exist.
966 */
json_get_array(struct json_object * object,const char * name)967 struct json_object json_get_array(struct json_object *object, const char *name)
968 {
969
970 struct json_object array = json_empty_object;
971 json_t *a = NULL;
972 int ret = 0;
973
974 if (json_is_invalid(object)) {
975 DBG_ERR("Invalid JSON object, unable to get array [%s]\n",
976 name);
977 json_free(&array);
978 return array;
979 }
980
981 array = json_new_array();
982 if (json_is_invalid(&array)) {
983 DBG_ERR("Unable to create new array for [%s]\n", name);
984 return array;
985 }
986
987 a = json_object_get(object->root, name);
988 if (a == NULL) {
989 return array;
990 }
991
992 ret = json_array_extend(array.root, a);
993 if (ret != 0) {
994 DBG_ERR("Unable to get array [%s]\n", name);
995 json_free(&array);
996 return array;
997 }
998
999 return array;
1000 }
1001
1002 /*
1003 * @brief get a json object named "name" from the json object.
1004 *
1005 * Get the object attribute named name, creating it if it does not exist.
1006 *
1007 * @param object the json object.
1008 * @param name the name of the object attribute
1009 *
1010 * @return The object, will be created if it did not exist.
1011 */
json_get_object(struct json_object * object,const char * name)1012 struct json_object json_get_object(struct json_object *object, const char *name)
1013 {
1014
1015 struct json_object o = json_new_object();
1016 json_t *v = NULL;
1017 int ret = 0;
1018
1019 if (json_is_invalid(object)) {
1020 DBG_ERR("Invalid JSON object, unable to get object [%s]\n",
1021 name);
1022 json_free(&o);
1023 return o;
1024 }
1025
1026 v = json_object_get(object->root, name);
1027 if (v == NULL) {
1028 return o;
1029 }
1030 ret = json_object_update(o.root, v);
1031 if (ret != 0) {
1032 DBG_ERR("Unable to get object [%s]\n", name);
1033 json_free(&o);
1034 return o;
1035 }
1036 return o;
1037 }
1038 #endif
1039