chiark / gitweb /
sd-bus: pass attach flags to BUS_CREATOR_INFO
[elogind.git] / src / libsystemd / sd-bus / bus-control.c
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
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <stddef.h>
27 #include <errno.h>
28
29 #include "strv.h"
30 #include "sd-bus.h"
31 #include "bus-internal.h"
32 #include "bus-message.h"
33 #include "bus-control.h"
34 #include "bus-bloom.h"
35 #include "bus-util.h"
36 #include "cgroup-util.h"
37
38 _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
39         int r;
40
41         assert_return(bus, -EINVAL);
42         assert_return(unique, -EINVAL);
43         assert_return(!bus_pid_changed(bus), -ECHILD);
44
45         r = bus_ensure_running(bus);
46         if (r < 0)
47                 return r;
48
49         *unique = bus->unique_name;
50         return 0;
51 }
52
53 static int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
54         struct kdbus_cmd_name *n;
55         size_t size, l;
56         int r;
57
58         assert(bus);
59         assert(name);
60
61         l = strlen(name) + 1;
62         size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
63         n = alloca0_align(size, 8);
64         n->size = size;
65         kdbus_translate_request_name_flags(flags, (uint64_t *) &n->flags);
66
67         n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
68         n->items[0].type = KDBUS_ITEM_NAME;
69         memcpy(n->items[0].str, name, l);
70
71 #ifdef HAVE_VALGRIND_MEMCHECK_H
72         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
73 #endif
74
75         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
76         if (r < 0)
77                 return -errno;
78
79         if (n->flags & KDBUS_NAME_IN_QUEUE)
80                 return 0;
81
82         return 1;
83 }
84
85 static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) {
86         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
87         uint32_t ret, param = 0;
88         int r;
89
90         assert(bus);
91         assert(name);
92
93         if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
94                 param |= BUS_NAME_ALLOW_REPLACEMENT;
95         if (flags & SD_BUS_NAME_REPLACE_EXISTING)
96                 param |= BUS_NAME_REPLACE_EXISTING;
97         if (!(flags & SD_BUS_NAME_QUEUE))
98                 param |= BUS_NAME_DO_NOT_QUEUE;
99
100         r = sd_bus_call_method(
101                         bus,
102                         "org.freedesktop.DBus",
103                         "/org/freedesktop/DBus",
104                         "org.freedesktop.DBus",
105                         "RequestName",
106                         NULL,
107                         &reply,
108                         "su",
109                         name,
110                         param);
111         if (r < 0)
112                 return r;
113
114         r = sd_bus_message_read(reply, "u", &ret);
115         if (r < 0)
116                 return r;
117
118         if (ret == BUS_NAME_ALREADY_OWNER)
119                 return -EALREADY;
120         else if (ret == BUS_NAME_EXISTS)
121                 return -EEXIST;
122         else if (ret == BUS_NAME_IN_QUEUE)
123                 return 0;
124         else if (ret == BUS_NAME_PRIMARY_OWNER)
125                 return 1;
126
127         return -EIO;
128 }
129
130 _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) {
131         assert_return(bus, -EINVAL);
132         assert_return(name, -EINVAL);
133         assert_return(bus->bus_client, -EINVAL);
134         assert_return(!bus_pid_changed(bus), -ECHILD);
135         assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
136         assert_return(service_name_is_valid(name), -EINVAL);
137         assert_return(name[0] != ':', -EINVAL);
138
139         if (!BUS_IS_OPEN(bus->state))
140                 return -ENOTCONN;
141
142         if (bus->is_kernel)
143                 return bus_request_name_kernel(bus, name, flags);
144         else
145                 return bus_request_name_dbus1(bus, name, flags);
146 }
147
148 static int bus_release_name_kernel(sd_bus *bus, const char *name) {
149         struct kdbus_cmd_name *n;
150         size_t size, l;
151         int r;
152
153         assert(bus);
154         assert(name);
155
156         l = strlen(name) + 1;
157         size = offsetof(struct kdbus_cmd_name, items) + KDBUS_ITEM_SIZE(l);
158         n = alloca0_align(size, 8);
159         n->size = size;
160
161         n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
162         n->items[0].type = KDBUS_ITEM_NAME;
163         memcpy(n->items[0].str, name, l);
164
165 #ifdef HAVE_VALGRIND_MEMCHECK_H
166         VALGRIND_MAKE_MEM_DEFINED(n, n->size);
167 #endif
168         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
169         if (r < 0)
170                 return -errno;
171
172         return 0;
173 }
174
175 static int bus_release_name_dbus1(sd_bus *bus, const char *name) {
176         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
177         uint32_t ret;
178         int r;
179
180         assert(bus);
181         assert(name);
182
183         r = sd_bus_call_method(
184                         bus,
185                         "org.freedesktop.DBus",
186                         "/org/freedesktop/DBus",
187                         "org.freedesktop.DBus",
188                         "ReleaseName",
189                         NULL,
190                         &reply,
191                         "s",
192                         name);
193         if (r < 0)
194                 return r;
195
196         r = sd_bus_message_read(reply, "u", &ret);
197         if (r < 0)
198                 return r;
199         if (ret == BUS_NAME_NON_EXISTENT)
200                 return -ESRCH;
201         if (ret == BUS_NAME_NOT_OWNER)
202                 return -EADDRINUSE;
203         if (ret == BUS_NAME_RELEASED)
204                 return 0;
205
206         return -EINVAL;
207 }
208
209 _public_ int sd_bus_release_name(sd_bus *bus, const char *name) {
210         assert_return(bus, -EINVAL);
211         assert_return(name, -EINVAL);
212         assert_return(bus->bus_client, -EINVAL);
213         assert_return(!bus_pid_changed(bus), -ECHILD);
214         assert_return(service_name_is_valid(name), -EINVAL);
215         assert_return(name[0] != ':', -EINVAL);
216
217         if (!BUS_IS_OPEN(bus->state))
218                 return -ENOTCONN;
219
220         if (bus->is_kernel)
221                 return bus_release_name_kernel(bus, name);
222         else
223                 return bus_release_name_dbus1(bus, name);
224 }
225
226 static int kernel_cmd_free(sd_bus *bus, uint64_t offset)
227 {
228         struct kdbus_cmd_free cmd;
229         int r;
230
231         assert(bus);
232
233         cmd.flags = 0;
234         cmd.offset = offset;
235
236         r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
237         if (r < 0)
238                 return -errno;
239
240         return 0;
241 }
242
243 static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
244         struct kdbus_cmd_name_list cmd = {};
245         struct kdbus_name_list *name_list;
246         struct kdbus_name_info *name;
247         uint64_t previous_id = 0;
248         int r;
249
250         /* Caller will free half-constructed list on failure... */
251
252         cmd.flags = flags;
253
254         r = ioctl(bus->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
255         if (r < 0)
256                 return -errno;
257
258         name_list = (struct kdbus_name_list *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
259
260         KDBUS_ITEM_FOREACH(name, name_list, names) {
261
262                 struct kdbus_item *item;
263                 const char *entry_name = NULL;
264
265                 if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) {
266                         char *n;
267
268                         if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
269                                 r = -ENOMEM;
270                                 goto fail;
271                         }
272
273                         r = strv_consume(x, n);
274                         if (r < 0)
275                                 goto fail;
276
277                         previous_id = name->owner_id;
278                 }
279
280                 KDBUS_ITEM_FOREACH(item, name, items)
281                         if (item->type == KDBUS_ITEM_OWNED_NAME)
282                                 entry_name = item->name.name;
283
284                 if (entry_name && service_name_is_valid(entry_name)) {
285                         r = strv_extend(x, entry_name);
286                         if (r < 0) {
287                                 r = -ENOMEM;
288                                 goto fail;
289                         }
290                 }
291         }
292
293         r = 0;
294
295 fail:
296         kernel_cmd_free(bus, cmd.offset);
297         return r;
298 }
299
300 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
301         _cleanup_strv_free_ char **x = NULL, **y = NULL;
302         int r;
303
304         if (acquired) {
305                 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
306                 if (r < 0)
307                         return r;
308         }
309
310         if (activatable) {
311                 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
312                 if (r < 0)
313                         return r;
314
315                 *activatable = y;
316                 y = NULL;
317         }
318
319         if (acquired) {
320                 *acquired = x;
321                 x = NULL;
322         }
323
324         return 0;
325 }
326
327 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
328         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
329         _cleanup_strv_free_ char **x = NULL, **y = NULL;
330         int r;
331
332         if (acquired) {
333                 r = sd_bus_call_method(
334                                 bus,
335                                 "org.freedesktop.DBus",
336                                 "/org/freedesktop/DBus",
337                                 "org.freedesktop.DBus",
338                                 "ListNames",
339                                 NULL,
340                                 &reply,
341                                 NULL);
342                 if (r < 0)
343                         return r;
344
345                 r = sd_bus_message_read_strv(reply, &x);
346                 if (r < 0)
347                         return r;
348
349                 reply = sd_bus_message_unref(reply);
350         }
351
352         if (activatable) {
353                 r = sd_bus_call_method(
354                                 bus,
355                                 "org.freedesktop.DBus",
356                                 "/org/freedesktop/DBus",
357                                 "org.freedesktop.DBus",
358                                 "ListActivatableNames",
359                                 NULL,
360                                 &reply,
361                                 NULL);
362                 if (r < 0)
363                         return r;
364
365                 r = sd_bus_message_read_strv(reply, &y);
366                 if (r < 0)
367                         return r;
368
369                 *activatable = y;
370                 y = NULL;
371         }
372
373         if (acquired) {
374                 *acquired = x;
375                 x = NULL;
376         }
377
378         return 0;
379 }
380
381 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
382         assert_return(bus, -EINVAL);
383         assert_return(acquired || activatable, -EINVAL);
384         assert_return(!bus_pid_changed(bus), -ECHILD);
385
386         if (!BUS_IS_OPEN(bus->state))
387                 return -ENOTCONN;
388
389         if (bus->is_kernel)
390                 return bus_list_names_kernel(bus, acquired, activatable);
391         else
392                 return bus_list_names_dbus1(bus, acquired, activatable);
393 }
394
395 static int bus_populate_creds_from_items(sd_bus *bus,
396                                          struct kdbus_info *info,
397                                          uint64_t mask,
398                                          sd_bus_creds *c) {
399
400         struct kdbus_item *item;
401         uint64_t m;
402         int r;
403
404         KDBUS_ITEM_FOREACH(item, info, items) {
405
406                 switch (item->type) {
407
408                 case KDBUS_ITEM_CREDS:
409                         m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
410
411                         if (m) {
412                                 c->uid = (uid_t) item->creds.uid;
413                                 c->pid = (pid_t) item->creds.pid;
414                                 c->gid = (gid_t) item->creds.gid;
415                                 c->mask |= m;
416                         }
417
418                         if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
419                                 c->tid = (pid_t) item->creds.tid;
420                                 c->mask |= SD_BUS_CREDS_TID;
421                         }
422
423                         if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
424                                 c->pid_starttime = item->creds.starttime;
425                                 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
426                         }
427
428                         break;
429
430                 case KDBUS_ITEM_PID_COMM:
431                         if (mask & SD_BUS_CREDS_COMM) {
432                                 c->comm = strdup(item->str);
433                                 if (!c->comm)
434                                         return -ENOMEM;
435
436                                 c->mask |= SD_BUS_CREDS_COMM;
437                         }
438                         break;
439
440                 case KDBUS_ITEM_TID_COMM:
441                         if (mask & SD_BUS_CREDS_TID_COMM) {
442                                 c->tid_comm = strdup(item->str);
443                                 if (!c->tid_comm)
444                                         return -ENOMEM;
445
446                                 c->mask |= SD_BUS_CREDS_TID_COMM;
447                         }
448                         break;
449
450                 case KDBUS_ITEM_EXE:
451                         if (mask & SD_BUS_CREDS_EXE) {
452                                 c->exe = strdup(item->str);
453                                 if (!c->exe)
454                                         return -ENOMEM;
455
456                                 c->mask |= SD_BUS_CREDS_EXE;
457                         }
458                         break;
459
460                 case KDBUS_ITEM_CMDLINE:
461                         if (mask & SD_BUS_CREDS_CMDLINE) {
462                                 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
463                                 c->cmdline = memdup(item->data, c->cmdline_size);
464                                 if (!c->cmdline)
465                                         return -ENOMEM;
466
467                                 c->mask |= SD_BUS_CREDS_CMDLINE;
468                         }
469                         break;
470
471                 case KDBUS_ITEM_CGROUP:
472                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
473                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
474                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
475
476                         if (m) {
477                                 c->cgroup = strdup(item->str);
478                                 if (!c->cgroup)
479                                         return -ENOMEM;
480
481                                 r = bus_get_root_path(bus);
482                                 if (r < 0)
483                                         return r;
484
485                                 c->cgroup_root = strdup(bus->cgroup_root);
486                                 if (!c->cgroup_root)
487                                         return -ENOMEM;
488
489                                 c->mask |= m;
490                         }
491                         break;
492
493                 case KDBUS_ITEM_CAPS:
494                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
495                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
496
497                         if (m) {
498                                 c->capability_size = item->size - offsetof(struct kdbus_item, caps.caps);
499                                 c->capability = memdup(item->caps.caps, c->capability_size);
500                                 if (!c->capability)
501                                         return -ENOMEM;
502
503                                 c->mask |= m;
504                         }
505                         break;
506
507                 case KDBUS_ITEM_SECLABEL:
508                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
509                                 c->label = strdup(item->str);
510                                 if (!c->label)
511                                         return -ENOMEM;
512
513                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
514                         }
515                         break;
516
517                 case KDBUS_ITEM_AUDIT:
518                         m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
519
520                         if (m) {
521                                 c->audit_session_id = item->audit.sessionid;
522                                 c->audit_login_uid = item->audit.loginuid;
523                                 c->mask |= m;
524                         }
525                         break;
526
527                 case KDBUS_ITEM_OWNED_NAME:
528                         if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
529                                 r = strv_extend(&c->well_known_names, item->name.name);
530                                 if (r < 0)
531                                         return r;
532
533                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
534                         }
535                         break;
536
537                 case KDBUS_ITEM_CONN_DESCRIPTION:
538                         if ((mask & SD_BUS_CREDS_DESCRIPTION)) {
539                                 c->description = strdup(item->str);
540                                 if (!c->description)
541                                         return -ENOMEM;
542
543                                 c->mask |= SD_BUS_CREDS_DESCRIPTION;
544                         }
545                         break;
546                 }
547         }
548
549         return 0;
550 }
551
552 static int bus_get_name_creds_kdbus(
553                 sd_bus *bus,
554                 const char *name,
555                 uint64_t mask,
556                 sd_bus_creds **creds) {
557
558         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
559         struct kdbus_cmd_info *cmd;
560         struct kdbus_info *conn_info;
561         size_t size, l;
562         uint64_t id;
563         int r;
564
565         r = bus_kernel_parse_unique_name(name, &id);
566         if (r < 0)
567                 return r;
568         if (r > 0) {
569                 size = offsetof(struct kdbus_cmd_info, items);
570                 cmd = alloca0_align(size, 8);
571                 cmd->id = id;
572         } else {
573                 l = strlen(name) + 1;
574                 size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
575                 cmd = alloca0_align(size, 8);
576                 cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
577                 cmd->items[0].type = KDBUS_ITEM_NAME;
578                 memcpy(cmd->items[0].str, name, l);
579         }
580
581         cmd->size = size;
582         kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
583
584         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
585         if (r < 0)
586                 return -errno;
587
588         conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
589
590         /* Non-activated names are considered not available */
591         if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) {
592                 if (name[0] == ':')
593                         r = -ENXIO;
594                 else
595                         r = -ESRCH;
596                 goto fail;
597         }
598
599         c = bus_creds_new();
600         if (!c) {
601                 r = -ENOMEM;
602                 goto fail;
603         }
604
605         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
606                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0) {
607                         r = -ENOMEM;
608                         goto fail;
609                 }
610
611                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
612         }
613
614         r = bus_populate_creds_from_items(bus, conn_info, mask, c);
615         if (r < 0)
616                 goto fail;
617
618         if (creds) {
619                 *creds = c;
620                 c = NULL;
621         }
622
623         r = 0;
624
625 fail:
626         kernel_cmd_free(bus, cmd->offset);
627         return r;
628 }
629
630 static int bus_get_name_creds_dbus1(
631                 sd_bus *bus,
632                 const char *name,
633                 uint64_t mask,
634                 sd_bus_creds **creds) {
635
636         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
637         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
638         const char *unique = NULL;
639         pid_t pid = 0;
640         int r;
641
642         /* Only query the owner if the caller wants to know it or if
643          * the caller just wants to check whether a name exists */
644         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
645                 r = sd_bus_call_method(
646                                 bus,
647                                 "org.freedesktop.DBus",
648                                 "/org/freedesktop/DBus",
649                                 "org.freedesktop.DBus",
650                                 "GetNameOwner",
651                                 NULL,
652                                 &reply_unique,
653                                 "s",
654                                 name);
655                 if (r < 0)
656                         return r;
657
658                 r = sd_bus_message_read(reply_unique, "s", &unique);
659                 if (r < 0)
660                         return r;
661         }
662
663         if (mask != 0) {
664                 c = bus_creds_new();
665                 if (!c)
666                         return -ENOMEM;
667
668                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
669                         c->unique_name = strdup(unique);
670                         if (!c->unique_name)
671                                 return -ENOMEM;
672
673                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
674                 }
675
676                 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
677                             SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
678                             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|
679                             SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
680                             SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
681                         uint32_t u;
682
683                         r = sd_bus_call_method(
684                                         bus,
685                                         "org.freedesktop.DBus",
686                                         "/org/freedesktop/DBus",
687                                         "org.freedesktop.DBus",
688                                         "GetConnectionUnixProcessID",
689                                         NULL,
690                                         &reply,
691                                         "s",
692                                         unique ? unique : name);
693                         if (r < 0)
694                                 return r;
695
696                         r = sd_bus_message_read(reply, "u", &u);
697                         if (r < 0)
698                                 return r;
699
700                         pid = u;
701                         if (mask & SD_BUS_CREDS_PID) {
702                                 c->pid = u;
703                                 c->mask |= SD_BUS_CREDS_PID;
704                         }
705
706                         reply = sd_bus_message_unref(reply);
707                 }
708
709                 if (mask & SD_BUS_CREDS_UID) {
710                         uint32_t u;
711
712                         r = sd_bus_call_method(
713                                         bus,
714                                         "org.freedesktop.DBus",
715                                         "/org/freedesktop/DBus",
716                                         "org.freedesktop.DBus",
717                                         "GetConnectionUnixUser",
718                                         NULL,
719                                         &reply,
720                                         "s",
721                                         unique ? unique : name);
722                         if (r < 0)
723                                 return r;
724
725                         r = sd_bus_message_read(reply, "u", &u);
726                         if (r < 0)
727                                 return r;
728
729                         c->uid = u;
730                         c->mask |= SD_BUS_CREDS_UID;
731
732                         reply = sd_bus_message_unref(reply);
733                 }
734
735                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
736                         const void *p = NULL;
737                         size_t sz = 0;
738
739                         r = sd_bus_call_method(
740                                         bus,
741                                         "org.freedesktop.DBus",
742                                         "/org/freedesktop/DBus",
743                                         "org.freedesktop.DBus",
744                                         "GetConnectionSELinuxSecurityContext",
745                                         NULL,
746                                         &reply,
747                                         "s",
748                                         unique ? unique : name);
749                         if (r < 0)
750                                 return r;
751
752                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
753                         if (r < 0)
754                                 return r;
755
756                         c->label = strndup(p, sz);
757                         if (!c->label)
758                                 return -ENOMEM;
759
760                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
761                 }
762
763                 r = bus_creds_add_more(c, mask, pid, 0);
764                 if (r < 0)
765                         return r;
766         }
767
768         if (creds) {
769                 *creds = c;
770                 c = NULL;
771         }
772
773         return 0;
774 }
775
776 _public_ int sd_bus_get_name_creds(
777                 sd_bus *bus,
778                 const char *name,
779                 uint64_t mask,
780                 sd_bus_creds **creds) {
781
782         assert_return(bus, -EINVAL);
783         assert_return(name, -EINVAL);
784         assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
785         assert_return(mask == 0 || creds, -EINVAL);
786         assert_return(!bus_pid_changed(bus), -ECHILD);
787         assert_return(service_name_is_valid(name), -EINVAL);
788         assert_return(bus->bus_client, -ENODATA);
789
790         if (!BUS_IS_OPEN(bus->state))
791                 return -ENOTCONN;
792
793         if (bus->is_kernel)
794                 return bus_get_name_creds_kdbus(bus, name, mask, creds);
795         else
796                 return bus_get_name_creds_dbus1(bus, name, mask, creds);
797 }
798
799 _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
800         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
801         pid_t pid = 0;
802         int r;
803
804         assert_return(bus, -EINVAL);
805         assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
806         assert_return(ret, -EINVAL);
807         assert_return(!bus_pid_changed(bus), -ECHILD);
808
809         if (!BUS_IS_OPEN(bus->state))
810                 return -ENOTCONN;
811
812         if (!bus->ucred_valid && !isempty(bus->label))
813                 return -ENODATA;
814
815         c = bus_creds_new();
816         if (!c)
817                 return -ENOMEM;
818
819         if (bus->ucred_valid) {
820                 pid = c->pid = bus->ucred.pid;
821                 c->uid = bus->ucred.uid;
822                 c->gid = bus->ucred.gid;
823
824                 c->mask |= (SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID) & mask;
825         }
826
827         if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) {
828                 c->label = strdup(bus->label);
829                 if (!c->label)
830                         return -ENOMEM;
831
832                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
833         }
834
835         if (bus->is_kernel) {
836                 struct kdbus_cmd_info cmd = {};
837                 struct kdbus_info *creator_info;
838
839                 cmd.size = sizeof(cmd);
840                 cmd.flags = _KDBUS_ATTACH_ALL;
841                 r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
842                 if (r < 0)
843                         return -errno;
844
845                 creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
846
847                 r = bus_populate_creds_from_items(bus, creator_info, mask, c);
848                 kernel_cmd_free(bus, cmd.offset);
849
850                 if (r < 0)
851                         return r;
852         } else {
853                 r = bus_creds_add_more(c, mask, pid, 0);
854                 if (r < 0)
855                         return r;
856         }
857
858         *ret = c;
859         c = NULL;
860         return 0;
861 }
862
863 static int add_name_change_match(sd_bus *bus,
864                                  uint64_t cookie,
865                                  const char *name,
866                                  const char *old_owner,
867                                  const char *new_owner) {
868
869         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
870         int is_name_id = -1, r;
871         struct kdbus_item *item;
872
873         assert(bus);
874
875         /* If we encounter a match that could match against
876          * NameOwnerChanged messages, then we need to create
877          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
878          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
879          * multiple if the match is underspecified.
880          *
881          * The NameOwnerChanged signals take three parameters with
882          * unique or well-known names, but only some forms actually
883          * exist:
884          *
885          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
886          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
887          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
888          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
889          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
890          *
891          * For the latter two the two unique names must be identical.
892          *
893          * */
894
895         if (name) {
896                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
897                 if (is_name_id < 0)
898                         return 0;
899         }
900
901         if (!isempty(old_owner)) {
902                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
903                 if (r < 0)
904                         return 0;
905                 if (r == 0)
906                         return 0;
907                 if (is_name_id > 0 && old_owner_id != name_id)
908                         return 0;
909         } else
910                 old_owner_id = KDBUS_MATCH_ID_ANY;
911
912         if (!isempty(new_owner)) {
913                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
914                 if (r < 0)
915                         return r;
916                 if (r == 0)
917                         return 0;
918                 if (is_name_id > 0 && new_owner_id != name_id)
919                         return 0;
920         } else
921                 new_owner_id = KDBUS_MATCH_ID_ANY;
922
923         if (is_name_id <= 0) {
924                 struct kdbus_cmd_match *m;
925                 size_t sz, l;
926
927                 /* If the name argument is missing or is a well-known
928                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
929                  * matches for it */
930
931                 l = name ? strlen(name) + 1 : 0;
932
933                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
934                             offsetof(struct kdbus_item, name_change) +
935                             offsetof(struct kdbus_notify_name_change, name) +
936                             l);
937
938                 m = alloca0_align(sz, 8);
939                 m->size = sz;
940                 m->cookie = cookie;
941
942                 item = m->items;
943                 item->size =
944                         offsetof(struct kdbus_item, name_change) +
945                         offsetof(struct kdbus_notify_name_change, name) +
946                         l;
947
948                 item->name_change.old_id.id = old_owner_id;
949                 item->name_change.new_id.id = new_owner_id;
950
951                 if (name)
952                         memcpy(item->name_change.name, name, l);
953
954                 /* If the old name is unset or empty, then
955                  * this can match against added names */
956                 if (!old_owner || old_owner[0] == 0) {
957                         item->type = KDBUS_ITEM_NAME_ADD;
958
959                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
960                         if (r < 0)
961                                 return -errno;
962                 }
963
964                 /* If the new name is unset or empty, then
965                  * this can match against removed names */
966                 if (!new_owner || new_owner[0] == 0) {
967                         item->type = KDBUS_ITEM_NAME_REMOVE;
968
969                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
970                         if (r < 0)
971                                 return -errno;
972                 }
973
974                 /* The CHANGE match we need in either case, because
975                  * what is reported as a name change by the kernel
976                  * might just be an owner change between starter and
977                  * normal clients. For userspace such a change should
978                  * be considered a removal/addition, hence let's
979                  * subscribe to this unconditionally. */
980                 item->type = KDBUS_ITEM_NAME_CHANGE;
981                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
982                 if (r < 0)
983                         return -errno;
984         }
985
986         if (is_name_id != 0) {
987                 struct kdbus_cmd_match *m;
988                 uint64_t sz;
989
990                 /* If the name argument is missing or is a unique
991                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
992                  * for it */
993
994                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
995                             offsetof(struct kdbus_item, id_change) +
996                             sizeof(struct kdbus_notify_id_change));
997
998                 m = alloca0_align(sz, 8);
999                 m->size = sz;
1000                 m->cookie = cookie;
1001
1002                 item = m->items;
1003                 item->size =
1004                         offsetof(struct kdbus_item, id_change) +
1005                         sizeof(struct kdbus_notify_id_change);
1006                 item->id_change.id = name_id;
1007
1008                 /* If the old name is unset or empty, then this can
1009                  * match against added ids */
1010                 if (!old_owner || old_owner[0] == 0) {
1011                         item->type = KDBUS_ITEM_ID_ADD;
1012
1013                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1014                         if (r < 0)
1015                                 return -errno;
1016                 }
1017
1018                 /* If thew new name is unset or empty, then this can
1019                  * match against removed ids */
1020                 if (!new_owner || new_owner[0] == 0) {
1021                         item->type = KDBUS_ITEM_ID_REMOVE;
1022
1023                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1024                         if (r < 0)
1025                                 return -errno;
1026                 }
1027         }
1028
1029         return 0;
1030 }
1031
1032 int bus_add_match_internal_kernel(
1033                 sd_bus *bus,
1034                 struct bus_match_component *components,
1035                 unsigned n_components,
1036                 uint64_t cookie) {
1037
1038         struct kdbus_cmd_match *m;
1039         struct kdbus_item *item;
1040         uint64_t *bloom;
1041         size_t sz;
1042         const char *sender = NULL;
1043         size_t sender_length = 0;
1044         uint64_t src_id = KDBUS_MATCH_ID_ANY;
1045         bool using_bloom = false;
1046         unsigned i;
1047         bool matches_name_change = true;
1048         const char *name_change_arg[3] = {};
1049         int r;
1050
1051         assert(bus);
1052
1053         bloom = alloca0(bus->bloom_size);
1054
1055         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
1056
1057         for (i = 0; i < n_components; i++) {
1058                 struct bus_match_component *c = &components[i];
1059
1060                 switch (c->type) {
1061
1062                 case BUS_MATCH_SENDER:
1063                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1064                                 matches_name_change = false;
1065
1066                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1067                         if (r < 0)
1068                                 return r;
1069                         else if (r > 0)
1070                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1071                         else  {
1072                                 sender = c->value_str;
1073                                 sender_length = strlen(sender);
1074                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1075                         }
1076
1077                         break;
1078
1079                 case BUS_MATCH_MESSAGE_TYPE:
1080                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1081                                 matches_name_change = false;
1082
1083                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1084                         using_bloom = true;
1085                         break;
1086
1087                 case BUS_MATCH_INTERFACE:
1088                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1089                                 matches_name_change = false;
1090
1091                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1092                         using_bloom = true;
1093                         break;
1094
1095                 case BUS_MATCH_MEMBER:
1096                         if (!streq(c->value_str, "NameOwnerChanged"))
1097                                 matches_name_change = false;
1098
1099                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1100                         using_bloom = true;
1101                         break;
1102
1103                 case BUS_MATCH_PATH:
1104                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1105                                 matches_name_change = false;
1106
1107                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1108                         using_bloom = true;
1109                         break;
1110
1111                 case BUS_MATCH_PATH_NAMESPACE:
1112                         if (!streq(c->value_str, "/")) {
1113                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1114                                 using_bloom = true;
1115                         }
1116                         break;
1117
1118                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1119                         char buf[sizeof("arg")-1 + 2 + 1];
1120
1121                         if (c->type - BUS_MATCH_ARG < 3)
1122                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1123
1124                         snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1125                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1126                         using_bloom = true;
1127                         break;
1128                 }
1129
1130                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1131                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1132
1133                         snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1134                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1135                         using_bloom = true;
1136                         break;
1137                 }
1138
1139                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1140                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1141
1142                         snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1143                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1144                         using_bloom = true;
1145                         break;
1146                 }
1147
1148                 case BUS_MATCH_DESTINATION:
1149                         /* The bloom filter does not include
1150                            the destination, since it is only
1151                            available for broadcast messages
1152                            which do not carry a destination
1153                            since they are undirected. */
1154                         break;
1155
1156                 case BUS_MATCH_ROOT:
1157                 case BUS_MATCH_VALUE:
1158                 case BUS_MATCH_LEAF:
1159                 case _BUS_MATCH_NODE_TYPE_MAX:
1160                 case _BUS_MATCH_NODE_TYPE_INVALID:
1161                         assert_not_reached("Invalid match type?");
1162                 }
1163         }
1164
1165         if (using_bloom)
1166                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1167
1168         m = alloca0_align(sz, 8);
1169         m->size = sz;
1170         m->cookie = cookie;
1171
1172         item = m->items;
1173
1174         if (src_id != KDBUS_MATCH_ID_ANY) {
1175                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1176                 item->type = KDBUS_ITEM_ID;
1177                 item->id = src_id;
1178                 item = KDBUS_ITEM_NEXT(item);
1179         }
1180
1181         if (using_bloom) {
1182                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1183                 item->type = KDBUS_ITEM_BLOOM_MASK;
1184                 memcpy(item->data64, bloom, bus->bloom_size);
1185                 item = KDBUS_ITEM_NEXT(item);
1186         }
1187
1188         if (sender) {
1189                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1190                 item->type = KDBUS_ITEM_NAME;
1191                 memcpy(item->str, sender, sender_length + 1);
1192         }
1193
1194         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1195         if (r < 0)
1196                 return -errno;
1197
1198         if (matches_name_change) {
1199
1200                 /* If this match could theoretically match
1201                  * NameOwnerChanged messages, we need to
1202                  * install a second non-bloom filter explitly
1203                  * for it */
1204
1205                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1206                 if (r < 0)
1207                         return r;
1208         }
1209
1210         return 0;
1211 }
1212
1213 #define internal_match(bus, m)                                          \
1214         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1215          ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1216          : (m))
1217
1218 static int bus_add_match_internal_dbus1(
1219                 sd_bus *bus,
1220                 const char *match) {
1221
1222         const char *e;
1223
1224         assert(bus);
1225         assert(match);
1226
1227         e = internal_match(bus, match);
1228
1229         return sd_bus_call_method(
1230                         bus,
1231                         "org.freedesktop.DBus",
1232                         "/org/freedesktop/DBus",
1233                         "org.freedesktop.DBus",
1234                         "AddMatch",
1235                         NULL,
1236                         NULL,
1237                         "s",
1238                         e);
1239 }
1240
1241 int bus_add_match_internal(
1242                 sd_bus *bus,
1243                 const char *match,
1244                 struct bus_match_component *components,
1245                 unsigned n_components,
1246                 uint64_t cookie) {
1247
1248         assert(bus);
1249
1250         if (bus->is_kernel)
1251                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1252         else
1253                 return bus_add_match_internal_dbus1(bus, match);
1254 }
1255
1256 int bus_remove_match_internal_kernel(
1257                 sd_bus *bus,
1258                 uint64_t cookie) {
1259
1260         struct kdbus_cmd_match m;
1261         int r;
1262
1263         assert(bus);
1264
1265         zero(m);
1266         m.size = offsetof(struct kdbus_cmd_match, items);
1267         m.cookie = cookie;
1268
1269         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1270         if (r < 0)
1271                 return -errno;
1272
1273         return 0;
1274 }
1275
1276 static int bus_remove_match_internal_dbus1(
1277                 sd_bus *bus,
1278                 const char *match) {
1279
1280         const char *e;
1281
1282         assert(bus);
1283         assert(match);
1284
1285         e = internal_match(bus, match);
1286
1287         return sd_bus_call_method(
1288                         bus,
1289                         "org.freedesktop.DBus",
1290                         "/org/freedesktop/DBus",
1291                         "org.freedesktop.DBus",
1292                         "RemoveMatch",
1293                         NULL,
1294                         NULL,
1295                         "s",
1296                         e);
1297 }
1298
1299 int bus_remove_match_internal(
1300                 sd_bus *bus,
1301                 const char *match,
1302                 uint64_t cookie) {
1303
1304         assert(bus);
1305
1306         if (bus->is_kernel)
1307                 return bus_remove_match_internal_kernel(bus, cookie);
1308         else
1309                 return bus_remove_match_internal_dbus1(bus, match);
1310 }
1311
1312 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1313         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1314         const char *mid;
1315         int r;
1316
1317         assert_return(bus, -EINVAL);
1318         assert_return(name, -EINVAL);
1319         assert_return(machine, -EINVAL);
1320         assert_return(!bus_pid_changed(bus), -ECHILD);
1321         assert_return(service_name_is_valid(name), -EINVAL);
1322
1323         if (!BUS_IS_OPEN(bus->state))
1324                 return -ENOTCONN;
1325
1326         if (streq_ptr(name, bus->unique_name))
1327                 return sd_id128_get_machine(machine);
1328
1329         r = sd_bus_message_new_method_call(
1330                         bus,
1331                         &m,
1332                         name,
1333                         "/",
1334                         "org.freedesktop.DBus.Peer",
1335                         "GetMachineId");
1336         if (r < 0)
1337                 return r;
1338
1339         r = sd_bus_message_set_auto_start(m, false);
1340         if (r < 0)
1341                 return r;
1342
1343         r = sd_bus_call(bus, m, 0, NULL, &reply);
1344         if (r < 0)
1345                 return r;
1346
1347         r = sd_bus_message_read(reply, "s", &mid);
1348         if (r < 0)
1349                 return r;
1350
1351         return sd_id128_from_string(mid, machine);
1352 }