json: add JSON_FORMAT_REFUSE_SENSITIVE to json_variant_format()

Returns -EPERM if any node in the variant is marked as sensitive,
useful to avoid leaking data to log messages and so on
This commit is contained in:
Luca Boccassi
2024-01-03 11:54:48 +01:00
parent caef0bc3dc
commit fa9a6db478
3 changed files with 143 additions and 11 deletions
+26
View File
@@ -1771,6 +1771,28 @@ static int json_format(FILE *f, JsonVariant *v, JsonFormatFlags flags, const cha
return 0;
}
static bool json_variant_is_sensitive_recursive(JsonVariant *v) {
if (!v)
return false;
if (json_variant_is_sensitive(v))
return true;
if (v == JSON_VARIANT_MAGIC_EMPTY_ARRAY ||
v == JSON_VARIANT_MAGIC_EMPTY_OBJECT)
return false;
if (!json_variant_is_regular(v))
return false;
if (!IN_SET(v->type, JSON_VARIANT_ARRAY, JSON_VARIANT_OBJECT))
return false;
if (v->is_reference)
return json_variant_is_sensitive_recursive(v->reference);
for (size_t i = 0; i < json_variant_elements(v); i++)
if (json_variant_is_sensitive_recursive(json_variant_by_index(v, i)))
return true;
return false;
}
int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) {
_cleanup_(memstream_done) MemStream m = {};
size_t sz;
@@ -1786,6 +1808,10 @@ int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) {
if (flags & JSON_FORMAT_OFF)
return -ENOEXEC;
if ((flags & JSON_FORMAT_REFUSE_SENSITIVE))
if (json_variant_is_sensitive_recursive(v))
return -EPERM;
f = memstream_init(&m);
if (!f)
return -ENOMEM;
+12 -11
View File
@@ -185,17 +185,18 @@ struct json_variant_foreach_state {
int json_variant_get_source(JsonVariant *v, const char **ret_source, unsigned *ret_line, unsigned *ret_column);
typedef enum JsonFormatFlags {
JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */
JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */
JSON_FORMAT_PRETTY_AUTO = 1 << 2, /* same, but only if connected to a tty (and JSON_FORMAT_NEWLINE otherwise) */
JSON_FORMAT_COLOR = 1 << 3, /* insert ANSI color sequences */
JSON_FORMAT_COLOR_AUTO = 1 << 4, /* insert ANSI color sequences if colors_enabled() says so */
JSON_FORMAT_SOURCE = 1 << 5, /* prefix with source filename/line/column */
JSON_FORMAT_SSE = 1 << 6, /* prefix/suffix with W3C server-sent events */
JSON_FORMAT_SEQ = 1 << 7, /* prefix/suffix with RFC 7464 application/json-seq */
JSON_FORMAT_FLUSH = 1 << 8, /* call fflush() after dumping JSON */
JSON_FORMAT_EMPTY_ARRAY = 1 << 9, /* output "[]" for empty input */
JSON_FORMAT_OFF = 1 << 10, /* make json_variant_format() fail with -ENOEXEC */
JSON_FORMAT_NEWLINE = 1 << 0, /* suffix with newline */
JSON_FORMAT_PRETTY = 1 << 1, /* add internal whitespace to appeal to human readers */
JSON_FORMAT_PRETTY_AUTO = 1 << 2, /* same, but only if connected to a tty (and JSON_FORMAT_NEWLINE otherwise) */
JSON_FORMAT_COLOR = 1 << 3, /* insert ANSI color sequences */
JSON_FORMAT_COLOR_AUTO = 1 << 4, /* insert ANSI color sequences if colors_enabled() says so */
JSON_FORMAT_SOURCE = 1 << 5, /* prefix with source filename/line/column */
JSON_FORMAT_SSE = 1 << 6, /* prefix/suffix with W3C server-sent events */
JSON_FORMAT_SEQ = 1 << 7, /* prefix/suffix with RFC 7464 application/json-seq */
JSON_FORMAT_FLUSH = 1 << 8, /* call fflush() after dumping JSON */
JSON_FORMAT_EMPTY_ARRAY = 1 << 9, /* output "[]" for empty input */
JSON_FORMAT_OFF = 1 << 10, /* make json_variant_format() fail with -ENOEXEC */
JSON_FORMAT_REFUSE_SENSITIVE = 1 << 11, /* return EPERM if any node in the tree is marked as senstitive */
} JsonFormatFlags;
int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret);