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