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 "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 : */
48 0 : 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 0 : ret = gettimeofday(&tv, NULL);
58 0 : if (ret != 0) {
59 0 : DBG_ERR("Unable to get time of day: (%d) %s\n",
60 : errno,
61 : strerror(errno));
62 0 : return NULL;
63 : }
64 :
65 0 : tm_info = localtime(&tv.tv_sec);
66 0 : if (tm_info == NULL) {
67 0 : DBG_ERR("Unable to determine local time\n");
68 0 : return NULL;
69 : }
70 :
71 0 : strftime(buffer, sizeof(buffer)-1, "%a, %d %b %Y %H:%M:%S", tm_info);
72 0 : strftime(tz, sizeof(tz)-1, "%Z", tm_info);
73 0 : ts = talloc_asprintf(frame, "%s.%06ld %s", buffer, (long)tv.tv_usec, tz);
74 0 : if (ts == NULL) {
75 0 : DBG_ERR("Out of memory formatting time stamp\n");
76 : }
77 0 : 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 : */
90 0 : void audit_log_human_text(const char* prefix,
91 : const char* message,
92 : int debug_class,
93 : int debug_level)
94 : {
95 0 : DEBUGC(debug_class, debug_level, ("%s %s\n", prefix, message));
96 0 : }
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 : */
112 427920 : void audit_log_json(struct json_object* message,
113 : int debug_class,
114 : int debug_level)
115 : {
116 427920 : TALLOC_CTX *frame = NULL;
117 427920 : char *s = NULL;
118 :
119 427920 : if (json_is_invalid(message)) {
120 0 : DBG_ERR("Invalid JSON object, unable to log\n");
121 0 : return;
122 : }
123 :
124 427920 : frame = talloc_stackframe();
125 427920 : s = json_to_string(frame, message);
126 427920 : if (s == NULL) {
127 0 : DBG_ERR("json_to_string returned NULL, "
128 : "JSON audit message could not written\n");
129 0 : TALLOC_FREE(frame);
130 0 : 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 427920 : DEBUGADDC(debug_class, debug_level, ("%s\n", s));
141 427920 : 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 : */
155 427920 : 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 427920 : TALLOC_CTX *frame = talloc_stackframe();
162 : unsigned num_servers, i;
163 : struct server_id *servers;
164 :
165 427920 : status = irpc_servers_byname(
166 : msg_ctx,
167 : frame,
168 : server_name,
169 : &num_servers,
170 : &servers);
171 :
172 427920 : if (!NT_STATUS_IS_OK(status)) {
173 427705 : 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 427705 : TALLOC_FREE(frame);
178 427705 : 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 215 : for (i = 0; i < num_servers; i++) {
187 215 : status = imessaging_send(
188 : msg_ctx,
189 215 : servers[i],
190 : MSG_PING,
191 : &data_blob_null);
192 215 : if (NT_STATUS_IS_OK(status)) {
193 215 : *event_server = servers[i];
194 215 : TALLOC_FREE(frame);
195 215 : return NT_STATUS_OK;
196 : }
197 : }
198 0 : 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 0 : TALLOC_FREE(frame);
204 0 : 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 : */
225 427920 : 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 427920 : struct server_id event_server = {
232 : .pid = 0,
233 : };
234 : NTSTATUS status;
235 :
236 427920 : const char *message_string = NULL;
237 427920 : DATA_BLOB message_blob = data_blob_null;
238 427920 : TALLOC_CTX *ctx = NULL;
239 :
240 427920 : if (json_is_invalid(message)) {
241 0 : DBG_ERR("Invalid JSON object, unable to send\n");
242 427705 : return;
243 : }
244 427920 : if (msg_ctx == NULL) {
245 0 : DBG_DEBUG("No messaging context\n");
246 0 : return;
247 : }
248 :
249 427920 : ctx = talloc_new(NULL);
250 427920 : if (ctx == NULL) {
251 0 : DBG_ERR("Out of memory creating temporary context\n");
252 0 : 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 427920 : status = get_event_server(msg_ctx, server_name, &event_server);
260 427920 : if (!NT_STATUS_IS_OK(status)) {
261 427705 : TALLOC_FREE(ctx);
262 427705 : return;
263 : }
264 :
265 215 : message_string = json_to_string(ctx, message);
266 215 : message_blob = data_blob_string_const(message_string);
267 215 : 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 215 : if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
277 0 : status = get_event_server(msg_ctx, server_name, &event_server);
278 0 : if (!NT_STATUS_IS_OK(status)) {
279 0 : TALLOC_FREE(ctx);
280 0 : return;
281 : }
282 0 : imessaging_send(
283 : msg_ctx,
284 : event_server,
285 : message_type,
286 : &message_blob);
287 : }
288 215 : 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 implementation
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 : */
304 5658890 : struct json_object json_new_object(void) {
305 :
306 5658890 : struct json_object object = json_empty_object;
307 :
308 5658890 : object.root = json_object();
309 5658890 : if (object.root == NULL) {
310 0 : object.valid = false;
311 0 : DBG_ERR("Unable to create JSON object\n");
312 0 : return object;
313 : }
314 5658890 : object.valid = true;
315 5658890 : 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 implementation
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 : */
331 2449028 : struct json_object json_new_array(void) {
332 :
333 2449028 : struct json_object array = json_empty_object;
334 :
335 2449028 : array.root = json_array();
336 2449028 : if (array.root == NULL) {
337 0 : array.valid = false;
338 0 : DBG_ERR("Unable to create JSON array\n");
339 0 : return array;
340 : }
341 2449028 : array.valid = true;
342 2449028 : 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 : */
353 427924 : void json_free(struct json_object *object)
354 : {
355 427924 : if (object->root != NULL) {
356 427924 : json_decref(object->root);
357 : }
358 427924 : object->root = NULL;
359 427924 : object->valid = false;
360 427924 : }
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 : */
370 42797368 : bool json_is_invalid(const struct json_object *object)
371 : {
372 42797368 : 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 : */
388 1375317 : int json_add_int(struct json_object *object, const char *name, const int value)
389 : {
390 1375317 : int ret = 0;
391 1375317 : json_t *integer = NULL;
392 :
393 1375317 : if (json_is_invalid(object)) {
394 0 : DBG_ERR("Unable to add int [%s] value [%d], "
395 : "target object is invalid\n",
396 : name,
397 : value);
398 0 : return JSON_ERROR;
399 : }
400 :
401 1375317 : integer = json_integer(value);
402 1375317 : if (integer == NULL) {
403 0 : DBG_ERR("Unable to create integer value [%s] value [%d]\n",
404 : name,
405 : value);
406 0 : return JSON_ERROR;
407 : }
408 :
409 1375317 : ret = json_object_set_new(object->root, name, integer);
410 1375317 : if (ret != 0) {
411 0 : json_decref(integer);
412 0 : DBG_ERR("Unable to add int [%s] value [%d]\n", name, value);
413 : }
414 1375317 : 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 : */
430 521866 : int json_add_bool(struct json_object *object,
431 : const char *name,
432 : const bool value)
433 : {
434 521866 : int ret = 0;
435 :
436 521866 : if (json_is_invalid(object)) {
437 0 : DBG_ERR("Unable to add boolean [%s] value [%d], "
438 : "target object is invalid\n",
439 : name,
440 : value);
441 0 : return JSON_ERROR;
442 : }
443 :
444 521866 : ret = json_object_set_new(object->root, name, json_boolean(value));
445 521866 : if (ret != 0) {
446 0 : DBG_ERR("Unable to add boolean [%s] value [%d]\n", name, value);
447 : }
448 521866 : 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 : */
464 5131029 : int json_add_string(struct json_object *object,
465 : const char *name,
466 : const char *value)
467 : {
468 5131029 : int ret = 0;
469 :
470 5131029 : if (json_is_invalid(object)) {
471 0 : DBG_ERR("Unable to add string [%s], target object is invalid\n",
472 : name);
473 0 : return JSON_ERROR;
474 : }
475 5131029 : if (value) {
476 5056835 : json_t *string = json_string(value);
477 5056835 : if (string == NULL) {
478 0 : DBG_ERR("Unable to add string [%s], "
479 : "could not create string object\n",
480 : name);
481 0 : return JSON_ERROR;
482 : }
483 5056835 : ret = json_object_set_new(object->root, name, string);
484 5056835 : if (ret != 0) {
485 0 : json_decref(string);
486 0 : DBG_ERR("Unable to add string [%s]\n", name);
487 0 : return ret;
488 : }
489 : } else {
490 74194 : ret = json_object_set_new(object->root, name, json_null());
491 74194 : if (ret != 0) {
492 0 : DBG_ERR("Unable to add null string [%s]\n", name);
493 0 : return ret;
494 : }
495 : }
496 5131029 : 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 : */
508 1710518 : void json_assert_is_array(struct json_object *array) {
509 :
510 1710518 : if (json_is_invalid(array)) {
511 0 : return;
512 : }
513 :
514 1710518 : if (json_is_array(array->root) == false) {
515 0 : DBG_ERR("JSON object is not an array\n");
516 0 : array->valid = false;
517 0 : 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 : */
534 7679994 : int json_add_object(struct json_object *object,
535 : const char *name,
536 : struct json_object *value)
537 : {
538 7679994 : int ret = 0;
539 7679994 : json_t *jv = NULL;
540 :
541 7679994 : if (value != NULL && json_is_invalid(value)) {
542 0 : DBG_ERR("Invalid JSON object [%s] supplied\n", name);
543 0 : return JSON_ERROR;
544 : }
545 7679994 : if (json_is_invalid(object)) {
546 0 : DBG_ERR("Unable to add object [%s], target object is invalid\n",
547 : name);
548 0 : return JSON_ERROR;
549 : }
550 :
551 7679994 : jv = value == NULL ? json_null() : value->root;
552 :
553 7679994 : if (json_is_array(object->root)) {
554 2939367 : ret = json_array_append_new(object->root, jv);
555 4740627 : } else if (json_is_object(object->root)) {
556 4740627 : ret = json_object_set_new(object->root, name, jv);
557 : } else {
558 0 : DBG_ERR("Invalid JSON object type\n");
559 0 : ret = JSON_ERROR;
560 : }
561 7679994 : if (ret != 0) {
562 0 : DBG_ERR("Unable to add object [%s]\n", name);
563 : }
564 7679994 : 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 : */
585 1437141 : int json_add_stringn(struct json_object *object,
586 : const char *name,
587 : const char *value,
588 : const size_t len)
589 : {
590 :
591 1437141 : int ret = 0;
592 1437141 : if (json_is_invalid(object)) {
593 0 : DBG_ERR("Unable to add string [%s], target object is invalid\n",
594 : name);
595 0 : return JSON_ERROR;
596 : }
597 :
598 2874282 : if (value != NULL && len > 0) {
599 1437141 : json_t *string = NULL;
600 1437141 : char buffer[len+1];
601 :
602 1437141 : strncpy(buffer, value, len);
603 1437141 : buffer[len] = '\0';
604 :
605 1437141 : string = json_string(buffer);
606 1437141 : if (string == NULL) {
607 0 : DBG_ERR("Unable to add string [%s], "
608 : "could not create string object\n",
609 : name);
610 0 : return JSON_ERROR;
611 : }
612 1437141 : ret = json_object_set_new(object->root, name, string);
613 1437141 : if (ret != 0) {
614 0 : json_decref(string);
615 0 : DBG_ERR("Unable to add string [%s]\n", name);
616 0 : return ret;
617 : }
618 : } else {
619 0 : ret = json_object_set_new(object->root, name, json_null());
620 0 : if (ret != 0) {
621 0 : DBG_ERR("Unable to add null string [%s]\n", name);
622 0 : return ret;
623 : }
624 : }
625 1437141 : 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 : */
651 427920 : int json_add_version(struct json_object *object, int major, int minor)
652 : {
653 427920 : int ret = 0;
654 : struct json_object version;
655 :
656 427920 : if (json_is_invalid(object)) {
657 0 : DBG_ERR("Unable to add version, target object is invalid\n");
658 0 : return JSON_ERROR;
659 : }
660 :
661 427920 : version = json_new_object();
662 427920 : if (json_is_invalid(&version)) {
663 0 : DBG_ERR("Unable to add version, failed to create object\n");
664 0 : return JSON_ERROR;
665 : }
666 427920 : ret = json_add_int(&version, "major", major);
667 427920 : if (ret != 0) {
668 0 : json_free(&version);
669 0 : return ret;
670 : }
671 427920 : ret = json_add_int(&version, "minor", minor);
672 427920 : if (ret != 0) {
673 0 : json_free(&version);
674 0 : return ret;
675 : }
676 427920 : ret = json_add_object(object, "version", &version);
677 427920 : if (ret != 0) {
678 0 : json_free(&version);
679 0 : return ret;
680 : }
681 427920 : 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 : */
698 427920 : 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 427920 : if (json_is_invalid(object)) {
709 0 : DBG_ERR("Unable to add time stamp, target object is invalid\n");
710 0 : return JSON_ERROR;
711 : }
712 :
713 427920 : r = gettimeofday(&tv, NULL);
714 427920 : if (r) {
715 0 : DBG_ERR("Unable to get time of day: (%d) %s\n",
716 : errno,
717 : strerror(errno));
718 0 : return JSON_ERROR;
719 : }
720 :
721 427920 : tm_info = localtime(&tv.tv_sec);
722 427920 : if (tm_info == NULL) {
723 0 : DBG_ERR("Unable to determine local time\n");
724 0 : return JSON_ERROR;
725 : }
726 :
727 427920 : strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info);
728 427920 : strftime(tz, sizeof(tz)-1, "%z", tm_info);
729 427920 : snprintf(
730 : timestamp,
731 : sizeof(timestamp),
732 : "%s.%06ld%s",
733 : buffer,
734 : tv.tv_usec,
735 : tz);
736 427920 : ret = json_add_string(object, "timestamp", timestamp);
737 427920 : if (ret != 0) {
738 0 : DBG_ERR("Unable to add time stamp to JSON object\n");
739 : }
740 427920 : 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 : */
759 379452 : int json_add_address(struct json_object *object,
760 : const char *name,
761 : const struct tsocket_address *address)
762 : {
763 379452 : int ret = 0;
764 :
765 379452 : if (json_is_invalid(object)) {
766 0 : DBG_ERR("Unable to add address [%s], "
767 : "target object is invalid\n",
768 : name);
769 0 : return JSON_ERROR;
770 : }
771 :
772 379452 : if (address == NULL) {
773 171081 : ret = json_object_set_new(object->root, name, json_null());
774 171081 : if (ret != 0) {
775 0 : DBG_ERR("Unable to add null address [%s]\n", name);
776 0 : return JSON_ERROR;
777 : }
778 : } else {
779 208371 : TALLOC_CTX *ctx = talloc_new(NULL);
780 208371 : char *s = NULL;
781 :
782 208371 : if (ctx == NULL) {
783 0 : DBG_ERR("Out of memory adding address [%s]\n", name);
784 0 : return JSON_ERROR;
785 : }
786 :
787 208371 : s = tsocket_address_string(address, ctx);
788 208371 : if (s == NULL) {
789 0 : DBG_ERR("Out of memory adding address [%s]\n", name);
790 0 : TALLOC_FREE(ctx);
791 0 : return JSON_ERROR;
792 : }
793 208371 : ret = json_add_string(object, name, s);
794 208371 : if (ret != 0) {
795 0 : DBG_ERR(
796 : "Unable to add address [%s] value [%s]\n", name, s);
797 0 : TALLOC_FREE(ctx);
798 0 : return JSON_ERROR;
799 : }
800 208371 : TALLOC_FREE(ctx);
801 : }
802 379452 : 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 : */
821 356899 : int json_add_sid(struct json_object *object,
822 : const char *name,
823 : const struct dom_sid *sid)
824 : {
825 356899 : int ret = 0;
826 :
827 356899 : if (json_is_invalid(object)) {
828 0 : DBG_ERR("Unable to add SID [%s], "
829 : "target object is invalid\n",
830 : name);
831 0 : return JSON_ERROR;
832 : }
833 :
834 356899 : if (sid == NULL) {
835 22451 : ret = json_object_set_new(object->root, name, json_null());
836 22451 : if (ret != 0) {
837 0 : DBG_ERR("Unable to add null SID [%s]\n", name);
838 0 : return ret;
839 : }
840 : } else {
841 : struct dom_sid_buf sid_buf;
842 :
843 334448 : ret = json_add_string(
844 334448 : object, name, dom_sid_str_buf(sid, &sid_buf));
845 334448 : if (ret != 0) {
846 0 : DBG_ERR("Unable to add SID [%s] value [%s]\n",
847 : name,
848 : sid_buf.buf);
849 0 : return ret;
850 : }
851 : }
852 356899 : 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 : */
872 673444 : int json_add_guid(struct json_object *object,
873 : const char *name,
874 : const struct GUID *guid)
875 : {
876 :
877 673444 : int ret = 0;
878 :
879 673444 : if (json_is_invalid(object)) {
880 0 : DBG_ERR("Unable to add GUID [%s], "
881 : "target object is invalid\n",
882 : name);
883 0 : return JSON_ERROR;
884 : }
885 :
886 673444 : if (guid == NULL) {
887 3625 : ret = json_object_set_new(object->root, name, json_null());
888 3625 : if (ret != 0) {
889 0 : DBG_ERR("Unable to add null GUID [%s]\n", name);
890 0 : return ret;
891 : }
892 : } else {
893 : char *guid_str;
894 : struct GUID_txt_buf guid_buff;
895 :
896 669819 : guid_str = GUID_buf_string(guid, &guid_buff);
897 669819 : ret = json_add_string(object, name, guid_str);
898 669819 : if (ret != 0) {
899 0 : DBG_ERR("Unable to guid GUID [%s] value [%s]\n",
900 : name,
901 : guid_str);
902 0 : return ret;
903 : }
904 : }
905 673444 : return ret;
906 : }
907 :
908 : /*
909 : * @brief Replaces the object for a given key with a given json object.
910 : *
911 : * If key already exists, the value will be replaced. Otherwise the given
912 : * value will be added under the given key.
913 : *
914 : * @param object the JSON object to be updated.
915 : * @param key the key which will be updated.
916 : * @param new_obj the new value object to be inserted.
917 : *
918 : * @return 0 the operation was successful
919 : * -1 the operation failed (e.j. if one of the paramters is invalid)
920 : */
921 0 : int json_update_object(struct json_object *object,
922 : const char *key,
923 : struct json_object *new_obj)
924 : {
925 0 : int ret = 0;
926 :
927 0 : if (json_is_invalid(object)) {
928 0 : DBG_ERR("Unable to update key [%s], "
929 : "target object is invalid\n",
930 : key);
931 0 : return JSON_ERROR;
932 : }
933 0 : if (json_is_invalid(new_obj)) {
934 0 : DBG_ERR("Unable to update key [%s], "
935 : "new object is invalid\n",
936 : key);
937 0 : return JSON_ERROR;
938 : }
939 :
940 0 : if (key == NULL) {
941 0 : DBG_ERR("Unable to add null String as key\n");
942 0 : return JSON_ERROR;
943 : }
944 :
945 0 : ret = json_object_set(object->root, key, new_obj->root);
946 0 : if (ret != 0) {
947 0 : DBG_ERR("Unable to update object\n");
948 0 : return ret;
949 : }
950 :
951 0 : return ret;
952 : }
953 :
954 : /*
955 : * @brief Convert a JSON object into a string
956 : *
957 : * Convert the json object into a string suitable for printing on a log line,
958 : * i.e. with no embedded line breaks.
959 : *
960 : * If the object is invalid it logs an error and returns NULL.
961 : *
962 : * @param mem_ctx the talloc memory context owning the returned string
963 : * @param object the json object.
964 : *
965 : * @return A string representation of the object or NULL if the object
966 : * is invalid.
967 : */
968 428139 : char *json_to_string(TALLOC_CTX *mem_ctx, const struct json_object *object)
969 : {
970 428139 : char *json = NULL;
971 428139 : char *json_string = NULL;
972 :
973 428139 : if (json_is_invalid(object)) {
974 0 : DBG_ERR("Invalid JSON object, unable to convert to string\n");
975 0 : return NULL;
976 : }
977 :
978 428139 : if (object->root == NULL) {
979 0 : return NULL;
980 : }
981 :
982 : /*
983 : * json_dumps uses malloc, so need to call free(json) to release
984 : * the memory
985 : */
986 428139 : json = json_dumps(object->root, 0);
987 428139 : if (json == NULL) {
988 0 : DBG_ERR("Unable to convert JSON object to string\n");
989 0 : return NULL;
990 : }
991 :
992 428139 : json_string = talloc_strdup(mem_ctx, json);
993 428139 : if (json_string == NULL) {
994 0 : free(json);
995 0 : DBG_ERR("Unable to copy JSON object string to talloc string\n");
996 0 : return NULL;
997 : }
998 428139 : free(json);
999 :
1000 428139 : return json_string;
1001 : }
1002 :
1003 : /*
1004 : * @brief get a json array named "name" from the json object.
1005 : *
1006 : * Get the array attribute named name, creating it if it does not exist.
1007 : *
1008 : * @param object the json object.
1009 : * @param name the name of the array attribute
1010 : *
1011 : * @return The array object, will be created if it did not exist.
1012 : */
1013 1228849 : struct json_object json_get_array(struct json_object *object, const char *name)
1014 : {
1015 :
1016 1228849 : struct json_object array = json_empty_object;
1017 1228849 : json_t *a = NULL;
1018 1228849 : int ret = 0;
1019 :
1020 1228849 : if (json_is_invalid(object)) {
1021 0 : DBG_ERR("Invalid JSON object, unable to get array [%s]\n",
1022 : name);
1023 0 : json_free(&array);
1024 0 : return array;
1025 : }
1026 :
1027 1228849 : array = json_new_array();
1028 1228849 : if (json_is_invalid(&array)) {
1029 0 : DBG_ERR("Unable to create new array for [%s]\n", name);
1030 0 : return array;
1031 : }
1032 :
1033 1228849 : a = json_object_get(object->root, name);
1034 1228849 : if (a == NULL) {
1035 1185425 : return array;
1036 : }
1037 :
1038 43424 : ret = json_array_extend(array.root, a);
1039 43424 : if (ret != 0) {
1040 0 : DBG_ERR("Unable to get array [%s]\n", name);
1041 0 : json_free(&array);
1042 0 : return array;
1043 : }
1044 :
1045 43424 : return array;
1046 : }
1047 :
1048 : /*
1049 : * @brief get a json object named "name" from the json object.
1050 : *
1051 : * Get the object attribute named name, creating it if it does not exist.
1052 : *
1053 : * @param object the json object.
1054 : * @param name the name of the object attribute
1055 : *
1056 : * @return The object, will be created if it did not exist.
1057 : */
1058 1228849 : struct json_object json_get_object(struct json_object *object, const char *name)
1059 : {
1060 :
1061 1228849 : struct json_object o = json_new_object();
1062 1228849 : json_t *v = NULL;
1063 1228849 : int ret = 0;
1064 :
1065 1228849 : if (json_is_invalid(object)) {
1066 0 : DBG_ERR("Invalid JSON object, unable to get object [%s]\n",
1067 : name);
1068 0 : json_free(&o);
1069 0 : return o;
1070 : }
1071 :
1072 1228849 : v = json_object_get(object->root, name);
1073 1228849 : if (v == NULL) {
1074 1185425 : return o;
1075 : }
1076 43424 : ret = json_object_update(o.root, v);
1077 43424 : if (ret != 0) {
1078 0 : DBG_ERR("Unable to get object [%s]\n", name);
1079 0 : json_free(&o);
1080 0 : return o;
1081 : }
1082 43424 : return o;
1083 : }
1084 : #endif
|