]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-convenience.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-convenience.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
992c052c
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include "bus-internal.h"
22#include "bus-message.h"
23#include "bus-signature.h"
e5609878 24#include "bus-type.h"
07630cea
LP
25#include "bus-util.h"
26#include "string-util.h"
992c052c 27
d9f644e2 28_public_ int sd_bus_emit_signal(
992c052c
LP
29 sd_bus *bus,
30 const char *path,
31 const char *interface,
32 const char *member,
33 const char *types, ...) {
34
4afd3348 35 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
992c052c
LP
36 int r;
37
f69dc9a3 38 assert_return(bus, -EINVAL);
f69dc9a3 39 assert_return(!bus_pid_changed(bus), -ECHILD);
992c052c 40
a3d59cd1
LP
41 if (!BUS_IS_OPEN(bus->state))
42 return -ENOTCONN;
43
151b9b96 44 r = sd_bus_message_new_signal(bus, &m, path, interface, member);
992c052c
LP
45 if (r < 0)
46 return r;
47
48 if (!isempty(types)) {
49 va_list ap;
50
51 va_start(ap, types);
19fe49f6 52 r = sd_bus_message_appendv(m, types, ap);
992c052c
LP
53 va_end(ap);
54 if (r < 0)
55 return r;
56 }
57
58 return sd_bus_send(bus, m, NULL);
59}
60
5d941c92
UTL
61_public_ int sd_bus_call_method_async(
62 sd_bus *bus,
63 sd_bus_slot **slot,
64 const char *destination,
65 const char *path,
66 const char *interface,
67 const char *member,
68 sd_bus_message_handler_t callback,
69 void *userdata,
70 const char *types, ...) {
71
4afd3348 72 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
5d941c92
UTL
73 int r;
74
75 assert_return(bus, -EINVAL);
76 assert_return(!bus_pid_changed(bus), -ECHILD);
77
78 if (!BUS_IS_OPEN(bus->state))
79 return -ENOTCONN;
80
81 r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
82 if (r < 0)
83 return r;
84
85 if (!isempty(types)) {
86 va_list ap;
87
88 va_start(ap, types);
19fe49f6 89 r = sd_bus_message_appendv(m, types, ap);
5d941c92
UTL
90 va_end(ap);
91 if (r < 0)
92 return r;
93 }
94
95 return sd_bus_call_async(bus, slot, m, callback, userdata, 0);
96}
97
d9f644e2 98_public_ int sd_bus_call_method(
992c052c
LP
99 sd_bus *bus,
100 const char *destination,
101 const char *path,
102 const char *interface,
103 const char *member,
104 sd_bus_error *error,
105 sd_bus_message **reply,
106 const char *types, ...) {
107
4afd3348 108 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
992c052c
LP
109 int r;
110
759e02e7
LP
111 bus_assert_return(bus, -EINVAL, error);
112 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
992c052c 113
759e02e7
LP
114 if (!BUS_IS_OPEN(bus->state)) {
115 r = -ENOTCONN;
116 goto fail;
117 }
a3d59cd1 118
151b9b96 119 r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
992c052c 120 if (r < 0)
759e02e7 121 goto fail;
992c052c
LP
122
123 if (!isempty(types)) {
124 va_list ap;
125
126 va_start(ap, types);
19fe49f6 127 r = sd_bus_message_appendv(m, types, ap);
992c052c
LP
128 va_end(ap);
129 if (r < 0)
759e02e7 130 goto fail;
992c052c
LP
131 }
132
c49b30a2 133 return sd_bus_call(bus, m, 0, error, reply);
759e02e7
LP
134
135fail:
136 return sd_bus_error_set_errno(error, r);
992c052c
LP
137}
138
d9f644e2 139_public_ int sd_bus_reply_method_return(
992c052c
LP
140 sd_bus_message *call,
141 const char *types, ...) {
142
4afd3348 143 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
992c052c
LP
144 int r;
145
f69dc9a3
LP
146 assert_return(call, -EINVAL);
147 assert_return(call->sealed, -EPERM);
40ca29a1 148 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
a3d59cd1 149 assert_return(call->bus, -EINVAL);
df2d202e 150 assert_return(!bus_pid_changed(call->bus), -ECHILD);
992c052c 151
a3d59cd1
LP
152 if (!BUS_IS_OPEN(call->bus->state))
153 return -ENOTCONN;
154
0461f8cd 155 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
992c052c
LP
156 return 0;
157
df2d202e 158 r = sd_bus_message_new_method_return(call, &m);
992c052c
LP
159 if (r < 0)
160 return r;
161
162 if (!isempty(types)) {
163 va_list ap;
164
165 va_start(ap, types);
19fe49f6 166 r = sd_bus_message_appendv(m, types, ap);
992c052c
LP
167 va_end(ap);
168 if (r < 0)
169 return r;
170 }
171
df2d202e 172 return sd_bus_send(call->bus, m, NULL);
992c052c
LP
173}
174
d9f644e2 175_public_ int sd_bus_reply_method_error(
992c052c
LP
176 sd_bus_message *call,
177 const sd_bus_error *e) {
178
4afd3348 179 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
992c052c
LP
180 int r;
181
f69dc9a3
LP
182 assert_return(call, -EINVAL);
183 assert_return(call->sealed, -EPERM);
40ca29a1 184 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
f69dc9a3 185 assert_return(sd_bus_error_is_set(e), -EINVAL);
a3d59cd1 186 assert_return(call->bus, -EINVAL);
df2d202e 187 assert_return(!bus_pid_changed(call->bus), -ECHILD);
992c052c 188
a3d59cd1
LP
189 if (!BUS_IS_OPEN(call->bus->state))
190 return -ENOTCONN;
191
0461f8cd 192 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
992c052c
LP
193 return 0;
194
151b9b96 195 r = sd_bus_message_new_method_error(call, &m, e);
992c052c
LP
196 if (r < 0)
197 return r;
198
df2d202e 199 return sd_bus_send(call->bus, m, NULL);
992c052c
LP
200}
201
d9f644e2 202_public_ int sd_bus_reply_method_errorf(
992c052c
LP
203 sd_bus_message *call,
204 const char *name,
205 const char *format,
206 ...) {
207
4afd3348 208 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
992c052c 209 va_list ap;
992c052c 210
f69dc9a3
LP
211 assert_return(call, -EINVAL);
212 assert_return(call->sealed, -EPERM);
40ca29a1 213 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
a3d59cd1 214 assert_return(call->bus, -EINVAL);
df2d202e 215 assert_return(!bus_pid_changed(call->bus), -ECHILD);
f69dc9a3 216
a3d59cd1
LP
217 if (!BUS_IS_OPEN(call->bus->state))
218 return -ENOTCONN;
219
0461f8cd 220 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
f69dc9a3
LP
221 return 0;
222
40ca29a1 223 va_start(ap, format);
780896a4 224 bus_error_setfv(&error, name, format, ap);
40ca29a1 225 va_end(ap);
992c052c 226
df2d202e 227 return sd_bus_reply_method_error(call, &error);
40ca29a1 228}
992c052c 229
d9f644e2 230_public_ int sd_bus_reply_method_errno(
40ca29a1
LP
231 sd_bus_message *call,
232 int error,
233 const sd_bus_error *p) {
992c052c 234
4afd3348 235 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
40ca29a1 236
40ca29a1
LP
237 assert_return(call, -EINVAL);
238 assert_return(call->sealed, -EPERM);
239 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
a3d59cd1 240 assert_return(call->bus, -EINVAL);
df2d202e 241 assert_return(!bus_pid_changed(call->bus), -ECHILD);
40ca29a1 242
a3d59cd1
LP
243 if (!BUS_IS_OPEN(call->bus->state))
244 return -ENOTCONN;
245
0461f8cd 246 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
40ca29a1
LP
247 return 0;
248
249 if (sd_bus_error_is_set(p))
df2d202e 250 return sd_bus_reply_method_error(call, p);
40ca29a1
LP
251
252 sd_bus_error_set_errno(&berror, error);
253
df2d202e 254 return sd_bus_reply_method_error(call, &berror);
40ca29a1
LP
255}
256
d9f644e2 257_public_ int sd_bus_reply_method_errnof(
40ca29a1
LP
258 sd_bus_message *call,
259 int error,
260 const char *format,
261 ...) {
262
4afd3348 263 _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
40ca29a1
LP
264 va_list ap;
265
40ca29a1
LP
266 assert_return(call, -EINVAL);
267 assert_return(call->sealed, -EPERM);
268 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
a3d59cd1 269 assert_return(call->bus, -EINVAL);
df2d202e 270 assert_return(!bus_pid_changed(call->bus), -ECHILD);
40ca29a1 271
a3d59cd1
LP
272 if (!BUS_IS_OPEN(call->bus->state))
273 return -ENOTCONN;
274
0461f8cd 275 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
40ca29a1
LP
276 return 0;
277
278 va_start(ap, format);
07a0d22f 279 sd_bus_error_set_errnofv(&berror, error, format, ap);
40ca29a1
LP
280 va_end(ap);
281
df2d202e 282 return sd_bus_reply_method_error(call, &berror);
992c052c
LP
283}
284
d9f644e2 285_public_ int sd_bus_get_property(
992c052c
LP
286 sd_bus *bus,
287 const char *destination,
288 const char *path,
289 const char *interface,
290 const char *member,
291 sd_bus_error *error,
292 sd_bus_message **reply,
293 const char *type) {
294
295 sd_bus_message *rep = NULL;
296 int r;
297
759e02e7
LP
298 bus_assert_return(bus, -EINVAL, error);
299 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
300 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
301 bus_assert_return(reply, -EINVAL, error);
302 bus_assert_return(signature_is_single(type, false), -EINVAL, error);
303 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
992c052c 304
759e02e7
LP
305 if (!BUS_IS_OPEN(bus->state)) {
306 r = -ENOTCONN;
307 goto fail;
308 }
a3d59cd1 309
992c052c
LP
310 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
311 if (r < 0)
312 return r;
313
314 r = sd_bus_message_enter_container(rep, 'v', type);
315 if (r < 0) {
316 sd_bus_message_unref(rep);
759e02e7 317 goto fail;
992c052c
LP
318 }
319
320 *reply = rep;
321 return 0;
759e02e7
LP
322
323fail:
324 return sd_bus_error_set_errno(error, r);
992c052c
LP
325}
326
d9f644e2 327_public_ int sd_bus_get_property_trivial(
e5609878
LP
328 sd_bus *bus,
329 const char *destination,
330 const char *path,
331 const char *interface,
332 const char *member,
333 sd_bus_error *error,
334 char type, void *ptr) {
335
4afd3348 336 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
e5609878
LP
337 int r;
338
759e02e7
LP
339 bus_assert_return(bus, -EINVAL, error);
340 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
341 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
342 bus_assert_return(bus_type_is_trivial(type), -EINVAL, error);
343 bus_assert_return(ptr, -EINVAL, error);
344 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
e5609878 345
759e02e7
LP
346 if (!BUS_IS_OPEN(bus->state)) {
347 r = -ENOTCONN;
348 goto fail;
349 }
a3d59cd1 350
e5609878
LP
351 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
352 if (r < 0)
353 return r;
354
355 r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
356 if (r < 0)
759e02e7 357 goto fail;
e5609878
LP
358
359 r = sd_bus_message_read_basic(reply, type, ptr);
360 if (r < 0)
759e02e7 361 goto fail;
e5609878
LP
362
363 return 0;
759e02e7
LP
364
365fail:
366 return sd_bus_error_set_errno(error, r);
e5609878
LP
367}
368
63be1989
LP
369_public_ int sd_bus_get_property_string(
370 sd_bus *bus,
371 const char *destination,
372 const char *path,
373 const char *interface,
374 const char *member,
375 sd_bus_error *error,
376 char **ret) {
377
4afd3348 378 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
63be1989
LP
379 const char *s;
380 char *n;
381 int r;
382
759e02e7
LP
383 bus_assert_return(bus, -EINVAL, error);
384 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
385 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
386 bus_assert_return(ret, -EINVAL, error);
387 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
63be1989 388
759e02e7
LP
389 if (!BUS_IS_OPEN(bus->state)) {
390 r = -ENOTCONN;
391 goto fail;
392 }
a3d59cd1 393
63be1989
LP
394 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
395 if (r < 0)
396 return r;
397
398 r = sd_bus_message_enter_container(reply, 'v', "s");
399 if (r < 0)
759e02e7 400 goto fail;
63be1989
LP
401
402 r = sd_bus_message_read_basic(reply, 's', &s);
403 if (r < 0)
759e02e7 404 goto fail;
63be1989
LP
405
406 n = strdup(s);
759e02e7
LP
407 if (!n) {
408 r = -ENOMEM;
409 goto fail;
410 }
63be1989
LP
411
412 *ret = n;
413 return 0;
759e02e7
LP
414
415fail:
416 return sd_bus_error_set_errno(error, r);
63be1989
LP
417}
418
419_public_ int sd_bus_get_property_strv(
420 sd_bus *bus,
421 const char *destination,
422 const char *path,
423 const char *interface,
424 const char *member,
425 sd_bus_error *error,
426 char ***ret) {
427
4afd3348 428 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
63be1989
LP
429 int r;
430
759e02e7
LP
431 bus_assert_return(bus, -EINVAL, error);
432 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
433 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
434 bus_assert_return(ret, -EINVAL, error);
435 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
63be1989 436
759e02e7
LP
437 if (!BUS_IS_OPEN(bus->state)) {
438 r = -ENOTCONN;
439 goto fail;
440 }
a3d59cd1 441
63be1989
LP
442 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
443 if (r < 0)
444 return r;
445
446 r = sd_bus_message_enter_container(reply, 'v', NULL);
447 if (r < 0)
759e02e7 448 goto fail;
63be1989
LP
449
450 r = sd_bus_message_read_strv(reply, ret);
451 if (r < 0)
759e02e7 452 goto fail;
63be1989
LP
453
454 return 0;
759e02e7
LP
455
456fail:
457 return sd_bus_error_set_errno(error, r);
63be1989
LP
458}
459
d9f644e2 460_public_ int sd_bus_set_property(
992c052c
LP
461 sd_bus *bus,
462 const char *destination,
463 const char *path,
464 const char *interface,
465 const char *member,
466 sd_bus_error *error,
467 const char *type, ...) {
468
4afd3348 469 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
992c052c
LP
470 va_list ap;
471 int r;
472
759e02e7
LP
473 bus_assert_return(bus, -EINVAL, error);
474 bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
475 bus_assert_return(member_name_is_valid(member), -EINVAL, error);
476 bus_assert_return(signature_is_single(type, false), -EINVAL, error);
477 bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
992c052c 478
759e02e7
LP
479 if (!BUS_IS_OPEN(bus->state)) {
480 r = -ENOTCONN;
481 goto fail;
482 }
a3d59cd1 483
151b9b96 484 r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
992c052c 485 if (r < 0)
759e02e7 486 goto fail;
992c052c
LP
487
488 r = sd_bus_message_append(m, "ss", strempty(interface), member);
489 if (r < 0)
759e02e7 490 goto fail;
992c052c
LP
491
492 r = sd_bus_message_open_container(m, 'v', type);
493 if (r < 0)
759e02e7 494 goto fail;
992c052c
LP
495
496 va_start(ap, type);
19fe49f6 497 r = sd_bus_message_appendv(m, type, ap);
992c052c
LP
498 va_end(ap);
499 if (r < 0)
759e02e7 500 goto fail;
992c052c
LP
501
502 r = sd_bus_message_close_container(m);
503 if (r < 0)
759e02e7 504 goto fail;
992c052c 505
c49b30a2 506 return sd_bus_call(bus, m, 0, error, NULL);
759e02e7
LP
507
508fail:
509 return sd_bus_error_set_errno(error, r);
992c052c 510}
5b12334d
LP
511
512_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
513 sd_bus_creds *c;
514
515 assert_return(call, -EINVAL);
516 assert_return(call->sealed, -EPERM);
a3d59cd1 517 assert_return(call->bus, -EINVAL);
5b12334d
LP
518 assert_return(!bus_pid_changed(call->bus), -ECHILD);
519
a3d59cd1
LP
520 if (!BUS_IS_OPEN(call->bus->state))
521 return -ENOTCONN;
522
5b12334d
LP
523 c = sd_bus_message_get_creds(call);
524
525 /* All data we need? */
526 if (c && (mask & ~c->mask) == 0) {
527 *creds = sd_bus_creds_ref(c);
528 return 0;
529 }
530
531 /* No data passed? Or not enough data passed to retrieve the missing bits? */
532 if (!c || !(c->mask & SD_BUS_CREDS_PID)) {
533 /* We couldn't read anything from the call, let's try
2d0c1561 534 * to get it from the sender or peer. */
5b12334d
LP
535
536 if (call->sender)
a132bef0 537 /* There's a sender, but the creds are missing. */
056f95d0 538 return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
5b12334d 539 else
a132bef0 540 /* There's no sender. For direct connections
2d0c1561 541 * the credentials of the AF_UNIX peer matter,
a132bef0 542 * which may be queried via sd_bus_get_owner_creds(). */
056f95d0 543 return sd_bus_get_owner_creds(call->bus, mask, creds);
5b12334d
LP
544 }
545
49b832c5 546 return bus_creds_extend_by_pid(c, mask, creds);
5b12334d 547}
def9a7aa
LP
548
549_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
4afd3348 550 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
def9a7aa 551 uid_t our_uid;
705a415f 552 bool know_caps = false;
def9a7aa
LP
553 int r;
554
555 assert_return(call, -EINVAL);
556 assert_return(call->sealed, -EPERM);
557 assert_return(call->bus, -EINVAL);
558 assert_return(!bus_pid_changed(call->bus), -ECHILD);
559
560 if (!BUS_IS_OPEN(call->bus->state))
561 return -ENOTCONN;
562
705a415f 563 if (capability >= 0) {
0f514420 564
705a415f 565 r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
def9a7aa
LP
566 if (r < 0)
567 return r;
568
0f514420
LP
569 /* We cannot use augmented caps for authorization,
570 * since then data is acquired raceful from
571 * /proc. This can never actually happen, but let's
572 * better be safe than sorry, and do an extra check
573 * here. */
574 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM);
575
def9a7aa
LP
576 r = sd_bus_creds_has_effective_cap(creds, capability);
577 if (r > 0)
578 return 1;
705a415f
LP
579 if (r == 0)
580 know_caps = true;
def9a7aa 581 } else {
705a415f 582 r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds);
def9a7aa
LP
583 if (r < 0)
584 return r;
585 }
586
587 /* Now, check the UID, but only if the capability check wasn't
588 * sufficient */
589 our_uid = getuid();
705a415f 590 if (our_uid != 0 || !know_caps || capability < 0) {
def9a7aa
LP
591 uid_t sender_uid;
592
0f514420
LP
593 /* We cannot use augmented uid/euid for authorization,
594 * since then data is acquired raceful from
595 * /proc. This can never actually happen, but let's
596 * better be safe than sorry, and do an extra check
597 * here. */
598 assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM);
599
705a415f
LP
600 /* Try to use the EUID, if we have it. */
601 r = sd_bus_creds_get_euid(creds, &sender_uid);
602 if (r < 0)
603 r = sd_bus_creds_get_uid(creds, &sender_uid);
604
def9a7aa
LP
605 if (r >= 0) {
606 /* Sender has same UID as us, then let's grant access */
607 if (sender_uid == our_uid)
608 return 1;
609
610 /* Sender is root, we are not root. */
611 if (our_uid != 0 && sender_uid == 0)
612 return 1;
613 }
614 }
615
616 return 0;
617}