]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-control.c
tests: fix build
[thirdparty/systemd.git] / src / libsystemd-bus / bus-control.c
CommitLineData
de1c301e
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
75722f1d
LP
22#ifdef HAVE_VALGRIND_MEMCHECK_H
23#include <valgrind/memcheck.h>
24#endif
25
de1c301e
LP
26#include <stddef.h>
27#include <errno.h>
28
29#include "strv.h"
de1c301e
LP
30#include "sd-bus.h"
31#include "bus-internal.h"
32#include "bus-message.h"
392d5b37 33#include "bus-control.h"
c7819669 34#include "bus-bloom.h"
40ca29a1 35#include "bus-util.h"
de1c301e 36
d9f644e2 37_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
20902f3e
LP
38 int r;
39
9bb058a1
LS
40 assert_return(bus, -EINVAL);
41 assert_return(unique, -EINVAL);
42 assert_return(!bus_pid_changed(bus), -ECHILD);
20902f3e
LP
43
44 r = bus_ensure_running(bus);
45 if (r < 0)
46 return r;
de1c301e 47
20902f3e
LP
48 *unique = bus->unique_name;
49 return 0;
de1c301e
LP
50}
51
29a07cdb 52static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
e7176abb
LP
53 struct kdbus_cmd_name *n;
54 size_t l;
de1c301e
LP
55 int r;
56
e7176abb
LP
57 assert(bus);
58 assert(name);
f08838da 59
e7176abb
LP
60 l = strlen(name);
61 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
62 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
63 kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
64 memcpy(n->name, name, l+1);
f08838da 65
75722f1d 66#ifdef HAVE_VALGRIND_MEMCHECK_H
e7176abb 67 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
75722f1d
LP
68#endif
69
e7176abb
LP
70 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
71 if (r < 0)
72 return -errno;
f08838da 73
e7176abb
LP
74 if (n->flags & KDBUS_NAME_IN_QUEUE)
75 return 0;
f08838da 76
e7176abb 77 return 1;
de1c301e
LP
78}
79
29a07cdb 80static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
d4100e24 81 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
29a07cdb 82 uint32_t ret, param = 0;
de1c301e
LP
83 int r;
84
e7176abb
LP
85 assert(bus);
86 assert(name);
87
29a07cdb
LP
88 if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
89 param |= BUS_NAME_ALLOW_REPLACEMENT;
90 if (flags & SD_BUS_NAME_REPLACE_EXISTING)
91 param |= BUS_NAME_REPLACE_EXISTING;
92 if (!(flags & SD_BUS_NAME_QUEUE))
93 param |= BUS_NAME_DO_NOT_QUEUE;
94
e7176abb
LP
95 r = sd_bus_call_method(
96 bus,
97 "org.freedesktop.DBus",
98 "/",
99 "org.freedesktop.DBus",
100 "RequestName",
101 NULL,
102 &reply,
103 "su",
104 name,
29a07cdb 105 param);
e7176abb
LP
106 if (r < 0)
107 return r;
108
109 r = sd_bus_message_read(reply, "u", &ret);
110 if (r < 0)
111 return r;
112
0461f8cd 113 if (ret == BUS_NAME_ALREADY_OWNER)
e7176abb 114 return -EALREADY;
0461f8cd 115 else if (ret == BUS_NAME_EXISTS)
e7176abb 116 return -EEXIST;
0461f8cd 117 else if (ret == BUS_NAME_IN_QUEUE)
e7176abb 118 return 0;
c0a09132
LP
119 else if (ret == BUS_NAME_PRIMARY_OWNER)
120 return 1;
e7176abb 121
c0a09132 122 return -EIO;
e7176abb
LP
123}
124
29a07cdb 125_public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
9bb058a1
LS
126 assert_return(bus, -EINVAL);
127 assert_return(name, -EINVAL);
128 assert_return(bus->bus_client, -EINVAL);
129 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
130 assert_return(!bus_pid_changed(bus), -ECHILD);
29a07cdb 131 assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
de1c301e 132
e7176abb
LP
133 if (bus->is_kernel)
134 return bus_request_name_kernel(bus, name, flags);
135 else
136 return bus_request_name_dbus1(bus, name, flags);
137}
f08838da 138
e7176abb
LP
139static int bus_release_name_kernel(sd_bus *bus, const char *name) {
140 struct kdbus_cmd_name *n;
141 size_t l;
142 int r;
f08838da 143
e7176abb
LP
144 assert(bus);
145 assert(name);
f08838da 146
e7176abb
LP
147 l = strlen(name);
148 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
149 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
150 memcpy(n->name, name, l+1);
f08838da 151
e7176abb
LP
152#ifdef HAVE_VALGRIND_MEMCHECK_H
153 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
154#endif
155 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
156 if (r < 0)
157 return -errno;
de1c301e 158
e7176abb 159 return n->flags;
de1c301e
LP
160}
161
e7176abb
LP
162static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
163 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
164 uint32_t ret;
de1c301e
LP
165 int r;
166
e7176abb
LP
167 assert(bus);
168 assert(name);
169
170 r = sd_bus_call_method(
171 bus,
172 "org.freedesktop.DBus",
173 "/",
174 "org.freedesktop.DBus",
175 "ReleaseName",
176 NULL,
177 &reply,
178 "s",
179 name);
180 if (r < 0)
181 return r;
182
183 r = sd_bus_message_read(reply, "u", &ret);
184 if (r < 0)
185 return r;
0461f8cd 186 if (ret == BUS_NAME_NON_EXISTENT)
043ccd83 187 return -ESRCH;
0461f8cd 188 if (ret == BUS_NAME_NOT_OWNER)
043ccd83 189 return -EADDRINUSE;
0461f8cd 190 if (ret == BUS_NAME_RELEASED)
e7176abb
LP
191 return 0;
192
193 return -EINVAL;
194}
195
196_public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
9bb058a1 197 assert_return(bus, -EINVAL);
e7176abb
LP
198 assert_return(name, -EINVAL);
199 assert_return(bus->bus_client, -EINVAL);
9bb058a1
LS
200 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
201 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 202
e7176abb
LP
203 if (bus->is_kernel)
204 return bus_release_name_kernel(bus, name);
205 else
206 return bus_release_name_dbus1(bus, name);
207}
de1c301e 208
71f2ab46
LP
209static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
210 struct kdbus_cmd_name_list cmd = {};
e7176abb
LP
211 struct kdbus_name_list *name_list;
212 struct kdbus_cmd_name *name;
7f7030e2 213 uint64_t previous_id = 0;
e7176abb 214 int r;
b1473984 215
71f2ab46 216 /* Caller will free half-constructed list on failure... */
b1473984 217
71f2ab46 218 cmd.flags = flags;
b1473984 219
71f2ab46 220 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
e7176abb
LP
221 if (r < 0)
222 return -errno;
b1473984 223
71f2ab46 224 name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
b6bd53c1 225
a8d4cac5 226 KDBUS_ITEM_FOREACH(name, name_list, names) {
b6bd53c1 227
7f7030e2 228 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->id != previous_id) {
71f2ab46
LP
229 char *n;
230
231 if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0)
232 return -ENOMEM;
233
234 r = strv_push(x, n);
235 if (r < 0) {
236 free(n);
237 return -ENOMEM;
238 }
7f7030e2
LP
239
240 previous_id = name->id;
71f2ab46 241 }
b1473984 242
7f7030e2
LP
243 if (name->size > sizeof(*name)) {
244 r = strv_extend(x, name->name);
245 if (r < 0)
246 return -ENOMEM;
247 }
89ffcd2a 248 }
de1c301e 249
71f2ab46 250 r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd.offset);
e7176abb
LP
251 if (r < 0)
252 return -errno;
253
de1c301e
LP
254 return 0;
255}
256
71f2ab46
LP
257static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
258 _cleanup_strv_free_ char **x = NULL, **y = NULL;
de1c301e
LP
259 int r;
260
71f2ab46
LP
261 if (acquired) {
262 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
263 if (r < 0)
264 return r;
265 }
a4297f08 266
71f2ab46 267 if (activatable) {
07442eff 268 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
71f2ab46
LP
269 if (r < 0)
270 return r;
5b12334d 271
71f2ab46
LP
272 *activatable = y;
273 y = NULL;
5b12334d 274 }
de1c301e 275
71f2ab46
LP
276 if (acquired) {
277 *acquired = x;
278 x = NULL;
279 }
280
281 return 0;
282}
283
284static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
285 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
286 _cleanup_strv_free_ char **x = NULL, **y = NULL;
287 int r;
288
289 if (acquired) {
290 r = sd_bus_call_method(
291 bus,
292 "org.freedesktop.DBus",
293 "/",
294 "org.freedesktop.DBus",
295 "ListNames",
296 NULL,
297 &reply,
298 NULL);
299 if (r < 0)
300 return r;
301
302 r = sd_bus_message_read_strv(reply, &x);
303 if (r < 0)
304 return r;
305
306 reply = sd_bus_message_unref(reply);
307 }
308
309 if (activatable) {
310 r = sd_bus_call_method(
311 bus,
312 "org.freedesktop.DBus",
313 "/",
314 "org.freedesktop.DBus",
315 "ListActivatableNames",
316 NULL,
317 &reply,
318 NULL);
319 if (r < 0)
320 return r;
321
322 r = sd_bus_message_read_strv(reply, &y);
323 if (r < 0)
324 return r;
325
326 *activatable = y;
327 y = NULL;
328 }
329
330 if (acquired) {
331 *acquired = x;
332 x = NULL;
a4297f08 333 }
de1c301e 334
49b832c5
LP
335 return 0;
336}
337
71f2ab46 338_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
e7176abb 339 assert_return(bus, -EINVAL);
71f2ab46 340 assert_return(acquired || activatable, -EINVAL);
e7176abb
LP
341 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
342 assert_return(!bus_pid_changed(bus), -ECHILD);
343
344 if (bus->is_kernel)
71f2ab46 345 return bus_list_names_kernel(bus, acquired, activatable);
e7176abb 346 else
71f2ab46 347 return bus_list_names_dbus1(bus, acquired, activatable);
e7176abb
LP
348}
349
49b832c5
LP
350static int bus_get_owner_kdbus(
351 sd_bus *bus,
352 const char *name,
353 uint64_t mask,
354 sd_bus_creds **creds) {
355
49b832c5 356 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
c85a5a24
DM
357 struct kdbus_cmd_conn_info *cmd;
358 struct kdbus_conn_info *conn_info;
49b832c5
LP
359 struct kdbus_item *item;
360 size_t size;
361 uint64_t m, id;
362 int r;
363
364 r = bus_kernel_parse_unique_name(name, &id);
365 if (r < 0)
366 return r;
367 if (r > 0) {
c85a5a24 368 size = offsetof(struct kdbus_cmd_conn_info, name);
49b832c5
LP
369 cmd = alloca0(size);
370 cmd->id = id;
371 } else {
c85a5a24 372 size = offsetof(struct kdbus_cmd_conn_info, name) + strlen(name) + 1;
49b832c5
LP
373 cmd = alloca0(size);
374 strcpy(cmd->name, name);
a4297f08 375 }
f7d85951 376 cmd->flags = KDBUS_ATTACH_NAMES;
de1c301e 377
49b832c5 378 cmd->size = size;
c85a5a24 379 r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
49b832c5
LP
380 if (r < 0)
381 return -errno;
382
c85a5a24 383 conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
49b832c5
LP
384
385 c = bus_creds_new();
386 if (!c)
387 return -ENOMEM;
388
389 if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
c85a5a24 390 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
49b832c5
LP
391 return -ENOMEM;
392
393 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
394 }
395
a8d4cac5 396 KDBUS_ITEM_FOREACH(item, conn_info, items) {
49b832c5
LP
397
398 switch (item->type) {
399
400 case KDBUS_ITEM_CREDS:
401 m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID |
402 SD_BUS_CREDS_TID | SD_BUS_CREDS_PID_STARTTIME) & mask;
403
404 if (m) {
405 c->uid = item->creds.uid;
406 c->pid = item->creds.pid;
407 c->gid = item->creds.gid;
408 c->tid = item->creds.tid;
409 c->pid_starttime = item->creds.starttime;
410 c->mask |= m;
411 }
412 break;
413
414 case KDBUS_ITEM_PID_COMM:
415 if (mask & SD_BUS_CREDS_COMM) {
416 c->comm = strdup(item->str);
417 if (!c->comm) {
418 r = -ENOMEM;
419 goto fail;
420 }
421
422 c->mask |= SD_BUS_CREDS_COMM;
423 }
424 break;
425
426 case KDBUS_ITEM_TID_COMM:
427 if (mask & SD_BUS_CREDS_TID_COMM) {
428 c->tid_comm = strdup(item->str);
429 if (!c->tid_comm) {
430 r = -ENOMEM;
431 goto fail;
432 }
433
434 c->mask |= SD_BUS_CREDS_TID_COMM;
435 }
436 break;
437
438 case KDBUS_ITEM_EXE:
439 if (mask & SD_BUS_CREDS_EXE) {
440 c->exe = strdup(item->str);
441 if (!c->exe) {
442 r = -ENOMEM;
443 goto fail;
444 }
445
446 c->mask |= SD_BUS_CREDS_EXE;
447 }
448 break;
449
450 case KDBUS_ITEM_CMDLINE:
451 if (mask & SD_BUS_CREDS_CMDLINE) {
a8d4cac5 452 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
49b832c5
LP
453 c->cmdline = memdup(item->data, c->cmdline_size);
454 if (!c->cmdline) {
455 r = -ENOMEM;
456 goto fail;
457 }
458
e7176abb
LP
459 c->mask |= SD_BUS_CREDS_CMDLINE;
460 }
461 break;
462
463 case KDBUS_ITEM_CGROUP:
464 m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
465 SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
466 SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
467
468 if (m) {
469 c->cgroup = strdup(item->str);
470 if (!c->cgroup) {
471 r = -ENOMEM;
472 goto fail;
473 }
474
475 c->mask |= m;
476 }
477 break;
478
479 case KDBUS_ITEM_CAPS:
480 m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
481 SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
482
483 if (m) {
a8d4cac5 484 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
e7176abb
LP
485 c->capability = memdup(item->data, c->capability_size);
486 if (!c->capability) {
487 r = -ENOMEM;
488 goto fail;
489 }
490
491 c->mask |= m;
492 }
493 break;
494
495 case KDBUS_ITEM_SECLABEL:
496 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
497 c->label = strdup(item->str);
498 if (!c->label) {
499 r = -ENOMEM;
500 goto fail;
501 }
502
503 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
504 }
505 break;
506
507 case KDBUS_ITEM_AUDIT:
508 m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
509
510 if (m) {
511 c->audit_session_id = item->audit.sessionid;
512 c->audit_login_uid = item->audit.loginuid;
513 c->mask |= m;
514 }
515 break;
516
65dae17a 517 case KDBUS_ITEM_NAME:
e7176abb 518 if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
65dae17a
KS
519 r = strv_extend(&c->well_known_names, item->name.name);
520 if (r < 0)
e7176abb 521 goto fail;
e7176abb
LP
522
523 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
524 }
525 break;
526 }
527 }
528
529 if (creds) {
530 *creds = c;
531 c = NULL;
532 }
533
534 r = 0;
535
536fail:
537 ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset);
538 return r;
539}
540
541static int bus_get_owner_dbus1(
542 sd_bus *bus,
543 const char *name,
544 uint64_t mask,
545 sd_bus_creds **creds) {
546
547 _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
548 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
549 const char *unique = NULL;
550 pid_t pid = 0;
551 int r;
552
553 /* Only query the owner if the caller wants to know it or if
554 * the caller just wants to check whether a name exists */
555 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
556 r = sd_bus_call_method(
557 bus,
558 "org.freedesktop.DBus",
559 "/",
560 "org.freedesktop.DBus",
561 "GetNameOwner",
562 NULL,
563 &reply_unique,
564 "s",
565 name);
566 if (r < 0)
567 return r;
568
569 r = sd_bus_message_read(reply_unique, "s", &unique);
570 if (r < 0)
571 return r;
572 }
573
574 if (mask != 0) {
575 c = bus_creds_new();
576 if (!c)
577 return -ENOMEM;
578
579 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
580 c->unique_name = strdup(unique);
581 if (!c->unique_name)
582 return -ENOMEM;
583
584 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
585 }
49b832c5 586
e7176abb
LP
587 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
588 SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
589 SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
590 SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
591 SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
592 uint32_t u;
49b832c5 593
e7176abb
LP
594 r = sd_bus_call_method(
595 bus,
596 "org.freedesktop.DBus",
597 "/",
598 "org.freedesktop.DBus",
599 "GetConnectionUnixProcessID",
600 NULL,
601 &reply,
602 "s",
603 unique ? unique : name);
604 if (r < 0)
605 return r;
49b832c5 606
e7176abb
LP
607 r = sd_bus_message_read(reply, "u", &u);
608 if (r < 0)
609 return r;
610
611 pid = u;
612 if (mask & SD_BUS_CREDS_PID) {
613 c->pid = u;
614 c->mask |= SD_BUS_CREDS_PID;
49b832c5 615 }
49b832c5 616
e7176abb
LP
617 reply = sd_bus_message_unref(reply);
618 }
49b832c5 619
e7176abb
LP
620 if (mask & SD_BUS_CREDS_UID) {
621 uint32_t u;
49b832c5 622
e7176abb
LP
623 r = sd_bus_call_method(
624 bus,
625 "org.freedesktop.DBus",
626 "/",
627 "org.freedesktop.DBus",
628 "GetConnectionUnixUser",
629 NULL,
630 &reply,
631 "s",
632 unique ? unique : name);
633 if (r < 0)
634 return r;
49b832c5 635
e7176abb
LP
636 r = sd_bus_message_read(reply, "u", &u);
637 if (r < 0)
638 return r;
49b832c5 639
e7176abb
LP
640 c->uid = u;
641 c->mask |= SD_BUS_CREDS_UID;
49b832c5 642
e7176abb
LP
643 reply = sd_bus_message_unref(reply);
644 }
49b832c5 645
e7176abb
LP
646 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
647 const void *p;
648 size_t sz;
49b832c5 649
e7176abb
LP
650 r = sd_bus_call_method(
651 bus,
652 "org.freedesktop.DBus",
653 "/",
654 "org.freedesktop.DBus",
655 "GetConnectionSELinuxSecurityContext",
656 NULL,
657 &reply,
658 "s",
659 unique ? unique : name);
660 if (r < 0)
661 return r;
49b832c5 662
e7176abb
LP
663 r = sd_bus_message_read_array(reply, 'y', &p, &sz);
664 if (r < 0)
665 return r;
666
667 c->label = strndup(p, sz);
668 if (!c->label)
669 return -ENOMEM;
670
671 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
49b832c5 672 }
e7176abb
LP
673
674 r = bus_creds_add_more(c, mask, pid, 0);
675 if (r < 0)
676 return r;
49b832c5
LP
677 }
678
679 if (creds) {
680 *creds = c;
681 c = NULL;
682 }
683
e7176abb 684 return 0;
49b832c5
LP
685}
686
687_public_ int sd_bus_get_owner(
688 sd_bus *bus,
689 const char *name,
690 uint64_t mask,
691 sd_bus_creds **creds) {
692
693 assert_return(bus, -EINVAL);
694 assert_return(name, -EINVAL);
95c4fe82 695 assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
49b832c5
LP
696 assert_return(mask == 0 || creds, -EINVAL);
697 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
698 assert_return(!bus_pid_changed(bus), -ECHILD);
699
700 if (bus->is_kernel)
701 return bus_get_owner_kdbus(bus, name, mask, creds);
702 else
e7176abb 703 return bus_get_owner_dbus1(bus, name, mask, creds);
de1c301e
LP
704}
705
777d7a61
LP
706static int add_name_change_match(sd_bus *bus,
707 uint64_t cookie,
708 const char *name,
709 const char *old_owner,
710 const char *new_owner) {
711
712 uint64_t name_id = 0, old_owner_id = 0, new_owner_id = 0;
713 int is_name_id = -1, r;
714 struct kdbus_item *item;
715
716 assert(bus);
717
718 /* If we encounter a match that could match against
719 * NameOwnerChanged messages, then we need to create
720 * KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE} and
721 * KDBUS_MATCH_ID_{ADD,REMOVE} matches for it, possibly
722 * multiple if the match is underspecified.
723 *
724 * The NameOwnerChanged signals take three parameters with
725 * unique or well-known names, but only some forms actually
726 * exist:
727 *
728 * WELLKNOWN, "", UNIQUE → KDBUS_MATCH_NAME_ADD
729 * WELLKNOWN, UNIQUE, "" → KDBUS_MATCH_NAME_REMOVE
730 * WELLKNOWN, UNIQUE, UNIQUE → KDBUS_MATCH_NAME_CHANGE
731 * UNIQUE, "", UNIQUE → KDBUS_MATCH_ID_ADD
732 * UNIQUE, UNIQUE, "" → KDBUS_MATCH_ID_REMOVE
733 *
734 * For the latter two the two unique names must be identical.
735 *
736 * */
737
738 if (name) {
739 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
740 if (is_name_id < 0)
741 return 0;
742 }
743
33cb6e79 744 if (!isempty(old_owner)) {
777d7a61
LP
745 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
746 if (r < 0)
747 return 0;
748 if (r == 0)
749 return 0;
750 if (is_name_id > 0 && old_owner_id != name_id)
751 return 0;
752 }
753
33cb6e79 754 if (!isempty(new_owner)) {
777d7a61
LP
755 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
756 if (r < 0)
757 return r;
758 if (r == 0)
759 return 0;
760 if (is_name_id > 0 && new_owner_id != name_id)
761 return 0;
762 }
763
764 if (is_name_id <= 0) {
006a0b87 765 struct kdbus_cmd_match *m;
777d7a61
LP
766 size_t sz, l;
767
768 /* If the name argument is missing or is a well-known
769 * name, then add KDBUS_MATCH_NAME_{ADD,REMOVE,CHANGE}
770 * matches for it */
771
772 l = name ? strlen(name) : 0;
773
774 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
775 offsetof(struct kdbus_item, name_change) +
776 offsetof(struct kdbus_notify_name_change, name) +
777 l+1);
778
006a0b87
LP
779 m = alloca0(sz);
780 m->size = sz;
781 m->cookie = cookie;
782 m->src_id = KDBUS_SRC_ID_KERNEL;
777d7a61 783
006a0b87
LP
784 item = m->items;
785 item->size =
786 offsetof(struct kdbus_item, name_change) +
787 offsetof(struct kdbus_notify_name_change, name) +
788 l+1;
777d7a61 789
ceceaf09
DM
790 item->name_change.old.id = old_owner_id;
791 item->name_change.new.id = new_owner_id;
777d7a61 792
006a0b87
LP
793 if (name)
794 strcpy(item->name_change.name, name);
777d7a61 795
006a0b87
LP
796 /* If the old name is unset or empty, then
797 * this can match against added names */
798 if (!old_owner || old_owner[0] == 0) {
799 item->type = KDBUS_MATCH_NAME_ADD;
777d7a61 800
006a0b87
LP
801 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
802 if (r < 0)
803 return -errno;
804 }
777d7a61 805
006a0b87
LP
806 /* If the new name is unset or empty, then
807 * this can match against removed names */
808 if (!new_owner || new_owner[0] == 0) {
809 item->type = KDBUS_MATCH_NAME_REMOVE;
777d7a61 810
006a0b87
LP
811 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
812 if (r < 0)
813 return -errno;
814 }
777d7a61 815
006a0b87
LP
816 /* If the neither name is explicitly set to
817 * the empty string, then this can match
818 * agains changed names */
819 if (!(old_owner && old_owner[0] == 0) &&
820 !(new_owner && new_owner[0] == 0)) {
821 item->type = KDBUS_MATCH_NAME_CHANGE;
777d7a61 822
006a0b87
LP
823 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
824 if (r < 0)
825 return -errno;
777d7a61
LP
826 }
827 }
828
829 if (is_name_id != 0) {
006a0b87
LP
830 struct kdbus_cmd_match *m;
831 uint64_t sz;
777d7a61
LP
832
833 /* If the name argument is missing or is a unique
834 * name, then add KDBUS_MATCH_ID_{ADD,REMOVE} matches
835 * for it */
836
006a0b87
LP
837 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
838 offsetof(struct kdbus_item, id_change) +
839 sizeof(struct kdbus_notify_id_change));
777d7a61 840
006a0b87
LP
841 m = alloca0(sz);
842 m->size = sz;
843 m->cookie = cookie;
844 m->src_id = KDBUS_SRC_ID_KERNEL;
777d7a61 845
006a0b87 846 item = m->items;
777d7a61
LP
847 item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change);
848 item->id_change.id = name_id;
849
850 /* If the old name is unset or empty, then this can
851 * match against added ids */
852 if (!old_owner || old_owner[0] == 0) {
853 item->type = KDBUS_MATCH_ID_ADD;
854
855 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
856 if (r < 0)
857 return -errno;
858 }
859
860 /* If thew new name is unset or empty, then this can
861 match against removed ids */
862 if (!new_owner || new_owner[0] == 0) {
863 item->type = KDBUS_MATCH_ID_REMOVE;
864
865 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
866 if (r < 0)
867 return -errno;
868 }
869 }
870
871 return 0;
872}
873
e7176abb 874static int bus_add_match_internal_kernel(
c7819669
LP
875 sd_bus *bus,
876 const char *match,
877 struct bus_match_component *components,
878 unsigned n_components,
879 uint64_t cookie) {
880
e7176abb
LP
881 struct kdbus_cmd_match *m;
882 struct kdbus_item *item;
883 uint64_t bloom[BLOOM_SIZE/8];
884 size_t sz;
885 const char *sender = NULL;
886 size_t sender_length = 0;
887 uint64_t src_id = KDBUS_MATCH_SRC_ID_ANY;
888 bool using_bloom = false;
889 unsigned i;
890 bool matches_name_change = true;
891 const char *name_change_arg[3] = {};
c7819669
LP
892 int r;
893
392d5b37
LP
894 assert(bus);
895 assert(match);
de1c301e 896
e7176abb 897 zero(bloom);
c7819669 898
e7176abb 899 sz = offsetof(struct kdbus_cmd_match, items);
c7819669 900
e7176abb
LP
901 for (i = 0; i < n_components; i++) {
902 struct bus_match_component *c = &components[i];
777d7a61 903
e7176abb 904 switch (c->type) {
c7819669 905
e7176abb
LP
906 case BUS_MATCH_SENDER:
907 if (!streq(c->value_str, "org.freedesktop.DBus"))
908 matches_name_change = false;
777d7a61 909
e7176abb
LP
910 r = bus_kernel_parse_unique_name(c->value_str, &src_id);
911 if (r < 0)
912 return r;
c7819669 913
e7176abb
LP
914 if (r > 0) {
915 sender = c->value_str;
916 sender_length = strlen(sender);
917 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
918 }
777d7a61 919
e7176abb 920 break;
c7819669 921
e7176abb
LP
922 case BUS_MATCH_MESSAGE_TYPE:
923 if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
924 matches_name_change = false;
777d7a61 925
e7176abb
LP
926 bloom_add_pair(bloom, "message-type", bus_message_type_to_string(c->value_u8));
927 using_bloom = true;
928 break;
c7819669 929
e7176abb
LP
930 case BUS_MATCH_INTERFACE:
931 if (!streq(c->value_str, "org.freedesktop.DBus"))
932 matches_name_change = false;
c7819669 933
e7176abb
LP
934 bloom_add_pair(bloom, "interface", c->value_str);
935 using_bloom = true;
936 break;
86312ab8 937
e7176abb
LP
938 case BUS_MATCH_MEMBER:
939 if (!streq(c->value_str, "NameOwnerChanged"))
940 matches_name_change = false;
777d7a61 941
e7176abb
LP
942 bloom_add_pair(bloom, "member", c->value_str);
943 using_bloom = true;
944 break;
86312ab8 945
e7176abb
LP
946 case BUS_MATCH_PATH:
947 if (!streq(c->value_str, "/org/freedesktop/DBus"))
948 matches_name_change = false;
86312ab8 949
e7176abb
LP
950 bloom_add_pair(bloom, "path", c->value_str);
951 using_bloom = true;
952 break;
953
954 case BUS_MATCH_PATH_NAMESPACE:
955 if (!streq(c->value_str, "/")) {
956 bloom_add_pair(bloom, "path-slash-prefix", c->value_str);
86312ab8 957 using_bloom = true;
86312ab8 958 }
e7176abb 959 break;
86312ab8 960
e7176abb
LP
961 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
962 char buf[sizeof("arg")-1 + 2 + 1];
86312ab8 963
e7176abb
LP
964 if (c->type - BUS_MATCH_ARG < 3)
965 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
86312ab8 966
e7176abb
LP
967 snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
968 bloom_add_pair(bloom, buf, c->value_str);
969 using_bloom = true;
970 break;
c7819669
LP
971 }
972
e7176abb
LP
973 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
974 char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
c7819669 975
e7176abb
LP
976 snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
977 bloom_add_pair(bloom, buf, c->value_str);
978 using_bloom = true;
979 break;
980 }
c7819669 981
e7176abb
LP
982 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
983 char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
c7819669 984
e7176abb
LP
985 snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
986 bloom_add_pair(bloom, buf, c->value_str);
987 using_bloom = true;
988 break;
c7819669
LP
989 }
990
e7176abb
LP
991 case BUS_MATCH_DESTINATION:
992 /* The bloom filter does not include
993 the destination, since it is only
994 available for broadcast messages
995 which do not carry a destination
996 since they are undirected. */
997 break;
998
999 case BUS_MATCH_ROOT:
1000 case BUS_MATCH_VALUE:
1001 case BUS_MATCH_LEAF:
1002 case _BUS_MATCH_NODE_TYPE_MAX:
1003 case _BUS_MATCH_NODE_TYPE_INVALID:
1004 assert_not_reached("Invalid match type?");
c7819669 1005 }
e7176abb
LP
1006 }
1007
1008 if (using_bloom)
1009 sz += ALIGN8(offsetof(struct kdbus_item, data64) + BLOOM_SIZE);
1010
1011 m = alloca0(sz);
1012 m->size = sz;
1013 m->cookie = cookie;
1014 m->src_id = src_id;
1015
1016 item = m->items;
1017
1018 if (using_bloom) {
1019 item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE;
1020 item->type = KDBUS_MATCH_BLOOM;
1021 memcpy(item->data64, bloom, BLOOM_SIZE);
1022
a8d4cac5 1023 item = KDBUS_ITEM_NEXT(item);
e7176abb
LP
1024 }
1025
1026 if (sender) {
1027 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1028 item->type = KDBUS_MATCH_SRC_NAME;
1029 memcpy(item->str, sender, sender_length + 1);
1030 }
1031
1032 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1033 if (r < 0)
1034 return -errno;
1035
1036 if (matches_name_change) {
1037
1038 /* If this match could theoretically match
1039 * NameOwnerChanged messages, we need to
1040 * install a second non-bloom filter explitly
1041 * for it */
c7819669 1042
e7176abb 1043 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
c7819669 1044 if (r < 0)
e7176abb
LP
1045 return r;
1046 }
c7819669 1047
e7176abb
LP
1048 return 0;
1049}
777d7a61 1050
e7176abb
LP
1051static int bus_add_match_internal_dbus1(
1052 sd_bus *bus,
1053 const char *match) {
777d7a61 1054
e7176abb
LP
1055 assert(bus);
1056 assert(match);
777d7a61 1057
e7176abb
LP
1058 return sd_bus_call_method(
1059 bus,
1060 "org.freedesktop.DBus",
1061 "/",
1062 "org.freedesktop.DBus",
1063 "AddMatch",
1064 NULL,
1065 NULL,
1066 "s",
1067 match);
de1c301e
LP
1068}
1069
e7176abb
LP
1070int bus_add_match_internal(
1071 sd_bus *bus,
1072 const char *match,
1073 struct bus_match_component *components,
1074 unsigned n_components,
1075 uint64_t cookie) {
1076
1077 assert(bus);
1078 assert(match);
1079
1080 if (bus->is_kernel)
1081 return bus_add_match_internal_kernel(bus, match, components, n_components, cookie);
1082 else
1083 return bus_add_match_internal_dbus1(bus, match);
1084}
1085
1086static int bus_remove_match_internal_kernel(
c7819669
LP
1087 sd_bus *bus,
1088 const char *match,
1089 uint64_t cookie) {
1090
e7176abb 1091 struct kdbus_cmd_match m;
c7819669
LP
1092 int r;
1093
392d5b37
LP
1094 assert(bus);
1095 assert(match);
de1c301e 1096
e7176abb
LP
1097 zero(m);
1098 m.size = offsetof(struct kdbus_cmd_match, items);
1099 m.cookie = cookie;
c7819669 1100
e7176abb
LP
1101 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1102 if (r < 0)
1103 return -errno;
c7819669 1104
e7176abb
LP
1105 return 0;
1106}
c7819669 1107
e7176abb
LP
1108static int bus_remove_match_internal_dbus1(
1109 sd_bus *bus,
1110 const char *match) {
777d7a61 1111
e7176abb
LP
1112 assert(bus);
1113 assert(match);
1114
1115 return sd_bus_call_method(
1116 bus,
1117 "org.freedesktop.DBus",
1118 "/",
1119 "org.freedesktop.DBus",
1120 "RemoveMatch",
1121 NULL,
1122 NULL,
1123 "s",
1124 match);
1125}
1126
1127int bus_remove_match_internal(
1128 sd_bus *bus,
1129 const char *match,
1130 uint64_t cookie) {
1131
1132 assert(bus);
1133 assert(match);
1134
1135 if (bus->is_kernel)
1136 return bus_remove_match_internal_kernel(bus, match, cookie);
1137 else
1138 return bus_remove_match_internal_dbus1(bus, match);
de1c301e 1139}
70666185 1140
d9f644e2 1141_public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
8d162091 1142 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
70666185
LP
1143 const char *mid;
1144 int r;
1145
8d162091
LP
1146 assert_return(bus, -EINVAL);
1147 assert_return(name, -EINVAL);
1148 assert_return(machine, -EINVAL);
1149 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1150 assert_return(!bus_pid_changed(bus), -ECHILD);
70666185
LP
1151
1152 if (streq_ptr(name, bus->unique_name))
1153 return sd_id128_get_machine(machine);
1154
8d162091
LP
1155 r = sd_bus_message_new_method_call(
1156 bus,
1157 name,
1158 "/",
1159 "org.freedesktop.DBus.Peer",
1160 "GetMachineId", &m);
1161 if (r < 0)
1162 return r;
1163
1164 r = sd_bus_message_set_no_auto_start(m, true);
1165 if (r < 0)
1166 return r;
70666185 1167
8d162091 1168 r = sd_bus_call(bus, m, 0, NULL, &reply);
70666185
LP
1169 if (r < 0)
1170 return r;
1171
1172 r = sd_bus_message_read(reply, "s", &mid);
1173 if (r < 0)
1174 return r;
1175
1176 return sd_id128_from_string(mid, machine);
1177}