chiark / gitweb /
sd-bus: sync kdbus.h (ABI break)
[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 n->flags;
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_cmd_name *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                                 return -ENOMEM;
270
271                         r = strv_consume(x, n);
272                         if (r < 0)
273                                 return r;
274
275                         previous_id = name->owner_id;
276                 }
277
278                 KDBUS_ITEM_FOREACH(item, name, items)
279                         if (item->type == KDBUS_ITEM_NAME)
280                                 entry_name = item->str;
281
282                 if (entry_name && service_name_is_valid(entry_name)) {
283                         r = strv_extend(x, entry_name);
284                         if (r < 0)
285                                 return -ENOMEM;
286                 }
287         }
288
289         r = kernel_cmd_free(bus, cmd.offset);
290         if (r < 0)
291                 return r;
292
293         return 0;
294 }
295
296 static int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
297         _cleanup_strv_free_ char **x = NULL, **y = NULL;
298         int r;
299
300         if (acquired) {
301                 r = kernel_get_list(bus, KDBUS_NAME_LIST_UNIQUE | KDBUS_NAME_LIST_NAMES, &x);
302                 if (r < 0)
303                         return r;
304         }
305
306         if (activatable) {
307                 r = kernel_get_list(bus, KDBUS_NAME_LIST_ACTIVATORS, &y);
308                 if (r < 0)
309                         return r;
310
311                 *activatable = y;
312                 y = NULL;
313         }
314
315         if (acquired) {
316                 *acquired = x;
317                 x = NULL;
318         }
319
320         return 0;
321 }
322
323 static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) {
324         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
325         _cleanup_strv_free_ char **x = NULL, **y = NULL;
326         int r;
327
328         if (acquired) {
329                 r = sd_bus_call_method(
330                                 bus,
331                                 "org.freedesktop.DBus",
332                                 "/org/freedesktop/DBus",
333                                 "org.freedesktop.DBus",
334                                 "ListNames",
335                                 NULL,
336                                 &reply,
337                                 NULL);
338                 if (r < 0)
339                         return r;
340
341                 r = sd_bus_message_read_strv(reply, &x);
342                 if (r < 0)
343                         return r;
344
345                 reply = sd_bus_message_unref(reply);
346         }
347
348         if (activatable) {
349                 r = sd_bus_call_method(
350                                 bus,
351                                 "org.freedesktop.DBus",
352                                 "/org/freedesktop/DBus",
353                                 "org.freedesktop.DBus",
354                                 "ListActivatableNames",
355                                 NULL,
356                                 &reply,
357                                 NULL);
358                 if (r < 0)
359                         return r;
360
361                 r = sd_bus_message_read_strv(reply, &y);
362                 if (r < 0)
363                         return r;
364
365                 *activatable = y;
366                 y = NULL;
367         }
368
369         if (acquired) {
370                 *acquired = x;
371                 x = NULL;
372         }
373
374         return 0;
375 }
376
377 _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
378         assert_return(bus, -EINVAL);
379         assert_return(acquired || activatable, -EINVAL);
380         assert_return(!bus_pid_changed(bus), -ECHILD);
381
382         if (!BUS_IS_OPEN(bus->state))
383                 return -ENOTCONN;
384
385         if (bus->is_kernel)
386                 return bus_list_names_kernel(bus, acquired, activatable);
387         else
388                 return bus_list_names_dbus1(bus, acquired, activatable);
389 }
390
391 static int bus_get_owner_kdbus(
392                 sd_bus *bus,
393                 const char *name,
394                 uint64_t mask,
395                 sd_bus_creds **creds) {
396
397         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
398         struct kdbus_cmd_conn_info *cmd;
399         struct kdbus_conn_info *conn_info;
400         struct kdbus_item *item;
401         size_t size;
402         uint64_t m, id;
403         int r;
404
405         r = bus_kernel_parse_unique_name(name, &id);
406         if (r < 0)
407                 return r;
408         if (r > 0) {
409                 size = offsetof(struct kdbus_cmd_conn_info, items);
410                 cmd = alloca0_align(size, 8);
411                 cmd->id = id;
412         } else {
413                 size_t item_size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
414
415                 size = offsetof(struct kdbus_cmd_conn_info, items) + item_size;
416                 cmd = alloca0_align(size, 8);
417                 cmd->items[0].size = item_size;
418                 cmd->items[0].type = KDBUS_ITEM_NAME;
419                 strcpy(cmd->items[0].str, name);
420         }
421
422         cmd->size = size;
423         kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
424
425         r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
426         if (r < 0)
427                 return -errno;
428
429         conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
430
431         /* Non-activated names are considered not available */
432         if (conn_info->flags & KDBUS_HELLO_ACTIVATOR)
433                 return name[0] == ':' ? -ENXIO : -ESRCH;
434
435         c = bus_creds_new();
436         if (!c)
437                 return -ENOMEM;
438
439         if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
440                 if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) conn_info->id) < 0)
441                         return -ENOMEM;
442
443                 c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
444         }
445
446         KDBUS_ITEM_FOREACH(item, conn_info, items) {
447
448                 switch (item->type) {
449
450                 case KDBUS_ITEM_CREDS:
451                         m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
452
453                         if (m) {
454                                 c->uid = (uid_t) item->creds.uid;
455                                 c->pid = (pid_t) item->creds.pid;
456                                 c->gid = (gid_t) item->creds.gid;
457                                 c->mask |= m;
458                         }
459
460                         if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
461                                 c->tid = (pid_t) item->creds.tid;
462                                 c->mask |= SD_BUS_CREDS_TID;
463                         }
464
465                         if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
466                                 c->pid_starttime = item->creds.starttime;
467                                 c->mask |= SD_BUS_CREDS_PID_STARTTIME;
468                         }
469
470                         break;
471
472                 case KDBUS_ITEM_PID_COMM:
473                         if (mask & SD_BUS_CREDS_COMM) {
474                                 c->comm = strdup(item->str);
475                                 if (!c->comm) {
476                                         r = -ENOMEM;
477                                         goto fail;
478                                 }
479
480                                 c->mask |= SD_BUS_CREDS_COMM;
481                         }
482                         break;
483
484                 case KDBUS_ITEM_TID_COMM:
485                         if (mask & SD_BUS_CREDS_TID_COMM) {
486                                 c->tid_comm = strdup(item->str);
487                                 if (!c->tid_comm) {
488                                         r = -ENOMEM;
489                                         goto fail;
490                                 }
491
492                                 c->mask |= SD_BUS_CREDS_TID_COMM;
493                         }
494                         break;
495
496                 case KDBUS_ITEM_EXE:
497                         if (mask & SD_BUS_CREDS_EXE) {
498                                 c->exe = strdup(item->str);
499                                 if (!c->exe) {
500                                         r = -ENOMEM;
501                                         goto fail;
502                                 }
503
504                                 c->mask |= SD_BUS_CREDS_EXE;
505                         }
506                         break;
507
508                 case KDBUS_ITEM_CMDLINE:
509                         if (mask & SD_BUS_CREDS_CMDLINE) {
510                                 c->cmdline_size = item->size - KDBUS_ITEM_HEADER_SIZE;
511                                 c->cmdline = memdup(item->data, c->cmdline_size);
512                                 if (!c->cmdline) {
513                                         r = -ENOMEM;
514                                         goto fail;
515                                 }
516
517                                 c->mask |= SD_BUS_CREDS_CMDLINE;
518                         }
519                         break;
520
521                 case KDBUS_ITEM_CGROUP:
522                         m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
523                              SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
524                              SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
525
526                         if (m) {
527                                 c->cgroup = strdup(item->str);
528                                 if (!c->cgroup) {
529                                         r = -ENOMEM;
530                                         goto fail;
531                                 }
532
533                                 r = bus_get_root_path(bus);
534                                 if (r < 0)
535                                         goto fail;
536
537                                 c->cgroup_root = strdup(bus->cgroup_root);
538                                 if (!c->cgroup_root) {
539                                         r = -ENOMEM;
540                                         goto fail;
541                                 }
542
543                                 c->mask |= m;
544                         }
545                         break;
546
547                 case KDBUS_ITEM_CAPS:
548                         m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
549                              SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
550
551                         if (m) {
552                                 c->capability_size = item->size - KDBUS_ITEM_HEADER_SIZE;
553                                 c->capability = memdup(item->data, c->capability_size);
554                                 if (!c->capability) {
555                                         r = -ENOMEM;
556                                         goto fail;
557                                 }
558
559                                 c->mask |= m;
560                         }
561                         break;
562
563                 case KDBUS_ITEM_SECLABEL:
564                         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
565                                 c->label = strdup(item->str);
566                                 if (!c->label) {
567                                         r = -ENOMEM;
568                                         goto fail;
569                                 }
570
571                                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
572                         }
573                         break;
574
575                 case KDBUS_ITEM_AUDIT:
576                         m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask;
577
578                         if (m) {
579                                 c->audit_session_id = item->audit.sessionid;
580                                 c->audit_login_uid = item->audit.loginuid;
581                                 c->mask |= m;
582                         }
583                         break;
584
585                 case KDBUS_ITEM_NAME:
586                         if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
587                                 r = strv_extend(&c->well_known_names, item->name.name);
588                                 if (r < 0)
589                                         goto fail;
590
591                                 c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
592                         }
593                         break;
594
595                 case KDBUS_ITEM_CONN_NAME:
596                         if ((mask & SD_BUS_CREDS_CONNECTION_NAME)) {
597                                 c->conn_name = strdup(item->str);
598                                 if (!c->conn_name) {
599                                         r = -ENOMEM;
600                                         goto fail;
601                                 }
602
603                                 c->mask |= SD_BUS_CREDS_CONNECTION_NAME;
604                         }
605                         break;
606                 }
607         }
608
609         if (creds) {
610                 *creds = c;
611                 c = NULL;
612         }
613
614         r = 0;
615
616 fail:
617         kernel_cmd_free(bus, cmd->offset);
618         return r;
619 }
620
621 static int bus_get_owner_dbus1(
622                 sd_bus *bus,
623                 const char *name,
624                 uint64_t mask,
625                 sd_bus_creds **creds) {
626
627         _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL;
628         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
629         const char *unique = NULL;
630         pid_t pid = 0;
631         int r;
632
633         /* Only query the owner if the caller wants to know it or if
634          * the caller just wants to check whether a name exists */
635         if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
636                 r = sd_bus_call_method(
637                                 bus,
638                                 "org.freedesktop.DBus",
639                                 "/org/freedesktop/DBus",
640                                 "org.freedesktop.DBus",
641                                 "GetNameOwner",
642                                 NULL,
643                                 &reply_unique,
644                                 "s",
645                                 name);
646                 if (r < 0)
647                         return r;
648
649                 r = sd_bus_message_read(reply_unique, "s", &unique);
650                 if (r < 0)
651                         return r;
652         }
653
654         if (mask != 0) {
655                 c = bus_creds_new();
656                 if (!c)
657                         return -ENOMEM;
658
659                 if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
660                         c->unique_name = strdup(unique);
661                         if (!c->unique_name)
662                                 return -ENOMEM;
663
664                         c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
665                 }
666
667                 if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
668                             SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
669                             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|
670                             SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
671                             SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
672                         uint32_t u;
673
674                         r = sd_bus_call_method(
675                                         bus,
676                                         "org.freedesktop.DBus",
677                                         "/org/freedesktop/DBus",
678                                         "org.freedesktop.DBus",
679                                         "GetConnectionUnixProcessID",
680                                         NULL,
681                                         &reply,
682                                         "s",
683                                         unique ? unique : name);
684                         if (r < 0)
685                                 return r;
686
687                         r = sd_bus_message_read(reply, "u", &u);
688                         if (r < 0)
689                                 return r;
690
691                         pid = u;
692                         if (mask & SD_BUS_CREDS_PID) {
693                                 c->pid = u;
694                                 c->mask |= SD_BUS_CREDS_PID;
695                         }
696
697                         reply = sd_bus_message_unref(reply);
698                 }
699
700                 if (mask & SD_BUS_CREDS_UID) {
701                         uint32_t u;
702
703                         r = sd_bus_call_method(
704                                         bus,
705                                         "org.freedesktop.DBus",
706                                         "/org/freedesktop/DBus",
707                                         "org.freedesktop.DBus",
708                                         "GetConnectionUnixUser",
709                                         NULL,
710                                         &reply,
711                                         "s",
712                                         unique ? unique : name);
713                         if (r < 0)
714                                 return r;
715
716                         r = sd_bus_message_read(reply, "u", &u);
717                         if (r < 0)
718                                 return r;
719
720                         c->uid = u;
721                         c->mask |= SD_BUS_CREDS_UID;
722
723                         reply = sd_bus_message_unref(reply);
724                 }
725
726                 if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
727                         const void *p = NULL;
728                         size_t sz = 0;
729
730                         r = sd_bus_call_method(
731                                         bus,
732                                         "org.freedesktop.DBus",
733                                         "/org/freedesktop/DBus",
734                                         "org.freedesktop.DBus",
735                                         "GetConnectionSELinuxSecurityContext",
736                                         NULL,
737                                         &reply,
738                                         "s",
739                                         unique ? unique : name);
740                         if (r < 0)
741                                 return r;
742
743                         r = sd_bus_message_read_array(reply, 'y', &p, &sz);
744                         if (r < 0)
745                                 return r;
746
747                         c->label = strndup(p, sz);
748                         if (!c->label)
749                                 return -ENOMEM;
750
751                         c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
752                 }
753
754                 r = bus_creds_add_more(c, mask, pid, 0);
755                 if (r < 0)
756                         return r;
757         }
758
759         if (creds) {
760                 *creds = c;
761                 c = NULL;
762         }
763
764         return 0;
765 }
766
767 _public_ int sd_bus_get_owner(
768                 sd_bus *bus,
769                 const char *name,
770                 uint64_t mask,
771                 sd_bus_creds **creds) {
772
773         assert_return(bus, -EINVAL);
774         assert_return(name, -EINVAL);
775         assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
776         assert_return(mask == 0 || creds, -EINVAL);
777         assert_return(!bus_pid_changed(bus), -ECHILD);
778         assert_return(service_name_is_valid(name), -EINVAL);
779         assert_return(bus->bus_client, -ENODATA);
780
781         if (!BUS_IS_OPEN(bus->state))
782                 return -ENOTCONN;
783
784         if (bus->is_kernel)
785                 return bus_get_owner_kdbus(bus, name, mask, creds);
786         else
787                 return bus_get_owner_dbus1(bus, name, mask, creds);
788 }
789
790 static int add_name_change_match(sd_bus *bus,
791                                  uint64_t cookie,
792                                  const char *name,
793                                  const char *old_owner,
794                                  const char *new_owner) {
795
796         uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
797         int is_name_id = -1, r;
798         struct kdbus_item *item;
799
800         assert(bus);
801
802         /* If we encounter a match that could match against
803          * NameOwnerChanged messages, then we need to create
804          * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
805          * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
806          * multiple if the match is underspecified.
807          *
808          * The NameOwnerChanged signals take three parameters with
809          * unique or well-known names, but only some forms actually
810          * exist:
811          *
812          * WELLKNOWN, "", UNIQUE       â†’ KDBUS_ITEM_NAME_ADD
813          * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_ITEM_NAME_REMOVE
814          * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_ITEM_NAME_CHANGE
815          * UNIQUE, "", UNIQUE          â†’ KDBUS_ITEM_ID_ADD
816          * UNIQUE, UNIQUE, ""          â†’ KDBUS_ITEM_ID_REMOVE
817          *
818          * For the latter two the two unique names must be identical.
819          *
820          * */
821
822         if (name) {
823                 is_name_id = bus_kernel_parse_unique_name(name, &name_id);
824                 if (is_name_id < 0)
825                         return 0;
826         }
827
828         if (!isempty(old_owner)) {
829                 r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
830                 if (r < 0)
831                         return 0;
832                 if (r == 0)
833                         return 0;
834                 if (is_name_id > 0 && old_owner_id != name_id)
835                         return 0;
836         } else
837                 old_owner_id = KDBUS_MATCH_ID_ANY;
838
839         if (!isempty(new_owner)) {
840                 r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
841                 if (r < 0)
842                         return r;
843                 if (r == 0)
844                         return 0;
845                 if (is_name_id > 0 && new_owner_id != name_id)
846                         return 0;
847         } else
848                 new_owner_id = KDBUS_MATCH_ID_ANY;
849
850         if (is_name_id <= 0) {
851                 struct kdbus_cmd_match *m;
852                 size_t sz, l;
853
854                 /* If the name argument is missing or is a well-known
855                  * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
856                  * matches for it */
857
858                 l = name ? strlen(name) + 1 : 0;
859
860                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
861                             offsetof(struct kdbus_item, name_change) +
862                             offsetof(struct kdbus_notify_name_change, name) +
863                             l);
864
865                 m = alloca0_align(sz, 8);
866                 m->size = sz;
867                 m->cookie = cookie;
868
869                 item = m->items;
870                 item->size =
871                         offsetof(struct kdbus_item, name_change) +
872                         offsetof(struct kdbus_notify_name_change, name) +
873                         l;
874
875                 item->name_change.old_id.id = old_owner_id;
876                 item->name_change.new_id.id = new_owner_id;
877
878                 if (name)
879                         memcpy(item->name_change.name, name, l);
880
881                 /* If the old name is unset or empty, then
882                  * this can match against added names */
883                 if (!old_owner || old_owner[0] == 0) {
884                         item->type = KDBUS_ITEM_NAME_ADD;
885
886                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
887                         if (r < 0)
888                                 return -errno;
889                 }
890
891                 /* If the new name is unset or empty, then
892                  * this can match against removed names */
893                 if (!new_owner || new_owner[0] == 0) {
894                         item->type = KDBUS_ITEM_NAME_REMOVE;
895
896                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
897                         if (r < 0)
898                                 return -errno;
899                 }
900
901                 /* The CHANGE match we need in either case, because
902                  * what is reported as a name change by the kernel
903                  * might just be an owner change between starter and
904                  * normal clients. For userspace such a change should
905                  * be considered a removal/addition, hence let's
906                  * subscribe to this unconditionally. */
907                 item->type = KDBUS_ITEM_NAME_CHANGE;
908                 r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
909                 if (r < 0)
910                         return -errno;
911         }
912
913         if (is_name_id != 0) {
914                 struct kdbus_cmd_match *m;
915                 uint64_t sz;
916
917                 /* If the name argument is missing or is a unique
918                  * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
919                  * for it */
920
921                 sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
922                             offsetof(struct kdbus_item, id_change) +
923                             sizeof(struct kdbus_notify_id_change));
924
925                 m = alloca0_align(sz, 8);
926                 m->size = sz;
927                 m->cookie = cookie;
928
929                 item = m->items;
930                 item->size =
931                         offsetof(struct kdbus_item, id_change) +
932                         sizeof(struct kdbus_notify_id_change);
933                 item->id_change.id = name_id;
934
935                 /* If the old name is unset or empty, then this can
936                  * match against added ids */
937                 if (!old_owner || old_owner[0] == 0) {
938                         item->type = KDBUS_ITEM_ID_ADD;
939
940                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
941                         if (r < 0)
942                                 return -errno;
943                 }
944
945                 /* If thew new name is unset or empty, then this can
946                  * match against removed ids */
947                 if (!new_owner || new_owner[0] == 0) {
948                         item->type = KDBUS_ITEM_ID_REMOVE;
949
950                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
951                         if (r < 0)
952                                 return -errno;
953                 }
954         }
955
956         return 0;
957 }
958
959 int bus_add_match_internal_kernel(
960                 sd_bus *bus,
961                 struct bus_match_component *components,
962                 unsigned n_components,
963                 uint64_t cookie) {
964
965         struct kdbus_cmd_match *m;
966         struct kdbus_item *item;
967         uint64_t *bloom;
968         size_t sz;
969         const char *sender = NULL;
970         size_t sender_length = 0;
971         uint64_t src_id = KDBUS_MATCH_ID_ANY;
972         bool using_bloom = false;
973         unsigned i;
974         bool matches_name_change = true;
975         const char *name_change_arg[3] = {};
976         int r;
977
978         assert(bus);
979
980         bloom = alloca0(bus->bloom_size);
981
982         sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
983
984         for (i = 0; i < n_components; i++) {
985                 struct bus_match_component *c = &components[i];
986
987                 switch (c->type) {
988
989                 case BUS_MATCH_SENDER:
990                         if (!streq(c->value_str, "org.freedesktop.DBus"))
991                                 matches_name_change = false;
992
993                         r = bus_kernel_parse_unique_name(c->value_str, &src_id);
994                         if (r < 0)
995                                 return r;
996                         else if (r > 0)
997                                 sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
998                         else  {
999                                 sender = c->value_str;
1000                                 sender_length = strlen(sender);
1001                                 sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
1002                         }
1003
1004                         break;
1005
1006                 case BUS_MATCH_MESSAGE_TYPE:
1007                         if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
1008                                 matches_name_change = false;
1009
1010                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
1011                         using_bloom = true;
1012                         break;
1013
1014                 case BUS_MATCH_INTERFACE:
1015                         if (!streq(c->value_str, "org.freedesktop.DBus"))
1016                                 matches_name_change = false;
1017
1018                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
1019                         using_bloom = true;
1020                         break;
1021
1022                 case BUS_MATCH_MEMBER:
1023                         if (!streq(c->value_str, "NameOwnerChanged"))
1024                                 matches_name_change = false;
1025
1026                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
1027                         using_bloom = true;
1028                         break;
1029
1030                 case BUS_MATCH_PATH:
1031                         if (!streq(c->value_str, "/org/freedesktop/DBus"))
1032                                 matches_name_change = false;
1033
1034                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
1035                         using_bloom = true;
1036                         break;
1037
1038                 case BUS_MATCH_PATH_NAMESPACE:
1039                         if (!streq(c->value_str, "/")) {
1040                                 bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
1041                                 using_bloom = true;
1042                         }
1043                         break;
1044
1045                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
1046                         char buf[sizeof("arg")-1 + 2 + 1];
1047
1048                         if (c->type - BUS_MATCH_ARG < 3)
1049                                 name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
1050
1051                         snprintf(buf, sizeof(buf), "arg%u", c->type - BUS_MATCH_ARG);
1052                         bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
1053                         using_bloom = true;
1054                         break;
1055                 }
1056
1057                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
1058                         char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
1059
1060                         snprintf(buf, sizeof(buf), "arg%u-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
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_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
1067                         char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
1068
1069                         snprintf(buf, sizeof(buf), "arg%u-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
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_DESTINATION:
1076                         /* The bloom filter does not include
1077                            the destination, since it is only
1078                            available for broadcast messages
1079                            which do not carry a destination
1080                            since they are undirected. */
1081                         break;
1082
1083                 case BUS_MATCH_ROOT:
1084                 case BUS_MATCH_VALUE:
1085                 case BUS_MATCH_LEAF:
1086                 case _BUS_MATCH_NODE_TYPE_MAX:
1087                 case _BUS_MATCH_NODE_TYPE_INVALID:
1088                         assert_not_reached("Invalid match type?");
1089                 }
1090         }
1091
1092         if (using_bloom)
1093                 sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
1094
1095         m = alloca0_align(sz, 8);
1096         m->size = sz;
1097         m->cookie = cookie;
1098
1099         item = m->items;
1100
1101         if (src_id != KDBUS_MATCH_ID_ANY) {
1102                 item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
1103                 item->type = KDBUS_ITEM_ID;
1104                 item->id = src_id;
1105                 item = KDBUS_ITEM_NEXT(item);
1106         }
1107
1108         if (using_bloom) {
1109                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
1110                 item->type = KDBUS_ITEM_BLOOM_MASK;
1111                 memcpy(item->data64, bloom, bus->bloom_size);
1112                 item = KDBUS_ITEM_NEXT(item);
1113         }
1114
1115         if (sender) {
1116                 item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
1117                 item->type = KDBUS_ITEM_NAME;
1118                 memcpy(item->str, sender, sender_length + 1);
1119         }
1120
1121         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
1122         if (r < 0)
1123                 return -errno;
1124
1125         if (matches_name_change) {
1126
1127                 /* If this match could theoretically match
1128                  * NameOwnerChanged messages, we need to
1129                  * install a second non-bloom filter explitly
1130                  * for it */
1131
1132                 r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
1133                 if (r < 0)
1134                         return r;
1135         }
1136
1137         return 0;
1138 }
1139
1140 #define internal_match(bus, m)                                          \
1141         ((bus)->hello_flags & KDBUS_HELLO_MONITOR                       \
1142          ? (isempty(m) ? "eavesdrop='true'" : strappenda((m), ",eavesdrop='true'")) \
1143          : (m))
1144
1145 static int bus_add_match_internal_dbus1(
1146                 sd_bus *bus,
1147                 const char *match) {
1148
1149         const char *e;
1150
1151         assert(bus);
1152         assert(match);
1153
1154         e = internal_match(bus, match);
1155
1156         return sd_bus_call_method(
1157                         bus,
1158                         "org.freedesktop.DBus",
1159                         "/org/freedesktop/DBus",
1160                         "org.freedesktop.DBus",
1161                         "AddMatch",
1162                         NULL,
1163                         NULL,
1164                         "s",
1165                         e);
1166 }
1167
1168 int bus_add_match_internal(
1169                 sd_bus *bus,
1170                 const char *match,
1171                 struct bus_match_component *components,
1172                 unsigned n_components,
1173                 uint64_t cookie) {
1174
1175         assert(bus);
1176
1177         if (bus->is_kernel)
1178                 return bus_add_match_internal_kernel(bus, components, n_components, cookie);
1179         else
1180                 return bus_add_match_internal_dbus1(bus, match);
1181 }
1182
1183 int bus_remove_match_internal_kernel(
1184                 sd_bus *bus,
1185                 uint64_t cookie) {
1186
1187         struct kdbus_cmd_match m;
1188         int r;
1189
1190         assert(bus);
1191
1192         zero(m);
1193         m.size = offsetof(struct kdbus_cmd_match, items);
1194         m.cookie = cookie;
1195
1196         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
1197         if (r < 0)
1198                 return -errno;
1199
1200         return 0;
1201 }
1202
1203 static int bus_remove_match_internal_dbus1(
1204                 sd_bus *bus,
1205                 const char *match) {
1206
1207         const char *e;
1208
1209         assert(bus);
1210         assert(match);
1211
1212         e = internal_match(bus, match);
1213
1214         return sd_bus_call_method(
1215                         bus,
1216                         "org.freedesktop.DBus",
1217                         "/org/freedesktop/DBus",
1218                         "org.freedesktop.DBus",
1219                         "RemoveMatch",
1220                         NULL,
1221                         NULL,
1222                         "s",
1223                         e);
1224 }
1225
1226 int bus_remove_match_internal(
1227                 sd_bus *bus,
1228                 const char *match,
1229                 uint64_t cookie) {
1230
1231         assert(bus);
1232
1233         if (bus->is_kernel)
1234                 return bus_remove_match_internal_kernel(bus, cookie);
1235         else
1236                 return bus_remove_match_internal_dbus1(bus, match);
1237 }
1238
1239 _public_ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
1240         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL;
1241         const char *mid;
1242         int r;
1243
1244         assert_return(bus, -EINVAL);
1245         assert_return(name, -EINVAL);
1246         assert_return(machine, -EINVAL);
1247         assert_return(!bus_pid_changed(bus), -ECHILD);
1248         assert_return(service_name_is_valid(name), -EINVAL);
1249
1250         if (!BUS_IS_OPEN(bus->state))
1251                 return -ENOTCONN;
1252
1253         if (streq_ptr(name, bus->unique_name))
1254                 return sd_id128_get_machine(machine);
1255
1256         r = sd_bus_message_new_method_call(
1257                         bus,
1258                         &m,
1259                         name,
1260                         "/",
1261                         "org.freedesktop.DBus.Peer",
1262                         "GetMachineId");
1263         if (r < 0)
1264                 return r;
1265
1266         r = sd_bus_message_set_auto_start(m, false);
1267         if (r < 0)
1268                 return r;
1269
1270         r = sd_bus_call(bus, m, 0, NULL, &reply);
1271         if (r < 0)
1272                 return r;
1273
1274         r = sd_bus_message_read(reply, "s", &mid);
1275         if (r < 0)
1276                 return r;
1277
1278         return sd_id128_from_string(mid, machine);
1279 }