assert(link);
- json_variant_sensitive(parameters);
-
r = varlink_dispatch(link, parameters, dispatch_table, &p);
if (r != 0)
return r;
assert(link);
- /* Let's also mark the (theoretically encrypted) input as sensitive, in case the NULL encryption scheme was used. */
- json_variant_sensitive(parameters);
-
r = varlink_dispatch(link, parameters, dispatch_table, &p);
if (r != 0)
return r;
/* Invocation as Varlink service */
- r = varlink_server_new(&varlink_server, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
+ r = varlink_server_new(&varlink_server, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA|VARLINK_SERVER_INPUT_SENSITIVE);
if (r < 0)
return log_error_errno(r, "Failed to allocate Varlink server: %m");
bool allow_fd_passing_output:1;
bool output_buffer_sensitive:1; /* whether to erase the output buffer after writing it to the socket */
+ bool input_sensitive:1; /* Whether incoming messages might be sensitive */
int af; /* address family if socket; AF_UNSPEC if not socket; negative if not known */
varlink_clear_current(v);
- v->input_buffer = mfree(v->input_buffer);
+ v->input_buffer = v->input_sensitive ? erase_and_free(v->input_buffer) : mfree(v->input_buffer);
v->output_buffer = v->output_buffer_sensitive ? erase_and_free(v->output_buffer) : mfree(v->output_buffer);
v->input_control_buffer = mfree(v->input_control_buffer);
}
static int varlink_parse_message(Varlink *v) {
- const char *e, *begin;
+ const char *e;
+ char *begin;
size_t sz;
int r;
sz = e - begin + 1;
r = json_parse(begin, 0, &v->current, NULL, NULL);
+ if (v->input_sensitive)
+ explicit_bzero_safe(begin, sz);
if (r < 0) {
/* If we encounter a parse failure flush all data. We cannot possibly recover from this,
* hence drop all buffered data now. */
return varlink_log_errno(v, r, "Failed to parse JSON: %m");
}
+ if (v->input_sensitive) {
+ /* Mark the parameters subfield as sensitive right-away, if that's requested */
+ JsonVariant *parameters = json_variant_by_key(v->current, "parameters");
+ if (parameters)
+ json_variant_sensitive(parameters);
+ }
+
v->input_buffer_size -= sz;
if (v->input_buffer_size == 0)
return 0;
}
+int varlink_set_input_sensitive(Varlink *v) {
+ assert_return(v, -EINVAL);
+
+ v->input_sensitive = true;
+ return 0;
+}
+
int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags) {
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
int r;
TAKE_FD(cfd);
+ if (FLAGS_SET(ss->server->flags, VARLINK_SERVER_INPUT_SENSITIVE))
+ varlink_set_input_sensitive(v);
+
if (ss->server->connect_callback) {
r = ss->server->connect_callback(ss->server, v, ss->server->userdata);
if (r < 0) {
VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */
VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */
VARLINK_SERVER_INHERIT_USERDATA = 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */
- _VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1,
+ VARLINK_SERVER_INPUT_SENSITIVE = 1 << 4, /* Automatically mark al connection input as sensitive */
+ _VARLINK_SERVER_FLAGS_ALL = (1 << 5) - 1,
} VarlinkServerFlags;
typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata);
int varlink_set_description(Varlink *v, const char *d);
+/* Automatically mark the parameters part of incoming messages as security sensitive */
+int varlink_set_input_sensitive(Varlink *v);
+
/* Create a varlink server */
int varlink_server_new(VarlinkServer **ret, VarlinkServerFlags flags);
VarlinkServer *varlink_server_ref(VarlinkServer *s);