]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
de1c301e LP |
2 | /*** |
3 | This file is part of systemd. | |
4 | ||
5 | Copyright 2013 Lennart Poettering | |
6 | ||
7 | systemd is free software; you can redistribute it and/or modify it | |
8 | under the terms of the GNU Lesser General Public License as published by | |
9 | the Free Software Foundation; either version 2.1 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | systemd is distributed in the hope that it will be useful, but | |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | Lesser General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU Lesser General Public License | |
18 | along with systemd; If not, see <http://www.gnu.org/licenses/>. | |
19 | ***/ | |
20 | ||
349cc4a5 | 21 | #if HAVE_VALGRIND_MEMCHECK_H |
75722f1d LP |
22 | #include <valgrind/memcheck.h> |
23 | #endif | |
24 | ||
de1c301e | 25 | #include <errno.h> |
cf0fbc49 | 26 | #include <stddef.h> |
de1c301e | 27 | |
de1c301e | 28 | #include "sd-bus.h" |
07630cea | 29 | |
b5efdb8a | 30 | #include "alloc-util.h" |
07630cea | 31 | #include "bus-bloom.h" |
ee104e11 | 32 | #include "bus-control.h" |
de1c301e LP |
33 | #include "bus-internal.h" |
34 | #include "bus-message.h" | |
057171ef | 35 | #include "bus-util.h" |
430f0182 | 36 | #include "capability-util.h" |
15a5e950 | 37 | #include "stdio-util.h" |
07630cea LP |
38 | #include "string-util.h" |
39 | #include "strv.h" | |
ee104e11 | 40 | #include "user-util.h" |
de1c301e | 41 | |
d9f644e2 | 42 | _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { |
20902f3e LP |
43 | int r; |
44 | ||
9bb058a1 LS |
45 | assert_return(bus, -EINVAL); |
46 | assert_return(unique, -EINVAL); | |
47 | assert_return(!bus_pid_changed(bus), -ECHILD); | |
20902f3e | 48 | |
33c62dcb LP |
49 | if (!bus->bus_client) |
50 | return -EINVAL; | |
51 | ||
20902f3e LP |
52 | r = bus_ensure_running(bus); |
53 | if (r < 0) | |
54 | return r; | |
de1c301e | 55 | |
20902f3e LP |
56 | *unique = bus->unique_name; |
57 | return 0; | |
de1c301e LP |
58 | } |
59 | ||
29a07cdb | 60 | static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) { |
4afd3348 | 61 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; |
29a07cdb | 62 | uint32_t ret, param = 0; |
de1c301e LP |
63 | int r; |
64 | ||
e7176abb LP |
65 | assert(bus); |
66 | assert(name); | |
67 | ||
29a07cdb LP |
68 | if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT) |
69 | param |= BUS_NAME_ALLOW_REPLACEMENT; | |
70 | if (flags & SD_BUS_NAME_REPLACE_EXISTING) | |
71 | param |= BUS_NAME_REPLACE_EXISTING; | |
72 | if (!(flags & SD_BUS_NAME_QUEUE)) | |
73 | param |= BUS_NAME_DO_NOT_QUEUE; | |
74 | ||
e7176abb LP |
75 | r = sd_bus_call_method( |
76 | bus, | |
77 | "org.freedesktop.DBus", | |
cd789fdf | 78 | "/org/freedesktop/DBus", |
e7176abb LP |
79 | "org.freedesktop.DBus", |
80 | "RequestName", | |
81 | NULL, | |
82 | &reply, | |
83 | "su", | |
84 | name, | |
29a07cdb | 85 | param); |
e7176abb LP |
86 | if (r < 0) |
87 | return r; | |
88 | ||
89 | r = sd_bus_message_read(reply, "u", &ret); | |
90 | if (r < 0) | |
91 | return r; | |
92 | ||
0461f8cd | 93 | if (ret == BUS_NAME_ALREADY_OWNER) |
e7176abb | 94 | return -EALREADY; |
0461f8cd | 95 | else if (ret == BUS_NAME_EXISTS) |
e7176abb | 96 | return -EEXIST; |
0461f8cd | 97 | else if (ret == BUS_NAME_IN_QUEUE) |
e7176abb | 98 | return 0; |
c0a09132 LP |
99 | else if (ret == BUS_NAME_PRIMARY_OWNER) |
100 | return 1; | |
e7176abb | 101 | |
c0a09132 | 102 | return -EIO; |
e7176abb LP |
103 | } |
104 | ||
29a07cdb | 105 | _public_ int sd_bus_request_name(sd_bus *bus, const char *name, uint64_t flags) { |
9bb058a1 LS |
106 | assert_return(bus, -EINVAL); |
107 | assert_return(name, -EINVAL); | |
9bb058a1 | 108 | assert_return(!bus_pid_changed(bus), -ECHILD); |
29a07cdb | 109 | assert_return(!(flags & ~(SD_BUS_NAME_ALLOW_REPLACEMENT|SD_BUS_NAME_REPLACE_EXISTING|SD_BUS_NAME_QUEUE)), -EINVAL); |
45fd5e4d LP |
110 | assert_return(service_name_is_valid(name), -EINVAL); |
111 | assert_return(name[0] != ':', -EINVAL); | |
de1c301e | 112 | |
33c62dcb LP |
113 | if (!bus->bus_client) |
114 | return -EINVAL; | |
115 | ||
210a6882 LP |
116 | /* Don't allow requesting the special driver and local names */ |
117 | if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) | |
118 | return -EINVAL; | |
119 | ||
a3d59cd1 LP |
120 | if (!BUS_IS_OPEN(bus->state)) |
121 | return -ENOTCONN; | |
122 | ||
a132bef0 | 123 | return bus_request_name_dbus1(bus, name, flags); |
de1c301e LP |
124 | } |
125 | ||
e7176abb | 126 | static int bus_release_name_dbus1(sd_bus *bus, const char *name) { |
4afd3348 | 127 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; |
e7176abb | 128 | uint32_t ret; |
de1c301e LP |
129 | int r; |
130 | ||
e7176abb LP |
131 | assert(bus); |
132 | assert(name); | |
133 | ||
134 | r = sd_bus_call_method( | |
135 | bus, | |
136 | "org.freedesktop.DBus", | |
cd789fdf | 137 | "/org/freedesktop/DBus", |
e7176abb LP |
138 | "org.freedesktop.DBus", |
139 | "ReleaseName", | |
140 | NULL, | |
141 | &reply, | |
142 | "s", | |
143 | name); | |
144 | if (r < 0) | |
145 | return r; | |
146 | ||
147 | r = sd_bus_message_read(reply, "u", &ret); | |
148 | if (r < 0) | |
149 | return r; | |
0461f8cd | 150 | if (ret == BUS_NAME_NON_EXISTENT) |
043ccd83 | 151 | return -ESRCH; |
0461f8cd | 152 | if (ret == BUS_NAME_NOT_OWNER) |
043ccd83 | 153 | return -EADDRINUSE; |
0461f8cd | 154 | if (ret == BUS_NAME_RELEASED) |
e7176abb LP |
155 | return 0; |
156 | ||
157 | return -EINVAL; | |
158 | } | |
159 | ||
160 | _public_ int sd_bus_release_name(sd_bus *bus, const char *name) { | |
9bb058a1 | 161 | assert_return(bus, -EINVAL); |
e7176abb | 162 | assert_return(name, -EINVAL); |
9bb058a1 | 163 | assert_return(!bus_pid_changed(bus), -ECHILD); |
45fd5e4d LP |
164 | assert_return(service_name_is_valid(name), -EINVAL); |
165 | assert_return(name[0] != ':', -EINVAL); | |
de1c301e | 166 | |
33c62dcb LP |
167 | if (!bus->bus_client) |
168 | return -EINVAL; | |
169 | ||
23539f67 | 170 | /* Don't allow releasing the special driver and local names */ |
210a6882 LP |
171 | if (STR_IN_SET(name, "org.freedesktop.DBus", "org.freedesktop.DBus.Local")) |
172 | return -EINVAL; | |
173 | ||
a3d59cd1 LP |
174 | if (!BUS_IS_OPEN(bus->state)) |
175 | return -ENOTCONN; | |
176 | ||
a132bef0 | 177 | return bus_release_name_dbus1(bus, name); |
71f2ab46 LP |
178 | } |
179 | ||
180 | static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatable) { | |
4afd3348 | 181 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; |
71f2ab46 LP |
182 | _cleanup_strv_free_ char **x = NULL, **y = NULL; |
183 | int r; | |
184 | ||
185 | if (acquired) { | |
186 | r = sd_bus_call_method( | |
187 | bus, | |
188 | "org.freedesktop.DBus", | |
cd789fdf | 189 | "/org/freedesktop/DBus", |
71f2ab46 LP |
190 | "org.freedesktop.DBus", |
191 | "ListNames", | |
192 | NULL, | |
193 | &reply, | |
194 | NULL); | |
195 | if (r < 0) | |
196 | return r; | |
197 | ||
198 | r = sd_bus_message_read_strv(reply, &x); | |
199 | if (r < 0) | |
200 | return r; | |
201 | ||
202 | reply = sd_bus_message_unref(reply); | |
203 | } | |
204 | ||
205 | if (activatable) { | |
206 | r = sd_bus_call_method( | |
207 | bus, | |
208 | "org.freedesktop.DBus", | |
cd789fdf | 209 | "/org/freedesktop/DBus", |
71f2ab46 LP |
210 | "org.freedesktop.DBus", |
211 | "ListActivatableNames", | |
212 | NULL, | |
213 | &reply, | |
214 | NULL); | |
215 | if (r < 0) | |
216 | return r; | |
217 | ||
218 | r = sd_bus_message_read_strv(reply, &y); | |
219 | if (r < 0) | |
220 | return r; | |
221 | ||
222 | *activatable = y; | |
223 | y = NULL; | |
224 | } | |
225 | ||
226 | if (acquired) { | |
227 | *acquired = x; | |
228 | x = NULL; | |
a4297f08 | 229 | } |
de1c301e | 230 | |
49b832c5 LP |
231 | return 0; |
232 | } | |
233 | ||
71f2ab46 | 234 | _public_ int sd_bus_list_names(sd_bus *bus, char ***acquired, char ***activatable) { |
e7176abb | 235 | assert_return(bus, -EINVAL); |
71f2ab46 | 236 | assert_return(acquired || activatable, -EINVAL); |
e7176abb LP |
237 | assert_return(!bus_pid_changed(bus), -ECHILD); |
238 | ||
33c62dcb LP |
239 | if (!bus->bus_client) |
240 | return -EINVAL; | |
241 | ||
a3d59cd1 LP |
242 | if (!BUS_IS_OPEN(bus->state)) |
243 | return -ENOTCONN; | |
244 | ||
a132bef0 | 245 | return bus_list_names_dbus1(bus, acquired, activatable); |
e7176abb LP |
246 | } |
247 | ||
056f95d0 | 248 | static int bus_get_name_creds_dbus1( |
e7176abb LP |
249 | sd_bus *bus, |
250 | const char *name, | |
251 | uint64_t mask, | |
252 | sd_bus_creds **creds) { | |
253 | ||
4afd3348 LP |
254 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply_unique = NULL, *reply = NULL; |
255 | _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; | |
e7176abb LP |
256 | const char *unique = NULL; |
257 | pid_t pid = 0; | |
258 | int r; | |
259 | ||
260 | /* Only query the owner if the caller wants to know it or if | |
261 | * the caller just wants to check whether a name exists */ | |
262 | if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) { | |
263 | r = sd_bus_call_method( | |
264 | bus, | |
265 | "org.freedesktop.DBus", | |
cd789fdf | 266 | "/org/freedesktop/DBus", |
e7176abb LP |
267 | "org.freedesktop.DBus", |
268 | "GetNameOwner", | |
269 | NULL, | |
270 | &reply_unique, | |
271 | "s", | |
272 | name); | |
273 | if (r < 0) | |
274 | return r; | |
275 | ||
276 | r = sd_bus_message_read(reply_unique, "s", &unique); | |
277 | if (r < 0) | |
278 | return r; | |
279 | } | |
280 | ||
281 | if (mask != 0) { | |
40f35505 LP |
282 | _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; |
283 | bool need_pid, need_uid, need_selinux, need_separate_calls; | |
e7176abb LP |
284 | c = bus_creds_new(); |
285 | if (!c) | |
286 | return -ENOMEM; | |
287 | ||
288 | if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) { | |
289 | c->unique_name = strdup(unique); | |
290 | if (!c->unique_name) | |
291 | return -ENOMEM; | |
292 | ||
293 | c->mask |= SD_BUS_CREDS_UNIQUE_NAME; | |
294 | } | |
49b832c5 | 295 | |
40f35505 LP |
296 | need_pid = (mask & SD_BUS_CREDS_PID) || |
297 | ((mask & SD_BUS_CREDS_AUGMENT) && | |
298 | (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID| | |
299 | SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID| | |
300 | SD_BUS_CREDS_SUPPLEMENTARY_GIDS| | |
301 | SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE| | |
302 | 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| | |
303 | SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS| | |
304 | SD_BUS_CREDS_SELINUX_CONTEXT| | |
305 | SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))); | |
306 | need_uid = mask & SD_BUS_CREDS_EUID; | |
307 | need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT; | |
705a415f | 308 | |
40f35505 LP |
309 | if (need_pid + need_uid + need_selinux > 1) { |
310 | ||
311 | /* If we need more than one of the credentials, then use GetConnectionCredentials() */ | |
49b832c5 | 312 | |
e7176abb LP |
313 | r = sd_bus_call_method( |
314 | bus, | |
315 | "org.freedesktop.DBus", | |
cd789fdf | 316 | "/org/freedesktop/DBus", |
e7176abb | 317 | "org.freedesktop.DBus", |
40f35505 LP |
318 | "GetConnectionCredentials", |
319 | &error, | |
e7176abb LP |
320 | &reply, |
321 | "s", | |
40f35505 | 322 | unique ?: name); |
49b832c5 | 323 | |
40f35505 | 324 | if (r < 0) { |
e7176abb | 325 | |
40f35505 LP |
326 | if (!sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) |
327 | return r; | |
49b832c5 | 328 | |
40f35505 LP |
329 | /* If we got an unknown method error, fall back to the invidual calls... */ |
330 | need_separate_calls = true; | |
331 | sd_bus_error_free(&error); | |
49b832c5 | 332 | |
40f35505 LP |
333 | } else { |
334 | need_separate_calls = false; | |
49b832c5 | 335 | |
40f35505 LP |
336 | r = sd_bus_message_enter_container(reply, 'a', "{sv}"); |
337 | if (r < 0) | |
338 | return r; | |
49b832c5 | 339 | |
40f35505 LP |
340 | for (;;) { |
341 | const char *m; | |
49b832c5 | 342 | |
40f35505 LP |
343 | r = sd_bus_message_enter_container(reply, 'e', "sv"); |
344 | if (r < 0) | |
345 | return r; | |
346 | if (r == 0) | |
347 | break; | |
49b832c5 | 348 | |
40f35505 LP |
349 | r = sd_bus_message_read(reply, "s", &m); |
350 | if (r < 0) | |
351 | return r; | |
49b832c5 | 352 | |
40f35505 LP |
353 | if (need_uid && streq(m, "UnixUserID")) { |
354 | uint32_t u; | |
49b832c5 | 355 | |
40f35505 LP |
356 | r = sd_bus_message_read(reply, "v", "u", &u); |
357 | if (r < 0) | |
358 | return r; | |
359 | ||
360 | c->euid = u; | |
361 | c->mask |= SD_BUS_CREDS_EUID; | |
362 | ||
363 | } else if (need_pid && streq(m, "ProcessID")) { | |
364 | uint32_t p; | |
365 | ||
366 | r = sd_bus_message_read(reply, "v", "u", &p); | |
367 | if (r < 0) | |
368 | return r; | |
369 | ||
370 | pid = p; | |
371 | if (mask & SD_BUS_CREDS_PID) { | |
372 | c->pid = p; | |
373 | c->mask |= SD_BUS_CREDS_PID; | |
374 | } | |
375 | ||
376 | } else if (need_selinux && streq(m, "LinuxSecurityLabel")) { | |
377 | const void *p = NULL; | |
378 | size_t sz = 0; | |
379 | ||
380 | r = sd_bus_message_enter_container(reply, 'v', "ay"); | |
381 | if (r < 0) | |
382 | return r; | |
383 | ||
384 | r = sd_bus_message_read_array(reply, 'y', &p, &sz); | |
385 | if (r < 0) | |
386 | return r; | |
387 | ||
388 | free(c->label); | |
389 | c->label = strndup(p, sz); | |
390 | if (!c->label) | |
391 | return -ENOMEM; | |
392 | ||
393 | c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; | |
394 | ||
395 | r = sd_bus_message_exit_container(reply); | |
396 | if (r < 0) | |
397 | return r; | |
398 | } else { | |
399 | r = sd_bus_message_skip(reply, "v"); | |
400 | if (r < 0) | |
401 | return r; | |
402 | } | |
403 | ||
404 | r = sd_bus_message_exit_container(reply); | |
405 | if (r < 0) | |
406 | return r; | |
407 | } | |
408 | ||
409 | r = sd_bus_message_exit_container(reply); | |
410 | if (r < 0) | |
359c09b1 | 411 | return r; |
40f35505 LP |
412 | |
413 | if (need_pid && pid == 0) | |
414 | return -EPROTO; | |
415 | } | |
416 | ||
417 | } else /* When we only need a single field, then let's use separate calls */ | |
418 | need_separate_calls = true; | |
419 | ||
420 | if (need_separate_calls) { | |
421 | if (need_pid) { | |
422 | uint32_t u; | |
423 | ||
424 | r = sd_bus_call_method( | |
425 | bus, | |
426 | "org.freedesktop.DBus", | |
427 | "/org/freedesktop/DBus", | |
428 | "org.freedesktop.DBus", | |
429 | "GetConnectionUnixProcessID", | |
430 | NULL, | |
431 | &reply, | |
432 | "s", | |
433 | unique ?: name); | |
359c09b1 LP |
434 | if (r < 0) |
435 | return r; | |
e7176abb | 436 | |
40f35505 LP |
437 | r = sd_bus_message_read(reply, "u", &u); |
438 | if (r < 0) | |
439 | return r; | |
e7176abb | 440 | |
40f35505 LP |
441 | pid = u; |
442 | if (mask & SD_BUS_CREDS_PID) { | |
443 | c->pid = u; | |
444 | c->mask |= SD_BUS_CREDS_PID; | |
445 | } | |
446 | ||
447 | reply = sd_bus_message_unref(reply); | |
448 | } | |
449 | ||
450 | if (need_uid) { | |
451 | uint32_t u; | |
452 | ||
453 | r = sd_bus_call_method( | |
454 | bus, | |
455 | "org.freedesktop.DBus", | |
456 | "/org/freedesktop/DBus", | |
457 | "org.freedesktop.DBus", | |
458 | "GetConnectionUnixUser", | |
459 | NULL, | |
460 | &reply, | |
461 | "s", | |
462 | unique ? unique : name); | |
463 | if (r < 0) | |
464 | return r; | |
465 | ||
466 | r = sd_bus_message_read(reply, "u", &u); | |
467 | if (r < 0) | |
468 | return r; | |
469 | ||
470 | c->euid = u; | |
471 | c->mask |= SD_BUS_CREDS_EUID; | |
472 | ||
473 | reply = sd_bus_message_unref(reply); | |
474 | } | |
475 | ||
476 | if (need_selinux) { | |
477 | const void *p = NULL; | |
478 | size_t sz = 0; | |
479 | ||
480 | r = sd_bus_call_method( | |
481 | bus, | |
482 | "org.freedesktop.DBus", | |
483 | "/org/freedesktop/DBus", | |
484 | "org.freedesktop.DBus", | |
485 | "GetConnectionSELinuxSecurityContext", | |
486 | &error, | |
487 | &reply, | |
488 | "s", | |
489 | unique ? unique : name); | |
490 | if (r < 0) { | |
491 | if (!sd_bus_error_has_name(&error, "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown")) | |
492 | return r; | |
493 | ||
494 | /* no data is fine */ | |
495 | } else { | |
496 | r = sd_bus_message_read_array(reply, 'y', &p, &sz); | |
497 | if (r < 0) | |
498 | return r; | |
499 | ||
500 | c->label = strndup(p, sz); | |
501 | if (!c->label) | |
502 | return -ENOMEM; | |
503 | ||
504 | c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; | |
505 | } | |
359c09b1 | 506 | } |
49b832c5 | 507 | } |
e7176abb LP |
508 | |
509 | r = bus_creds_add_more(c, mask, pid, 0); | |
510 | if (r < 0) | |
511 | return r; | |
49b832c5 LP |
512 | } |
513 | ||
514 | if (creds) { | |
515 | *creds = c; | |
516 | c = NULL; | |
517 | } | |
518 | ||
e7176abb | 519 | return 0; |
49b832c5 LP |
520 | } |
521 | ||
056f95d0 | 522 | _public_ int sd_bus_get_name_creds( |
49b832c5 LP |
523 | sd_bus *bus, |
524 | const char *name, | |
525 | uint64_t mask, | |
526 | sd_bus_creds **creds) { | |
527 | ||
528 | assert_return(bus, -EINVAL); | |
529 | assert_return(name, -EINVAL); | |
15411c0c | 530 | assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); |
49b832c5 | 531 | assert_return(mask == 0 || creds, -EINVAL); |
49b832c5 | 532 | assert_return(!bus_pid_changed(bus), -ECHILD); |
45fd5e4d | 533 | assert_return(service_name_is_valid(name), -EINVAL); |
33c62dcb LP |
534 | |
535 | if (!bus->bus_client) | |
536 | return -EINVAL; | |
49b832c5 | 537 | |
694859b5 LP |
538 | /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not |
539 | * going to match. */ | |
540 | if (!bus->is_local) | |
541 | mask &= ~SD_BUS_CREDS_AUGMENT; | |
542 | ||
210a6882 LP |
543 | if (streq(name, "org.freedesktop.DBus.Local")) |
544 | return -EINVAL; | |
545 | ||
51c7d5aa LP |
546 | if (streq(name, "org.freedesktop.DBus")) |
547 | return sd_bus_get_owner_creds(bus, mask, creds); | |
548 | ||
a3d59cd1 LP |
549 | if (!BUS_IS_OPEN(bus->state)) |
550 | return -ENOTCONN; | |
551 | ||
a132bef0 | 552 | return bus_get_name_creds_dbus1(bus, name, mask, creds); |
52cfc037 LP |
553 | } |
554 | ||
555 | static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { | |
4afd3348 | 556 | _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL; |
52cfc037 | 557 | pid_t pid = 0; |
7fc04b12 | 558 | bool do_label; |
52cfc037 | 559 | int r; |
7fc04b12 LP |
560 | |
561 | assert(bus); | |
562 | ||
563 | do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT); | |
8f44e3ea | 564 | |
c4e6556c ZJS |
565 | /* Avoid allocating anything if we have no chance of returning useful data */ |
566 | if (!bus->ucred_valid && !do_label) | |
8f44e3ea DM |
567 | return -ENODATA; |
568 | ||
569 | c = bus_creds_new(); | |
570 | if (!c) | |
571 | return -ENOMEM; | |
572 | ||
573 | if (bus->ucred_valid) { | |
52cfc037 LP |
574 | if (bus->ucred.pid > 0) { |
575 | pid = c->pid = bus->ucred.pid; | |
576 | c->mask |= SD_BUS_CREDS_PID & mask; | |
577 | } | |
8f44e3ea | 578 | |
fed1e721 | 579 | if (bus->ucred.uid != UID_INVALID) { |
05bae4a6 DH |
580 | c->euid = bus->ucred.uid; |
581 | c->mask |= SD_BUS_CREDS_EUID & mask; | |
52cfc037 LP |
582 | } |
583 | ||
fed1e721 | 584 | if (bus->ucred.gid != GID_INVALID) { |
05bae4a6 DH |
585 | c->egid = bus->ucred.gid; |
586 | c->mask |= SD_BUS_CREDS_EGID & mask; | |
52cfc037 | 587 | } |
8f44e3ea DM |
588 | } |
589 | ||
c4e6556c | 590 | if (do_label) { |
8f44e3ea | 591 | c->label = strdup(bus->label); |
505e77ca | 592 | if (!c->label) |
8f44e3ea | 593 | return -ENOMEM; |
8f44e3ea DM |
594 | |
595 | c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; | |
596 | } | |
597 | ||
705a415f LP |
598 | r = bus_creds_add_more(c, mask, pid, 0); |
599 | if (r < 0) | |
600 | return r; | |
601 | ||
8f44e3ea | 602 | *ret = c; |
505e77ca | 603 | c = NULL; |
8f44e3ea DM |
604 | return 0; |
605 | } | |
606 | ||
52cfc037 LP |
607 | _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { |
608 | assert_return(bus, -EINVAL); | |
15411c0c | 609 | assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP); |
52cfc037 LP |
610 | assert_return(ret, -EINVAL); |
611 | assert_return(!bus_pid_changed(bus), -ECHILD); | |
612 | ||
613 | if (!BUS_IS_OPEN(bus->state)) | |
614 | return -ENOTCONN; | |
615 | ||
694859b5 LP |
616 | if (!bus->is_local) |
617 | mask &= ~SD_BUS_CREDS_AUGMENT; | |
618 | ||
a132bef0 | 619 | return bus_get_owner_creds_dbus1(bus, mask, ret); |
e7176abb | 620 | } |
777d7a61 | 621 | |
09365592 LP |
622 | #define internal_match(bus, m) \ |
623 | ((bus)->hello_flags & KDBUS_HELLO_MONITOR \ | |
63c372cb | 624 | ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \ |
09365592 LP |
625 | : (m)) |
626 | ||
e7176abb LP |
627 | static int bus_add_match_internal_dbus1( |
628 | sd_bus *bus, | |
629 | const char *match) { | |
777d7a61 | 630 | |
09365592 LP |
631 | const char *e; |
632 | ||
e7176abb LP |
633 | assert(bus); |
634 | assert(match); | |
777d7a61 | 635 | |
09365592 LP |
636 | e = internal_match(bus, match); |
637 | ||
e7176abb LP |
638 | return sd_bus_call_method( |
639 | bus, | |
640 | "org.freedesktop.DBus", | |
cd789fdf | 641 | "/org/freedesktop/DBus", |
e7176abb LP |
642 | "org.freedesktop.DBus", |
643 | "AddMatch", | |
644 | NULL, | |
645 | NULL, | |
646 | "s", | |
09365592 | 647 | e); |
de1c301e LP |
648 | } |
649 | ||
e7176abb LP |
650 | int bus_add_match_internal( |
651 | sd_bus *bus, | |
652 | const char *match, | |
653 | struct bus_match_component *components, | |
532f808f | 654 | unsigned n_components) { |
e7176abb LP |
655 | |
656 | assert(bus); | |
e7176abb | 657 | |
33c62dcb LP |
658 | if (!bus->bus_client) |
659 | return -EINVAL; | |
660 | ||
a132bef0 | 661 | return bus_add_match_internal_dbus1(bus, match); |
e7176abb | 662 | } |
c7819669 | 663 | |
e7176abb LP |
664 | static int bus_remove_match_internal_dbus1( |
665 | sd_bus *bus, | |
666 | const char *match) { | |
777d7a61 | 667 | |
09365592 LP |
668 | const char *e; |
669 | ||
e7176abb LP |
670 | assert(bus); |
671 | assert(match); | |
672 | ||
09365592 LP |
673 | e = internal_match(bus, match); |
674 | ||
e7176abb LP |
675 | return sd_bus_call_method( |
676 | bus, | |
677 | "org.freedesktop.DBus", | |
cd789fdf | 678 | "/org/freedesktop/DBus", |
e7176abb LP |
679 | "org.freedesktop.DBus", |
680 | "RemoveMatch", | |
681 | NULL, | |
682 | NULL, | |
683 | "s", | |
09365592 | 684 | e); |
e7176abb LP |
685 | } |
686 | ||
687 | int bus_remove_match_internal( | |
688 | sd_bus *bus, | |
532f808f | 689 | const char *match) { |
e7176abb LP |
690 | |
691 | assert(bus); | |
e7176abb | 692 | |
33c62dcb LP |
693 | if (!bus->bus_client) |
694 | return -EINVAL; | |
695 | ||
a132bef0 | 696 | return bus_remove_match_internal_dbus1(bus, match); |
de1c301e | 697 | } |
70666185 | 698 | |
056f95d0 | 699 | _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) { |
4afd3348 | 700 | _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *m = NULL; |
70666185 LP |
701 | const char *mid; |
702 | int r; | |
703 | ||
8d162091 LP |
704 | assert_return(bus, -EINVAL); |
705 | assert_return(name, -EINVAL); | |
706 | assert_return(machine, -EINVAL); | |
8d162091 | 707 | assert_return(!bus_pid_changed(bus), -ECHILD); |
45fd5e4d | 708 | assert_return(service_name_is_valid(name), -EINVAL); |
70666185 | 709 | |
33c62dcb LP |
710 | if (!bus->bus_client) |
711 | return -EINVAL; | |
712 | ||
a3d59cd1 LP |
713 | if (!BUS_IS_OPEN(bus->state)) |
714 | return -ENOTCONN; | |
715 | ||
70666185 LP |
716 | if (streq_ptr(name, bus->unique_name)) |
717 | return sd_id128_get_machine(machine); | |
718 | ||
8d162091 LP |
719 | r = sd_bus_message_new_method_call( |
720 | bus, | |
151b9b96 | 721 | &m, |
8d162091 LP |
722 | name, |
723 | "/", | |
724 | "org.freedesktop.DBus.Peer", | |
151b9b96 | 725 | "GetMachineId"); |
8d162091 LP |
726 | if (r < 0) |
727 | return r; | |
728 | ||
eee9ec0e | 729 | r = sd_bus_message_set_auto_start(m, false); |
8d162091 LP |
730 | if (r < 0) |
731 | return r; | |
70666185 | 732 | |
8d162091 | 733 | r = sd_bus_call(bus, m, 0, NULL, &reply); |
70666185 LP |
734 | if (r < 0) |
735 | return r; | |
736 | ||
737 | r = sd_bus_message_read(reply, "s", &mid); | |
738 | if (r < 0) | |
739 | return r; | |
740 | ||
741 | return sd_id128_from_string(mid, machine); | |
742 | } |