1    	/* SPDX-License-Identifier: LGPL-2.1+ */
2    	
3    	#if HAVE_VALGRIND_MEMCHECK_H
4    	#include <valgrind/memcheck.h>
5    	#endif
6    	
7    	#include <errno.h>
8    	#include <stddef.h>
9    	
10   	#include "sd-bus.h"
11   	
12   	#include "alloc-util.h"
13   	#include "bus-control.h"
14   	#include "bus-internal.h"
15   	#include "bus-message.h"
16   	#include "bus-util.h"
17   	#include "capability-util.h"
18   	#include "process-util.h"
19   	#include "stdio-util.h"
20   	#include "string-util.h"
21   	#include "strv.h"
22   	#include "user-util.h"
23   	
24   	_public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
25   	        int r;
26   	
27   	        assert_return(bus, -EINVAL);
28   	        assert_return(bus = bus_resolve(bus), -ENOPKG);
29   	        assert_return(unique, -EINVAL);
30   	        assert_return(!bus_pid_changed(bus), -ECHILD);
31   	
32   	        if (!bus->bus_client)
33   	                return -EINVAL;
34   	
35   	        r = bus_ensure_running(bus);
36   	        if (r < 0)
37   	                return r;
38   	
39   	        *unique = bus->unique_name;
40   	        return 0;
41   	}
42   	
43   	static int validate_request_name_parameters(
44   	                sd_bus *bus,
45   	                const char *name,
46   	                uint64_t flags,
47   	                uint32_t *ret_param) {
48   	
49   	        uint32_t param = 0;
50   	
51   	        assert(bus);
52   	        assert(name);
53   	        assert(ret_param);
54   	
55   	        assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL);
56   	        assert_return(service_name_is_valid(name), -EINVAL);
57   	        assert_return(name[0] != ':', -EINVAL);
58   	
59   	        if (!bus->bus_client)
60   	                return -EINVAL;
61   	
62   	        /* Don't allow requesting the special driver and local names */
63   	        if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
64   	                return -EINVAL;
65   	
66   	        if (!BUS_IS_OPEN(bus->state))
67   	                return -ENOTCONN;
68   	
69   	        if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
70   	                param |= BUS_NAME_ALLOW_REPLACEMENT;
71   	        if (flags & SD_BUS_NAME_REPLACE_EXISTING)
72   	                param |= BUS_NAME_REPLACE_EXISTING;
73   	        if (!(flags & SD_BUS_NAME_QUEUE))
74   	                param |= BUS_NAME_DO_NOT_QUEUE;
75   	
76   	        *ret_param = param;
77   	
78   	        return 0;
79   	}
80   	
81   	_public_ int sd_bus_request_name(
82   	                sd_bus *bus,
83   	                const char *name,
84   	                uint64_t flags) {
85   	
86   	        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
87   	        uint32_t ret, param = 0;
88   	        int r;
89   	
90   	        assert_return(bus, -EINVAL);
(1) Event assignment_where_comparison_intended: Assignment "bus = bus_resolve(bus)" has a side effect. This code will work differently in a non-debug build.
(2) Event remediation: Did you intend to use a comparison ("==") instead?
91   	        assert_return(bus = bus_resolve(bus), -ENOPKG);
92   	        assert_return(name, -EINVAL);
93   	        assert_return(!bus_pid_changed(bus), -ECHILD);
94   	
95   	        r = validate_request_name_parameters(bus, name, flags, &param);
96   	        if (r < 0)
97   	                return r;
98   	
99   	        r = sd_bus_call_method(
100  	                        bus,
101  	                        "org.freedesktop.DBus",
102  	                        "/org/freedesktop/DBus",
103  	                        "org.freedesktop.DBus",
104  	                        "RequestName",
105  	                        NULL,
106  	                        &reply,
107  	                        "su",
108  	                        name,
109  	                        param);
110  	        if (r < 0)
111  	                return r;
112  	
113  	        r = sd_bus_message_read(reply, "u", &ret);
114  	        if (r < 0)
115  	                return r;
116  	
117  	        switch (ret) {
118  	
119  	        case BUS_NAME_ALREADY_OWNER:
120  	                return -EALREADY;
121  	
122  	        case BUS_NAME_EXISTS:
123  	                return -EEXIST;
124  	
125  	        case BUS_NAME_IN_QUEUE:
126  	                return 0;
127  	
128  	        case BUS_NAME_PRIMARY_OWNER:
129  	                return 1;
130  	        }
131  	
132  	        return -EIO;
133  	}
134  	
135  	static int default_request_name_handler(
136  	                sd_bus_message *m,
137  	                void *userdata,
138  	                sd_bus_error *ret_error) {
139  	
140  	        uint32_t ret;
141  	        int r;
142  	
143  	        assert(m);
144  	
145  	        if (sd_bus_message_is_method_error(m, NULL)) {
146  	                log_debug_errno(sd_bus_message_get_errno(m),
147  	                                "Unable to request name, failing connection: %s",
148  	                                sd_bus_message_get_error(m)->message);
149  	
150  	                bus_enter_closing(sd_bus_message_get_bus(m));
151  	                return 1;
152  	        }
153  	
154  	        r = sd_bus_message_read(m, "u", &ret);
155  	        if (r < 0)
156  	                return r;
157  	
158  	        switch (ret) {
159  	
160  	        case BUS_NAME_ALREADY_OWNER:
161  	                log_debug("Already owner of requested service name, ignoring.");
162  	                return 1;
163  	
164  	        case BUS_NAME_IN_QUEUE:
165  	                log_debug("In queue for requested service name.");
166  	                return 1;
167  	
168  	        case BUS_NAME_PRIMARY_OWNER:
169  	                log_debug("Successfully acquired requested service name.");
170  	                return 1;
171  	
172  	        case BUS_NAME_EXISTS:
173  	                log_debug("Requested service name already owned, failing connection.");
174  	                bus_enter_closing(sd_bus_message_get_bus(m));
175  	                return 1;
176  	        }
177  	
178  	        log_debug("Unexpected response from RequestName(), failing connection.");
179  	        bus_enter_closing(sd_bus_message_get_bus(m));
180  	        return 1;
181  	}
182  	
183  	_public_ int sd_bus_request_name_async(
184  	                sd_bus *bus,
185  	                sd_bus_slot **ret_slot,
186  	                const char *name,
187  	                uint64_t flags,
188  	                sd_bus_message_handler_t callback,
189  	                void *userdata) {
190  	
191  	        uint32_t param = 0;
192  	        int r;
193  	
194  	        assert_return(bus, -EINVAL);
195  	        assert_return(bus = bus_resolve(bus), -ENOPKG);
196  	        assert_return(name, -EINVAL);
197  	        assert_return(!bus_pid_changed(bus), -ECHILD);
198  	
199  	        r = validate_request_name_parameters(bus, name, flags, &param);
200  	        if (r < 0)
201  	                return r;
202  	
203  	        return sd_bus_call_method_async(
204  	                        bus,
205  	                        ret_slot,
206  	                        "org.freedesktop.DBus",
207  	                        "/org/freedesktop/DBus",
208  	                        "org.freedesktop.DBus",
209  	                        "RequestName",
210  	                        callback ?: default_request_name_handler,
211  	                        userdata,
212  	                        "su",
213  	                        name,
214  	                        param);
215  	}
216  	
217  	static int validate_release_name_parameters(
218  	                sd_bus *bus,
219  	                const char *name) {
220  	
221  	        assert(bus);
222  	        assert(name);
223  	
224  	        assert_return(service_name_is_valid(name), -EINVAL);
225  	        assert_return(name[0] != ':', -EINVAL);
226  	
227  	        if (!bus->bus_client)
228  	                return -EINVAL;
229  	
230  	        /* Don't allow releasing the special driver and local names */
231  	        if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local"))
232  	                return -EINVAL;
233  	
234  	        if (!BUS_IS_OPEN(bus->state))
235  	                return -ENOTCONN;
236  	
237  	        return 0;
238  	}
239  	
240  	_public_ int sd_bus_release_name(
241  	                sd_bus *bus,
242  	                const char *name) {
243  	
244  	        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
245  	        uint32_t ret;
246  	        int r;
247  	
248  	        assert_return(bus, -EINVAL);
249  	        assert_return(bus = bus_resolve(bus), -ENOPKG);
250  	        assert_return(name, -EINVAL);
251  	        assert_return(!bus_pid_changed(bus), -ECHILD);
252  	
253  	        r = validate_release_name_parameters(bus, name);
254  	        if (r < 0)
255  	                return r;
256  	
257  	        r = sd_bus_call_method(
258  	                        bus,
259  	                        "org.freedesktop.DBus",
260  	                        "/org/freedesktop/DBus",
261  	                        "org.freedesktop.DBus",
262  	                        "ReleaseName",
263  	                        NULL,
264  	                        &reply,
265  	                        "s",
266  	                        name);
267  	        if (r < 0)
268  	                return r;
269  	
270  	        r = sd_bus_message_read(reply, "u", &ret);
271  	        if (r < 0)
272  	                return r;
273  	
274  	        switch (ret) {
275  	
276  	        case BUS_NAME_NON_EXISTENT:
277  	                return -ESRCH;
278  	
279  	        case BUS_NAME_NOT_OWNER:
280  	                return -EADDRINUSE;
281  	
282  	        case BUS_NAME_RELEASED:
283  	                return 0;
284  	        }
285  	
286  	        return -EIO;
287  	}
288  	
289  	static int default_release_name_handler(
290  	                sd_bus_message *m,
291  	                void *userdata,
292  	                sd_bus_error *ret_error) {
293  	
294  	        uint32_t ret;
295  	        int r;
296  	
297  	        assert(m);
298  	
299  	        if (sd_bus_message_is_method_error(m, NULL)) {
300  	                log_debug_errno(sd_bus_message_get_errno(m),
301  	                                "Unable to release name, failing connection: %s",
302  	                                sd_bus_message_get_error(m)->message);
303  	
304  	                bus_enter_closing(sd_bus_message_get_bus(m));
305  	                return 1;
306  	        }
307  	
308  	        r = sd_bus_message_read(m, "u", &ret);
309  	        if (r < 0)
310  	                return r;
311  	
312  	        switch (ret) {
313  	
314  	        case BUS_NAME_NON_EXISTENT:
315  	                log_debug("Name asked to release is not taken currently, ignoring.");
316  	                return 1;
317  	
318  	        case BUS_NAME_NOT_OWNER:
319  	                log_debug("Name asked to release is owned by somebody else, ignoring.");
320  	                return 1;
321  	
322  	        case BUS_NAME_RELEASED:
323  	                log_debug("Name successfully released.");
324  	                return 1;
325  	        }
326  	
327  	        log_debug("Unexpected response from ReleaseName(), failing connection.");
328  	        bus_enter_closing(sd_bus_message_get_bus(m));
329  	        return 1;
330  	}
331  	
332  	_public_ int sd_bus_release_name_async(
333  	                sd_bus *bus,
334  	                sd_bus_slot **ret_slot,
335  	                const char *name,
336  	                sd_bus_message_handler_t callback,
337  	                void *userdata) {
338  	
339  	        int r;
340  	
341  	        assert_return(bus, -EINVAL);
342  	        assert_return(bus = bus_resolve(bus), -ENOPKG);
343  	        assert_return(name, -EINVAL);
344  	        assert_return(!bus_pid_changed(bus), -ECHILD);
345  	
346  	        r = validate_release_name_parameters(bus, name);
347  	        if (r < 0)
348  	                return r;
349  	
350  	        return sd_bus_call_method_async(
351  	                        bus,
352  	                        ret_slot,
353  	                        "org.freedesktop.DBus",
354  	                        "/org/freedesktop/DBus",
355  	                        "org.freedesktop.DBus",
356  	                        "ReleaseName",
357  	                        callback ?: default_release_name_handler,
358  	                        userdata,
359  	                        "s",
360  	                        name);
361  	}
362  	
363  	_public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) {
364  	        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
365  	        _cleanup_strv_free_ char **x = NULL, **y = NULL;
366  	        int r;
367  	
368  	        assert_return(bus, -EINVAL);
369  	        assert_return(bus = bus_resolve(bus), -ENOPKG);
370  	        assert_return(acquired || activatable, -EINVAL);
371  	        assert_return(!bus_pid_changed(bus), -ECHILD);
372  	
373  	        if (!bus->bus_client)
374  	                return -EINVAL;
375  	
376  	        if (!BUS_IS_OPEN(bus->state))
377  	                return -ENOTCONN;
378  	
379  	        if (acquired) {
380  	                r = sd_bus_call_method(
381  	                                bus,
382  	                                "org.freedesktop.DBus",
383  	                                "/org/freedesktop/DBus",
384  	                                "org.freedesktop.DBus",
385  	                                "ListNames",
386  	                                NULL,
387  	                                &reply,
388  	                                NULL);
389  	                if (r < 0)
390  	                        return r;
391  	
392  	                r = sd_bus_message_read_strv(reply, &x);
393  	                if (r < 0)
394  	                        return r;
395  	
396  	                reply = sd_bus_message_unref(reply);
397  	        }
398  	
399  	        if (activatable) {
400  	                r = sd_bus_call_method(
401  	                                bus,
402  	                                "org.freedesktop.DBus",
403  	                                "/org/freedesktop/DBus",
404  	                                "org.freedesktop.DBus",
405  	                                "ListActivatableNames",
406  	                                NULL,
407  	                                &reply,
408  	                                NULL);
409  	                if (r < 0)
410  	                        return r;
411  	
412  	                r = sd_bus_message_read_strv(reply, &y);
413  	                if (r < 0)
414  	                        return r;
415  	
416  	                *activatable = TAKE_PTR(y);
417  	        }
418  	
419  	        if (acquired)
420  	                *acquired = TAKE_PTR(x);
421  	
422  	        return 0;
423  	}
424  	
425  	_public_ int sd_bus_get_name_creds(
426  	                sd_bus *bus,
427  	                const char *name,
428  	                uint64_t mask,
429  	                sd_bus_creds **creds) {
430  	
431  	        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL;
432  	        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
433  	        const char *unique;
434  	        pid_t pid = 0;
435  	        int r;
436  	
437  	        assert_return(bus, -EINVAL);
438  	        assert_return(bus = bus_resolve(bus), -ENOPKG);
439  	        assert_return(name, -EINVAL);
440  	        assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
441  	        assert_return(mask == 0 || creds, -EINVAL);
442  	        assert_return(!bus_pid_changed(bus), -ECHILD);
443  	        assert_return(service_name_is_valid(name), -EINVAL);
444  	
445  	        if (!bus->bus_client)
446  	                return -EINVAL;
447  	
448  	        /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
449  	         * going to match. */
450  	        if (!bus->is_local)
451  	                mask &= ~SD_BUS_CREDS_AUGMENT;
452  	
453  	        if (streq(name, "org.freedesktop.DBus.Local"))
454  	                return -EINVAL;
455  	
456  	        if (streq(name, "org.freedesktop.DBus"))
457  	                return sd_bus_get_owner_creds(bus, mask, creds);
458  	
459  	        if (!BUS_IS_OPEN(bus->state))
460  	                return -ENOTCONN;
461  	
462  	        /* If the name is unique anyway, we can use it directly */
463  	        unique = name[0] == ':' ? name : NULL;
464  	
465  	        /* Only query the owner if the caller wants to know it and the name is not unique anyway, or if the caller just
466  	         * wants to check whether a name exists */
467  	        if ((FLAGS_SET(mask, SD_BUS_CREDS_UNIQUE_NAME) && !unique) || mask == 0) {
468  	                r = sd_bus_call_method(
469  	                                bus,
470  	                                "org.freedesktop.DBus",
471  	                                "/org/freedesktop/DBus",
472  	                                "org.freedesktop.DBus",
473  	                                "GetNameOwner",
474  	                                NULL,
475  	                                &reply_unique,
476  	                                "s",
477  	                                name);
478  	                if (r < 0)
479  	                        return r;
480  	
481  	                r = sd_bus_message_read(reply_unique, "s", &unique);
482  	                if (r < 0)
483  	                        return r;
484  	        }
485  	
486  	        if (mask != 0) {
487  	                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
488  	                bool need_pid, need_uid, need_selinux, need_separate_calls;
489  	
490  	                c = bus_creds_new();
491  	                if (!c)
492  	                        return -ENOMEM;
493  	
494  	                if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) {
495  	                        c->unique_name = strdup(unique);
496  	                        if (!c->unique_name)
497  	                                return -ENOMEM;
498  	
499  	                        c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
500  	                }
501  	
502  	                need_pid = (mask & SD_BUS_CREDS_PID) ||
503  	                        ((mask & SD_BUS_CREDS_AUGMENT) &&
504  	                         (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
505  	                                  SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
506  	                                  SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
507  	                                  SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
508  	                                  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|
509  	                                  SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
510  	                                  SD_BUS_CREDS_SELINUX_CONTEXT|
511  	                                  SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)));
512  	                need_uid = mask & SD_BUS_CREDS_EUID;
513  	                need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT;
514  	
515  	                if (need_pid + need_uid + need_selinux > 1) {
516  	
517  	                        /* If we need more than one of the credentials, then use GetConnectionCredentials() */
518  	
519  	                        r = sd_bus_call_method(
520  	                                        bus,
521  	                                        "org.freedesktop.DBus",
522  	                                        "/org/freedesktop/DBus",
523  	                                        "org.freedesktop.DBus",
524  	                                        "GetConnectionCredentials",
525  	                                        &error,
526  	                                        &reply,
527  	                                        "s",
528  	                                        unique ?: name);
529  	
530  	                        if (r < 0) {
531  	
532  	                                if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD))
533  	                                        return r;
534  	
535  	                                /* If we got an unknown method error, fall back to the individual calls... */
536  	                                need_separate_calls = true;
537  	                                sd_bus_error_free(&error);
538  	
539  	                        } else {
540  	                                need_separate_calls = false;
541  	
542  	                                r = sd_bus_message_enter_container(reply, 'a', "{sv}");
543  	                                if (r < 0)
544  	                                        return r;
545  	
546  	                                for (;;) {
547  	                                        const char *m;
548  	
549  	                                        r = sd_bus_message_enter_container(reply, 'e', "sv");
550  	                                        if (r < 0)
551  	                                                return r;
552  	                                        if (r == 0)
553  	                                                break;
554  	
555  	                                        r = sd_bus_message_read(reply, "s", &m);
556  	                                        if (r < 0)
557  	                                                return r;
558  	
559  	                                        if (need_uid && streq(m, "UnixUserID")) {
560  	                                                uint32_t u;
561  	
562  	                                                r = sd_bus_message_read(reply, "v", "u", &u);
563  	                                                if (r < 0)
564  	                                                        return r;
565  	
566  	                                                c->euid = u;
567  	                                                c->mask |= SD_BUS_CREDS_EUID;
568  	
569  	                                        } else if (need_pid && streq(m, "ProcessID")) {
570  	                                                uint32_t p;
571  	
572  	                                                r = sd_bus_message_read(reply, "v", "u", &p);
573  	                                                if (r < 0)
574  	                                                        return r;
575  	
576  	                                                pid = p;
577  	                                                if (mask & SD_BUS_CREDS_PID) {
578  	                                                        c->pid = p;
579  	                                                        c->mask |= SD_BUS_CREDS_PID;
580  	                                                }
581  	
582  	                                        } else if (need_selinux && streq(m, "LinuxSecurityLabel")) {
583  	                                                const void *p = NULL;
584  	                                                size_t sz = 0;
585  	
586  	                                                r = sd_bus_message_enter_container(reply, 'v', "ay");
587  	                                                if (r < 0)
588  	                                                        return r;
589  	
590  	                                                r = sd_bus_message_read_array(reply, 'y', &p, &sz);
591  	                                                if (r < 0)
592  	                                                        return r;
593  	
594  	                                                free(c->label);
595  	                                                c->label = strndup(p, sz);
596  	                                                if (!c->label)
597  	                                                        return -ENOMEM;
598  	
599  	                                                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
600  	
601  	                                                r = sd_bus_message_exit_container(reply);
602  	                                                if (r < 0)
603  	                                                        return r;
604  	                                        } else {
605  	                                                r = sd_bus_message_skip(reply, "v");
606  	                                                if (r < 0)
607  	                                                        return r;
608  	                                        }
609  	
610  	                                        r = sd_bus_message_exit_container(reply);
611  	                                        if (r < 0)
612  	                                                return r;
613  	                                }
614  	
615  	                                r = sd_bus_message_exit_container(reply);
616  	                                if (r < 0)
617  	                                        return r;
618  	
619  	                                if (need_pid && pid == 0)
620  	                                        return -EPROTO;
621  	                        }
622  	
623  	                } else /* When we only need a single field, then let's use separate calls */
624  	                        need_separate_calls = true;
625  	
626  	                if (need_separate_calls) {
627  	                        if (need_pid) {
628  	                                uint32_t u;
629  	
630  	                                r = sd_bus_call_method(
631  	                                                bus,
632  	                                                "org.freedesktop.DBus",
633  	                                                "/org/freedesktop/DBus",
634  	                                                "org.freedesktop.DBus",
635  	                                                "GetConnectionUnixProcessID",
636  	                                                NULL,
637  	                                                &reply,
638  	                                                "s",
639  	                                                unique ?: name);
640  	                                if (r < 0)
641  	                                        return r;
642  	
643  	                                r = sd_bus_message_read(reply, "u", &u);
644  	                                if (r < 0)
645  	                                        return r;
646  	
647  	                                pid = u;
648  	                                if (mask & SD_BUS_CREDS_PID) {
649  	                                        c->pid = u;
650  	                                        c->mask |= SD_BUS_CREDS_PID;
651  	                                }
652  	
653  	                                reply = sd_bus_message_unref(reply);
654  	                        }
655  	
656  	                        if (need_uid) {
657  	                                uint32_t u;
658  	
659  	                                r = sd_bus_call_method(
660  	                                                bus,
661  	                                                "org.freedesktop.DBus",
662  	                                                "/org/freedesktop/DBus",
663  	                                                "org.freedesktop.DBus",
664  	                                                "GetConnectionUnixUser",
665  	                                                NULL,
666  	                                                &reply,
667  	                                                "s",
668  	                                                unique ?: name);
669  	                                if (r < 0)
670  	                                        return r;
671  	
672  	                                r = sd_bus_message_read(reply, "u", &u);
673  	                                if (r < 0)
674  	                                        return r;
675  	
676  	                                c->euid = u;
677  	                                c->mask |= SD_BUS_CREDS_EUID;
678  	
679  	                                reply = sd_bus_message_unref(reply);
680  	                        }
681  	
682  	                        if (need_selinux) {
683  	                                const void *p = NULL;
684  	                                size_t sz = 0;
685  	
686  	                                r = sd_bus_call_method(
687  	                                                bus,
688  	                                                "org.freedesktop.DBus",
689  	                                                "/org/freedesktop/DBus",
690  	                                                "org.freedesktop.DBus",
691  	                                                "GetConnectionSELinuxSecurityContext",
692  	                                                &error,
693  	                                                &reply,
694  	                                                "s",
695  	                                                unique ?: name);
696  	                                if (r < 0) {
697  	                                        if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown"))
698  	                                                return r;
699  	
700  	                                        /* no data is fine */
701  	                                } else {
702  	                                        r = sd_bus_message_read_array(reply, 'y', &p, &sz);
703  	                                        if (r < 0)
704  	                                                return r;
705  	
706  	                                        c->label = memdup_suffix0(p, sz);
707  	                                        if (!c->label)
708  	                                                return -ENOMEM;
709  	
710  	                                        c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
711  	                                }
712  	                        }
713  	                }
714  	
715  	                r = bus_creds_add_more(c, mask, pid, 0);
716  	                if (r < 0)
717  	                        return r;
718  	        }
719  	
720  	        if (creds)
721  	                *creds = TAKE_PTR(c);
722  	
723  	        return 0;
724  	}
725  	
726  	_public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
727  	        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
728  	        bool do_label, do_groups;
729  	        pid_t pid = 0;
730  	        int r;
731  	
732  	        assert_return(bus, -EINVAL);
733  	        assert_return(bus = bus_resolve(bus), -ENOPKG);
734  	        assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
735  	        assert_return(ret, -EINVAL);
736  	        assert_return(!bus_pid_changed(bus), -ECHILD);
737  	
738  	        if (!BUS_IS_OPEN(bus->state))
739  	                return -ENOTCONN;
740  	
741  	        if (!bus->is_local)
742  	                mask &= ~SD_BUS_CREDS_AUGMENT;
743  	
744  	        do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
745  	        do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS);
746  	
747  	        /* Avoid allocating anything if we have no chance of returning useful data */
748  	        if (!bus->ucred_valid && !do_label && !do_groups)
749  	                return -ENODATA;
750  	
751  	        c = bus_creds_new();
752  	        if (!c)
753  	                return -ENOMEM;
754  	
755  	        if (bus->ucred_valid) {
756  	                if (pid_is_valid(bus->ucred.pid)) {
757  	                        pid = c->pid = bus->ucred.pid;
758  	                        c->mask |= SD_BUS_CREDS_PID & mask;
759  	                }
760  	
761  	                if (uid_is_valid(bus->ucred.uid)) {
762  	                        c->euid = bus->ucred.uid;
763  	                        c->mask |= SD_BUS_CREDS_EUID & mask;
764  	                }
765  	
766  	                if (gid_is_valid(bus->ucred.gid)) {
767  	                        c->egid = bus->ucred.gid;
768  	                        c->mask |= SD_BUS_CREDS_EGID & mask;
769  	                }
770  	        }
771  	
772  	        if (do_label) {
773  	                c->label = strdup(bus->label);
774  	                if (!c->label)
775  	                        return -ENOMEM;
776  	
777  	                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
778  	        }
779  	
780  	        if (do_groups) {
781  	                c->supplementary_gids = newdup(gid_t, bus->groups, bus->n_groups);
782  	                if (!c->supplementary_gids)
783  	                        return -ENOMEM;
784  	
785  	                c->n_supplementary_gids = bus->n_groups;
786  	
787  	                c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
788  	        }
789  	
790  	        r = bus_creds_add_more(c, mask, pid, 0);
791  	        if (r < 0)
792  	                return r;
793  	
794  	        *ret = TAKE_PTR(c);
795  	
796  	        return 0;
797  	}
798  	
799  	#define append_eavesdrop(bus, m)                                        \
800  	        ((bus)->is_monitor                                              \
801  	         ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
802  	         : (m))
803  	
804  	int bus_add_match_internal(
805  	                sd_bus *bus,
806  	                const char *match,
807  	                uint64_t *ret_counter) {
808  	
809  	        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
810  	        const char *e;
811  	        int r;
812  	
813  	        assert(bus);
814  	
815  	        if (!bus->bus_client)
816  	                return -EINVAL;
817  	
818  	        e = append_eavesdrop(bus, match);
819  	
820  	        r = sd_bus_call_method(
821  	                        bus,
822  	                        "org.freedesktop.DBus",
823  	                        "/org/freedesktop/DBus",
824  	                        "org.freedesktop.DBus",
825  	                        "AddMatch",
826  	                        NULL,
827  	                        &reply,
828  	                        "s",
829  	                        e);
830  	        if (r < 0)
831  	                return r;
832  	
833  	        /* If the caller asked for it, return the read counter of the reply */
834  	        if (ret_counter)
835  	                *ret_counter = reply->read_counter;
836  	
837  	        return r;
838  	}
839  	
840  	int bus_add_match_internal_async(
841  	                sd_bus *bus,
842  	                sd_bus_slot **ret_slot,
843  	                const char *match,
844  	                sd_bus_message_handler_t callback,
845  	                void *userdata) {
846  	
847  	        const char *e;
848  	
849  	        assert(bus);
850  	
851  	        if (!bus->bus_client)
852  	                return -EINVAL;
853  	
854  	        e = append_eavesdrop(bus, match);
855  	
856  	        return sd_bus_call_method_async(
857  	                        bus,
858  	                        ret_slot,
859  	                        "org.freedesktop.DBus",
860  	                        "/org/freedesktop/DBus",
861  	                        "org.freedesktop.DBus",
862  	                        "AddMatch",
863  	                        callback,
864  	                        userdata,
865  	                        "s",
866  	                        e);
867  	}
868  	
869  	int bus_remove_match_internal(
870  	                sd_bus *bus,
871  	                const char *match) {
872  	
873  	        const char *e;
874  	
875  	        assert(bus);
876  	        assert(match);
877  	
878  	        if (!bus->bus_client)
879  	                return -EINVAL;
880  	
881  	        e = append_eavesdrop(bus, match);
882  	
883  	        /* Fire and forget */
884  	
885  	        return sd_bus_call_method_async(
886  	                        bus,
887  	                        NULL,
888  	                        "org.freedesktop.DBus",
889  	                        "/org/freedesktop/DBus",
890  	                        "org.freedesktop.DBus",
891  	                        "RemoveMatch",
892  	                        NULL,
893  	                        NULL,
894  	                        "s",
895  	                        e);
896  	}
897  	
898  	_public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
899  	        _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL;
900  	        const char *mid;
901  	        int r;
902  	
903  	        assert_return(bus, -EINVAL);
904  	        assert_return(bus = bus_resolve(bus), -ENOPKG);
905  	        assert_return(name, -EINVAL);
906  	        assert_return(machine, -EINVAL);
907  	        assert_return(!bus_pid_changed(bus), -ECHILD);
908  	        assert_return(service_name_is_valid(name), -EINVAL);
909  	
910  	        if (!bus->bus_client)
911  	                return -EINVAL;
912  	
913  	        if (!BUS_IS_OPEN(bus->state))
914  	                return -ENOTCONN;
915  	
916  	        if (streq_ptr(name, bus->unique_name))
917  	                return sd_id128_get_machine(machine);
918  	
919  	        r = sd_bus_message_new_method_call(
920  	                        bus,
921  	                        &m,
922  	                        name,
923  	                        "/",
924  	                        "org.freedesktop.DBus.Peer",
925  	                        "GetMachineId");
926  	        if (r < 0)
927  	                return r;
928  	
929  	        r = sd_bus_message_set_auto_start(m, false);
930  	        if (r < 0)
931  	                return r;
932  	
933  	        r = sd_bus_call(bus, m, 0, NULL, &reply);
934  	        if (r < 0)
935  	                return r;
936  	
937  	        r = sd_bus_message_read(reply, "s", &mid);
938  	        if (r < 0)
939  	                return r;
940  	
941  	        return sd_id128_from_string(mid, machine);
942  	}
943