chiark / gitweb /
sd-bus: factor out creds item iterator
[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_NAME)
282                                 entry_name = item->str;
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 - KDBUS_ITEM_HEADER_SIZE;
499                                 c->capability = memdup(item->data, 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_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_NAME:
538                         if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
539                                 c->conn_name = strdup(item->str);
540                                 if (!c->conn_name)
541                                         return -ENOMEM;
542
543                                 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
544                         }
545                         break;
546                 }
547         }
548
549         return 0;
550 }
551
552 static int bus_get_owner_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_owner_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_owner(
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_owner_kdbus(bus, name, mask, creds);
795         else
796                 return bus_get_owner_dbus1(bus, name, mask, creds);
797 }
798
799 static int add_name_change_match(sd_bus *bus,
800                                  uint64_t cookie,
801                                  const char *name,
802                                  const char *old_owner,
803                                  const char *new_owner) {
804
805         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
806         int is_name_id = -1, r;
807         struct kdbus_item *item;
808
809         assert(bus);
810
811         /* If we encounter a match that could match against
812          * NameOwnerChanged messages, then we need to create
813          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
814          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
815          * multiple if the match is underspecified.
816          *
817          * The NameOwnerChanged signals take three parameters with
818          * unique or well-known names, but only some forms actually
819          * exist:
820          *
821          * WELLKNOWN, "", UNIQUE       → KDBUS_ITEM_NAME_ADD
822          * WELLKNOWN, UNIQUE, ""       → KDBUS_ITEM_NAME_REMOVE
823          * WELLKNOWN, UNIQUE, UNIQUE   → KDBUS_ITEM_NAME_CHANGE
824          * UNIQUE, "", UNIQUE          → KDBUS_ITEM_ID_ADD
825          * UNIQUE, UNIQUE, ""          → KDBUS_ITEM_ID_REMOVE
826          *
827          * For the latter two the two unique names must be identical.
828          *
829          * */
830
831         if (name) {
832                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
833                 if (is_name_id < 0)
834                         return 0;
835         }
836
837         if (!isempty(old_owner)) {
838                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
839                 if (r < 0)
840                         return 0;
841                 if (r == 0)
842                         return 0;
843                 if (is_name_id > 0 && old_owner_id != name_id)
844                         return 0;
845         } else
846                 old_owner_id = KDBUS_MATCH_ID_ANY;
847
848         if (!isempty(new_owner)) {
849                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
850                 if (r < 0)
851                         return r;
852                 if (r == 0)
853                         return 0;
854                 if (is_name_id > 0 && new_owner_id != name_id)
855                         return 0;
856         } else
857                 new_owner_id = KDBUS_MATCH_ID_ANY;
858
859         if (is_name_id <= 0) {
860                 struct kdbus_cmd_match *m;
861                 size_t sz, l;
862
863                 /* If the name argument is missing or is a well-known
864                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
865                  * matches for it */
866
867                 l = name ? strlen(name) + 1 : 0;
868
869                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
870                             offsetof(struct kdbus_item, name_change) +
871                             offsetof(struct kdbus_notify_name_change, name) +
872                             l);
873
874                 m = alloca0_align(sz, 8);
875                 m->size = sz;
876                 m->cookie = cookie;
877
878                 item = m->items;
879                 item->size =
880                         offsetof(struct kdbus_item, name_change) +
881                         offsetof(struct kdbus_notify_name_change, name) +
882                         l;
883
884                 item->name_change.old_id.id = old_owner_id;
885                 item->name_change.new_id.id = new_owner_id;
886
887                 if (name)
888                         memcpy(item->name_change.name, name, l);
889
890                 /* If the old name is unset or empty, then
891                  * this can match against added names */
892                 if (!old_owner || old_owner[0] == 0) {
893                         item->type = KDBUS_ITEM_NAME_ADD;
894
895                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
896                         if (r < 0)
897                                 return -errno;
898                 }
899
900                 /* If the new name is unset or empty, then
901                  * this can match against removed names */
902                 if (!new_owner || new_owner[0] == 0) {
903                         item->type = KDBUS_ITEM_NAME_REMOVE;
904
905                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
906                         if (r < 0)
907                                 return -errno;
908                 }
909
910                 /* The CHANGE match we need in either case, because
911                  * what is reported as a name change by the kernel
912                  * might just be an owner change between starter and
913                  * normal clients. For userspace such a change should
914                  * be considered a removal/addition, hence let's
915                  * subscribe to this unconditionally. */
916                 item->type = KDBUS_ITEM_NAME_CHANGE;
917                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
918                 if (r < 0)
919                         return -errno;
920         }
921
922         if (is_name_id != 0) {
923                 struct kdbus_cmd_match *m;
924                 uint64_t sz;
925
926                 /* If the name argument is missing or is a unique
927                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
928                  * for it */
929
930                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
931                             offsetof(struct kdbus_item, id_change) +
932                             sizeof(struct kdbus_notify_id_change));
933
934                 m = alloca0_align(sz, 8);
935                 m->size = sz;
936                 m->cookie = cookie;
937
938                 item = m->items;
939                 item->size =
940                         offsetof(struct kdbus_item, id_change) +
941                         sizeof(struct kdbus_notify_id_change);
942                 item->id_change.id = name_id;
943
944                 /* If the old name is unset or empty, then this can
945                  * match against added ids */
946                 if (!old_owner || old_owner[0] == 0) {
947                         item->type = KDBUS_ITEM_ID_ADD;
948
949                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
950                         if (r < 0)
951                                 return -errno;
952                 }
953
954                 /* If thew new name is unset or empty, then this can
955                  * match against removed ids */
956                 if (!new_owner || new_owner[0] == 0) {
957                         item->type = KDBUS_ITEM_ID_REMOVE;
958
959                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
960                         if (r < 0)
961                                 return -errno;
962                 }
963         }
964
965         return 0;
966 }
967
968 int bus_add_match_internal_kernel(
969                 sd_bus *bus,
970                 struct bus_match_component *components,
971                 unsigned n_components,
972                 uint64_t cookie) {
973
974         struct kdbus_cmd_match *m;
975         struct kdbus_item *item;
976         uint64_t *bloom;
977         size_t sz;
978         const char *sender = NULL;
979         size_t sender_length = 0;
980         uint64_t src_id = KDBUS_MATCH_ID_ANY;
981         bool using_bloom = false;
982         unsigned i;
983         bool matches_name_change = true;
984         const char *name_change_arg[3] = {};
985         int r;
986
987         assert(bus);
988
989         bloom = alloca0(bus->bloom_size);
990
991         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
992
993         for (i = 0; i < n_components; i++) {
994                 struct bus_match_component *c = &components[i];
995
996                 switch (c->type) {
997
998                 case BUS_MATCH_SENDER:
999                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1000                                 matches_name_change = false;
1001
1002                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
1003                         if (r < 0)
1004                                 return r;
1005                         else if (r > 0)
1006                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
1007                         else  {
1008                                 sender = c->value_str;
1009                                 sender_length = strlen(sender);
1010                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1011                         }
1012
1013                         break;
1014
1015                 case BUS_MATCH_MESSAGE_TYPE:
1016                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1017                                 matches_name_change = false;
1018
1019                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1020                         using_bloom = true;
1021                         break;
1022
1023                 case BUS_MATCH_INTERFACE:
1024                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1025                                 matches_name_change = false;
1026
1027                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1028                         using_bloom = true;
1029                         break;
1030
1031                 case BUS_MATCH_MEMBER:
1032                         if (!streq(c->value_str, "NameOwnerChanged"))
1033                                 matches_name_change = false;
1034
1035                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1036                         using_bloom = true;
1037                         break;
1038
1039                 case BUS_MATCH_PATH:
1040                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1041                                 matches_name_change = false;
1042
1043                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1044                         using_bloom = true;
1045                         break;
1046
1047                 case BUS_MATCH_PATH_NAMESPACE:
1048                         if (!streq(c->value_str, "/")) {
1049                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1050                                 using_bloom = true;
1051                         }
1052                         break;
1053
1054                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1055                         char buf[sizeof("arg")-1 + 2 + 1];
1056
1057                         if (c->type - BUS_MATCH_ARG < 3)
1058                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1059
1060                         snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1061                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1062                         using_bloom = true;
1063                         break;
1064                 }
1065
1066                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1067                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1068
1069                         snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
1070                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1071                         using_bloom = true;
1072                         break;
1073                 }
1074
1075                 case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1076                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1077
1078                         snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
1079                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1080                         using_bloom = true;
1081                         break;
1082                 }
1083
1084                 case BUS_MATCH_DESTINATION:
1085                         /* The bloom filter does not include
1086                            the destination, since it is only
1087                            available for broadcast messages
1088                            which do not carry a destination
1089                            since they are undirected. */
1090                         break;
1091
1092                 case BUS_MATCH_ROOT:
1093                 case BUS_MATCH_VALUE:
1094                 case BUS_MATCH_LEAF:
1095                 case _BUS_MATCH_NODE_TYPE_MAX:
1096                 case _BUS_MATCH_NODE_TYPE_INVALID:
1097                         assert_not_reached("Invalid match type?");
1098                 }
1099         }
1100
1101         if (using_bloom)
1102                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1103
1104         m = alloca0_align(sz, 8);
1105         m->size = sz;
1106         m->cookie = cookie;
1107
1108         item = m->items;
1109
1110         if (src_id != KDBUS_MATCH_ID_ANY) {
1111                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1112                 item->type = KDBUS_ITEM_ID;
1113                 item->id = src_id;
1114                 item = KDBUS_ITEM_NEXT(item);
1115         }
1116
1117         if (using_bloom) {
1118                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1119                 item->type = KDBUS_ITEM_BLOOM_MASK;
1120                 memcpy(item->data64, bloom, bus->bloom_size);
1121                 item = KDBUS_ITEM_NEXT(item);
1122         }
1123
1124         if (sender) {
1125                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1126                 item->type = KDBUS_ITEM_NAME;
1127                 memcpy(item->str, sender, sender_length + 1);
1128         }
1129
1130         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1131         if (r < 0)
1132                 return -errno;
1133
1134         if (matches_name_change) {
1135
1136                 /* If this match could theoretically match
1137                  * NameOwnerChanged messages, we need to
1138                  * install a second non-bloom filter explitly
1139                  * for it */
1140
1141                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1142                 if (r < 0)
1143                         return r;
1144         }
1145
1146         return 0;
1147 }
1148
1149 #define internal_match(bus, m)                                          \
1150         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1151          ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1152          : (m))
1153
1154 static int bus_add_match_internal_dbus1(
1155                 sd_bus *bus,
1156                 const char *match) {
1157
1158         const char *e;
1159
1160         assert(bus);
1161         assert(match);
1162
1163         e = internal_match(bus, match);
1164
1165         return sd_bus_call_method(
1166                         bus,
1167                         "org.freedesktop.DBus",
1168                         "/org/freedesktop/DBus",
1169                         "org.freedesktop.DBus",
1170                         "AddMatch",
1171                         NULL,
1172                         NULL,
1173                         "s",
1174                         e);
1175 }
1176
1177 int bus_add_match_internal(
1178                 sd_bus *bus,
1179                 const char *match,
1180                 struct bus_match_component *components,
1181                 unsigned n_components,
1182                 uint64_t cookie) {
1183
1184         assert(bus);
1185
1186         if (bus->is_kernel)
1187                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1188         else
1189                 return bus_add_match_internal_dbus1(bus, match);
1190 }
1191
1192 int bus_remove_match_internal_kernel(
1193                 sd_bus *bus,
1194                 uint64_t cookie) {
1195
1196         struct kdbus_cmd_match m;
1197         int r;
1198
1199         assert(bus);
1200
1201         zero(m);
1202         m.size = offsetof(struct kdbus_cmd_match, items);
1203         m.cookie = cookie;
1204
1205         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1206         if (r < 0)
1207                 return -errno;
1208
1209         return 0;
1210 }
1211
1212 static int bus_remove_match_internal_dbus1(
1213                 sd_bus *bus,
1214                 const char *match) {
1215
1216         const char *e;
1217
1218         assert(bus);
1219         assert(match);
1220
1221         e = internal_match(bus, match);
1222
1223         return sd_bus_call_method(
1224                         bus,
1225                         "org.freedesktop.DBus",
1226                         "/org/freedesktop/DBus",
1227                         "org.freedesktop.DBus",
1228                         "RemoveMatch",
1229                         NULL,
1230                         NULL,
1231                         "s",
1232                         e);
1233 }
1234
1235 int bus_remove_match_internal(
1236                 sd_bus *bus,
1237                 const char *match,
1238                 uint64_t cookie) {
1239
1240         assert(bus);
1241
1242         if (bus->is_kernel)
1243                 return bus_remove_match_internal_kernel(bus, cookie);
1244         else
1245                 return bus_remove_match_internal_dbus1(bus, match);
1246 }
1247
1248 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1249         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1250         const char *mid;
1251         int r;
1252
1253         assert_return(bus, -EINVAL);
1254         assert_return(name, -EINVAL);
1255         assert_return(machine, -EINVAL);
1256         assert_return(!bus_pid_changed(bus), -ECHILD);
1257         assert_return(service_name_is_valid(name), -EINVAL);
1258
1259         if (!BUS_IS_OPEN(bus->state))
1260                 return -ENOTCONN;
1261
1262         if (streq_ptr(name, bus->unique_name))
1263                 return sd_id128_get_machine(machine);
1264
1265         r = sd_bus_message_new_method_call(
1266                         bus,
1267                         &m,
1268                         name,
1269                         "/",
1270                         "org.freedesktop.DBus.Peer",
1271                         "GetMachineId");
1272         if (r < 0)
1273                 return r;
1274
1275         r = sd_bus_message_set_auto_start(m, false);
1276         if (r < 0)
1277                 return r;
1278
1279         r = sd_bus_call(bus, m, 0, NULL, &reply);
1280         if (r < 0)
1281                 return r;
1282
1283         r = sd_bus_message_read(reply, "s", &mid);
1284         if (r < 0)
1285                 return r;
1286
1287         return sd_id128_from_string(mid, machine);
1288 }