]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/bus-proxyd/driver.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / bus-proxyd / driver.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
9
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 ***/
23
24 #include <errno.h>
25 #include <stddef.h>
26 #include <string.h>
27
28 #include "sd-bus.h"
29
30 #include "bus-internal.h"
31 #include "bus-message.h"
32 #include "bus-util.h"
33 #include "driver.h"
34 #include "env-util.h"
35 #include "proxy.h"
36 #include "set.h"
37 #include "strv.h"
38 #include "synthesize.h"
39 #include "util.h"
40
41 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
42 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
43 int r;
44
45 assert(bus);
46 assert(name);
47 assert(_creds);
48
49 r = sd_bus_get_name_creds(bus, name, mask, &c);
50 if (r == -ESRCH || r == -ENXIO)
51 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
52 if (r < 0)
53 return r;
54
55 *_creds = c;
56 c = NULL;
57
58 return 0;
59 }
60
61 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
62 const char *name;
63 int r;
64
65 assert(bus);
66 assert(m);
67 assert(_creds);
68
69 r = sd_bus_message_read(m, "s", &name);
70 if (r < 0)
71 return r;
72
73 return get_creds_by_name(bus, name, mask, _creds, error);
74 }
75
76 static int driver_activation(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
77 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
78 ProxyActivation *activation = userdata;
79
80 /*
81 * The org.freedesktop.DBus.Peer.Ping() call returned. We don't care
82 * whether this succeeded, failed, was not implemented or timed out. We
83 * cannot assume that the target reacts to this properly. Hence, just
84 * send the reply to the activation request and be done.
85 */
86
87 m = activation->request; /* claim reference */
88
89 --activation->proxy->n_activations;
90 LIST_REMOVE(activations_by_proxy, activation->proxy->activations, activation);
91 sd_bus_slot_unref(activation->slot);
92 free(activation);
93
94 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
95 }
96
97 int bus_proxy_process_driver(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPolicy *sp, const struct ucred *ucred, Set *owned_names) {
98 int r;
99
100 assert(a);
101 assert(b);
102 assert(m);
103
104 if (!a->is_kernel)
105 return 0;
106
107 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
108 return 0;
109
110 /* The "Hello()" call is is handled in process_hello() */
111
112 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
113
114 if (!sd_bus_message_has_signature(m, ""))
115 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
116
117 return synthetic_reply_method_return(m, "s",
118 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
119 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
120 "<node>\n"
121 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
122 " <method name=\"Introspect\">\n"
123 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
124 " </method>\n"
125 " </interface>\n"
126 " <interface name=\"org.freedesktop.DBus\">\n"
127 " <method name=\"AddMatch\">\n"
128 " <arg type=\"s\" direction=\"in\"/>\n"
129 " </method>\n"
130 " <method name=\"RemoveMatch\">\n"
131 " <arg type=\"s\" direction=\"in\"/>\n"
132 " </method>\n"
133 " <method name=\"GetConnectionCredentials\">\n"
134 " <arg type=\"s\" direction=\"in\"/>\n"
135 " <arg type=\"a{sv}\" direction=\"out\"/>\n"
136 " </method>\n"
137 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
138 " <arg type=\"s\" direction=\"in\"/>\n"
139 " <arg type=\"ay\" direction=\"out\"/>\n"
140 " </method>\n"
141 " <method name=\"GetConnectionUnixProcessID\">\n"
142 " <arg type=\"s\" direction=\"in\"/>\n"
143 " <arg type=\"u\" direction=\"out\"/>\n"
144 " </method>\n"
145 " <method name=\"GetConnectionUnixUser\">\n"
146 " <arg type=\"s\" direction=\"in\"/>\n"
147 " <arg type=\"u\" direction=\"out\"/>\n"
148 " </method>\n"
149 " <method name=\"GetId\">\n"
150 " <arg type=\"s\" direction=\"out\"/>\n"
151 " </method>\n"
152 " <method name=\"GetNameOwner\">\n"
153 " <arg type=\"s\" direction=\"in\"/>\n"
154 " <arg type=\"s\" direction=\"out\"/>\n"
155 " </method>\n"
156 " <method name=\"Hello\">\n"
157 " <arg type=\"s\" direction=\"out\"/>\n"
158 " </method>\n"
159 " <method name=\"ListActivatableNames\">\n"
160 " <arg type=\"as\" direction=\"out\"/>\n"
161 " </method>\n"
162 " <method name=\"ListNames\">\n"
163 " <arg type=\"as\" direction=\"out\"/>\n"
164 " </method>\n"
165 " <method name=\"ListQueuedOwners\">\n"
166 " <arg type=\"s\" direction=\"in\"/>\n"
167 " <arg type=\"as\" direction=\"out\"/>\n"
168 " </method>\n"
169 " <method name=\"NameHasOwner\">\n"
170 " <arg type=\"s\" direction=\"in\"/>\n"
171 " <arg type=\"b\" direction=\"out\"/>\n"
172 " </method>\n"
173 " <method name=\"ReleaseName\">\n"
174 " <arg type=\"s\" direction=\"in\"/>\n"
175 " <arg type=\"u\" direction=\"out\"/>\n"
176 " </method>\n"
177 " <method name=\"ReloadConfig\">\n"
178 " </method>\n"
179 " <method name=\"RequestName\">\n"
180 " <arg type=\"s\" direction=\"in\"/>\n"
181 " <arg type=\"u\" direction=\"in\"/>\n"
182 " <arg type=\"u\" direction=\"out\"/>\n"
183 " </method>\n"
184 " <method name=\"StartServiceByName\">\n"
185 " <arg type=\"s\" direction=\"in\"/>\n"
186 " <arg type=\"u\" direction=\"in\"/>\n"
187 " <arg type=\"u\" direction=\"out\"/>\n"
188 " </method>\n"
189 " <method name=\"UpdateActivationEnvironment\">\n"
190 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
191 " </method>\n"
192 " <signal name=\"NameAcquired\">\n"
193 " <arg type=\"s\"/>\n"
194 " </signal>\n"
195 " <signal name=\"NameLost\">\n"
196 " <arg type=\"s\"/>\n"
197 " </signal>\n"
198 " <signal name=\"NameOwnerChanged\">\n"
199 " <arg type=\"s\"/>\n"
200 " <arg type=\"s\"/>\n"
201 " <arg type=\"s\"/>\n"
202 " </signal>\n"
203 " </interface>\n"
204 "</node>\n");
205
206 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
207 const char *match;
208
209 if (!sd_bus_message_has_signature(m, "s"))
210 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
211
212 r = sd_bus_message_read(m, "s", &match);
213 if (r < 0)
214 return synthetic_reply_method_errno(m, r, NULL);
215
216 r = sd_bus_add_match(a, NULL, match, proxy_match, p);
217 if (r < 0)
218 return synthetic_reply_method_errno(m, r, NULL);
219
220 return synthetic_reply_method_return(m, NULL);
221
222 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
223 const char *match;
224
225 if (!sd_bus_message_has_signature(m, "s"))
226 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
227
228 r = sd_bus_message_read(m, "s", &match);
229 if (r < 0)
230 return synthetic_reply_method_errno(m, r, NULL);
231
232 r = bus_remove_match_by_string(a, match, NULL, NULL);
233 if (r == 0)
234 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
235 if (r < 0)
236 return synthetic_reply_method_errno(m, r, NULL);
237
238 return synthetic_reply_method_return(m, NULL);
239
240 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionCredentials")) {
241 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
242 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
243 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
244
245 if (!sd_bus_message_has_signature(m, "s"))
246 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
247
248 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
249 if (r < 0)
250 return synthetic_reply_method_errno(m, r, &error);
251
252 r = sd_bus_message_new_method_return(m, &reply);
253 if (r < 0)
254 return synthetic_reply_method_errno(m, r, NULL);
255
256 r = sd_bus_message_open_container(reply, 'a', "{sv}");
257 if (r < 0)
258 return synthetic_reply_method_errno(m, r, NULL);
259
260 /* Due to i.e. namespace translations some data might be missing */
261
262 if (creds->mask & SD_BUS_CREDS_PID) {
263 r = sd_bus_message_append(reply, "{sv}", "ProcessID", "u", (uint32_t) creds->pid);
264 if (r < 0)
265 return synthetic_reply_method_errno(m, r, NULL);
266 }
267
268 if (creds->mask & SD_BUS_CREDS_EUID) {
269 r = sd_bus_message_append(reply, "{sv}", "UnixUserID", "u", (uint32_t) creds->euid);
270 if (r < 0)
271 return synthetic_reply_method_errno(m, r, NULL);
272 }
273
274 if (creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
275 r = sd_bus_message_open_container(reply, 'e', "sv");
276 if (r < 0)
277 return synthetic_reply_method_errno(m, r, NULL);
278
279 r = sd_bus_message_append(reply, "s", "LinuxSecurityLabel");
280 if (r < 0)
281 return synthetic_reply_method_errno(m, r, NULL);
282
283 r = sd_bus_message_open_container(reply, 'v', "ay");
284 if (r < 0)
285 return synthetic_reply_method_errno(m, r, NULL);
286
287 r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
288 if (r < 0)
289 return synthetic_reply_method_errno(m, r, NULL);
290
291 r = sd_bus_message_close_container(reply);
292 if (r < 0)
293 return synthetic_reply_method_errno(m, r, NULL);
294
295 r = sd_bus_message_close_container(reply);
296 if (r < 0)
297 return synthetic_reply_method_errno(m, r, NULL);
298 }
299
300 r = sd_bus_message_close_container(reply);
301 if (r < 0)
302 return synthetic_reply_method_errno(m, r, NULL);
303
304 return synthetic_driver_send(m->bus, reply);
305
306 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
307 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
308 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
309 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
310
311 if (!sd_bus_message_has_signature(m, "s"))
312 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
313
314 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
315 if (r < 0)
316 return synthetic_reply_method_errno(m, r, &error);
317
318 if (!(creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
319 return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
320
321 r = sd_bus_message_new_method_return(m, &reply);
322 if (r < 0)
323 return synthetic_reply_method_errno(m, r, NULL);
324
325 r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
326 if (r < 0)
327 return synthetic_reply_method_errno(m, r, NULL);
328
329 return synthetic_driver_send(m->bus, reply);
330
331 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
332 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
333 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
334
335 if (!sd_bus_message_has_signature(m, "s"))
336 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
337
338 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
339 if (r < 0)
340 return synthetic_reply_method_errno(m, r, &error);
341
342 if (!(creds->mask & SD_BUS_CREDS_PID))
343 return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
344
345 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
346
347 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
348 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
349 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
350
351 if (!sd_bus_message_has_signature(m, "s"))
352 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
353
354 r = get_creds_by_message(a, m, SD_BUS_CREDS_EUID, &creds, &error);
355 if (r < 0)
356 return synthetic_reply_method_errno(m, r, &error);
357
358 if (!(creds->mask & SD_BUS_CREDS_EUID))
359 return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
360
361 return synthetic_reply_method_return(m, "u", (uint32_t) creds->euid);
362
363 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
364 sd_id128_t server_id;
365 char buf[SD_ID128_STRING_MAX];
366
367 if (!sd_bus_message_has_signature(m, ""))
368 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
369
370 r = sd_bus_get_bus_id(a, &server_id);
371 if (r < 0)
372 return synthetic_reply_method_errno(m, r, NULL);
373
374 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
375
376 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
377 const char *name;
378 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
379 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
380
381 if (!sd_bus_message_has_signature(m, "s"))
382 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
383
384 r = sd_bus_message_read(m, "s", &name);
385 if (r < 0)
386 return synthetic_reply_method_errno(m, r, NULL);
387
388 if (streq(name, "org.freedesktop.DBus"))
389 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
390
391 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
392 if (r < 0)
393 return synthetic_reply_method_errno(m, r, &error);
394
395 if (!(creds->mask & SD_BUS_CREDS_UNIQUE_NAME))
396 return synthetic_reply_method_errno(m, -EOPNOTSUPP, NULL);
397
398 return synthetic_reply_method_return(m, "s", creds->unique_name);
399
400 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
401 _cleanup_strv_free_ char **names = NULL;
402
403 if (!sd_bus_message_has_signature(m, ""))
404 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
405
406 r = sd_bus_list_names(a, NULL, &names);
407 if (r < 0)
408 return synthetic_reply_method_errno(m, r, NULL);
409
410 /* Let's sort the names list to make it stable */
411 strv_sort(names);
412
413 return synthetic_reply_method_return_strv(m, names);
414
415 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
416 _cleanup_strv_free_ char **names = NULL;
417
418 if (!sd_bus_message_has_signature(m, ""))
419 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
420
421 r = sd_bus_list_names(a, &names, NULL);
422 if (r < 0)
423 return synthetic_reply_method_errno(m, r, NULL);
424
425 r = strv_extend(&names, "org.freedesktop.DBus");
426 if (r < 0)
427 return synthetic_reply_method_errno(m, r, NULL);
428
429 /* Let's sort the names list to make it stable */
430 strv_sort(names);
431
432 return synthetic_reply_method_return_strv(m, names);
433
434 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
435 struct kdbus_cmd_list cmd = {
436 .flags = KDBUS_LIST_QUEUED,
437 .size = sizeof(cmd),
438 };
439 struct kdbus_info *name_list, *name;
440 _cleanup_strv_free_ char **owners = NULL;
441 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
442 char *arg0;
443 int err = 0;
444
445 if (!sd_bus_message_has_signature(m, "s"))
446 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
447
448 r = sd_bus_message_read(m, "s", &arg0);
449 if (r < 0)
450 return synthetic_reply_method_errno(m, r, NULL);
451
452 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
453 if (r == -ESRCH || r == -ENXIO) {
454 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
455 return synthetic_reply_method_errno(m, r, &error);
456 }
457 if (r < 0)
458 return synthetic_reply_method_errno(m, r, NULL);
459
460 r = ioctl(a->input_fd, KDBUS_CMD_LIST, &cmd);
461 if (r < 0)
462 return synthetic_reply_method_errno(m, -errno, NULL);
463
464 name_list = (struct kdbus_info *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
465
466 KDBUS_FOREACH(name, name_list, cmd.list_size) {
467 struct kdbus_item *item;
468 char *n;
469
470 KDBUS_ITEM_FOREACH(item, name, items) {
471 if (item->type == KDBUS_ITEM_OWNED_NAME) {
472 if (!streq_ptr(item->name.name, arg0))
473 continue;
474
475 if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
476 err = -ENOMEM;
477 break;
478 }
479
480 r = strv_consume(&owners, n);
481 if (r < 0) {
482 err = r;
483 break;
484 }
485 }
486 }
487
488 if (err < 0)
489 break;
490 }
491
492 r = bus_kernel_cmd_free(a, cmd.offset);
493 if (r < 0)
494 return synthetic_reply_method_errno(m, r, NULL);
495
496 if (err < 0)
497 return synthetic_reply_method_errno(m, err, NULL);
498
499 return synthetic_reply_method_return_strv(m, owners);
500
501 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
502 const char *name;
503
504 if (!sd_bus_message_has_signature(m, "s"))
505 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
506
507 r = sd_bus_message_read(m, "s", &name);
508 if (r < 0)
509 return synthetic_reply_method_errno(m, r, NULL);
510
511 if (streq(name, "org.freedesktop.DBus"))
512 return synthetic_reply_method_return(m, "b", true);
513
514 r = sd_bus_get_name_creds(a, name, 0, NULL);
515 if (r < 0 && r != -ESRCH && r != -ENXIO)
516 return synthetic_reply_method_errno(m, r, NULL);
517
518 return synthetic_reply_method_return(m, "b", r >= 0);
519
520 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
521 const char *name;
522
523 if (!sd_bus_message_has_signature(m, "s"))
524 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
525
526 r = sd_bus_message_read(m, "s", &name);
527 if (r < 0)
528 return synthetic_reply_method_errno(m, r, NULL);
529
530 r = sd_bus_release_name(a, name);
531 if (r < 0) {
532 if (r == -ESRCH)
533 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
534 if (r == -EADDRINUSE)
535 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
536
537 return synthetic_reply_method_errno(m, r, NULL);
538 }
539
540 set_remove(owned_names, (char*) name);
541
542 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
543
544 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
545 if (!sd_bus_message_has_signature(m, ""))
546 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
547
548 r = shared_policy_reload(sp);
549 if (r < 0)
550 return synthetic_reply_method_errno(m, r, NULL);
551
552 return synthetic_reply_method_return(m, NULL);
553
554 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
555 const char *name;
556 uint32_t flags, param;
557 bool in_queue;
558
559 if (!sd_bus_message_has_signature(m, "su"))
560 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
561
562 r = sd_bus_message_read(m, "su", &name, &flags);
563 if (r < 0)
564 return synthetic_reply_method_errno(m, r, NULL);
565
566 if (sp) {
567 Policy *policy;
568 bool denied;
569
570 policy = shared_policy_acquire(sp);
571 denied = !policy_check_own(policy, ucred->uid, ucred->gid, name);
572 shared_policy_release(sp, policy);
573 if (denied)
574 return synthetic_reply_method_errno(m, -EPERM, NULL);
575 }
576
577 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
578 return synthetic_reply_method_errno(m, -EINVAL, NULL);
579
580 param = 0;
581 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
582 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
583 if (flags & BUS_NAME_REPLACE_EXISTING)
584 param |= SD_BUS_NAME_REPLACE_EXISTING;
585 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
586 param |= SD_BUS_NAME_QUEUE;
587
588 r = set_put_strdup(owned_names, name);
589 if (r < 0)
590 return synthetic_reply_method_errno(m, r, NULL);
591
592 r = sd_bus_request_name(a, name, param);
593 if (r < 0) {
594 if (r == -EALREADY)
595 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
596
597 set_remove(owned_names, (char*) name);
598
599 if (r == -EEXIST)
600 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
601 return synthetic_reply_method_errno(m, r, NULL);
602 }
603
604 in_queue = (r == 0);
605
606 if (in_queue)
607 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
608
609 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
610
611 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
612 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
613 ProxyActivation *activation;
614 const char *name;
615 uint64_t cookie;
616 uint32_t flags;
617
618 if (!sd_bus_message_has_signature(m, "su"))
619 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
620
621 r = sd_bus_message_read(m, "su", &name, &flags);
622 if (r < 0)
623 return synthetic_reply_method_errno(m, r, NULL);
624
625 if (flags != 0)
626 return synthetic_reply_method_errno(m, -EINVAL, NULL);
627
628 r = sd_bus_get_name_creds(a, name, 0, NULL);
629 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
630 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
631 if (r != -ESRCH)
632 return synthetic_reply_method_errno(m, r, NULL);
633
634 if (p->n_activations >= PROXY_ACTIVATIONS_MAX)
635 return synthetic_reply_method_errno(m, -EMFILE, NULL);
636
637 r = sd_bus_message_get_cookie(m, &cookie);
638 if (r < 0)
639 return synthetic_reply_method_errno(m, r, NULL);
640
641 r = sd_bus_message_new_method_call(a,
642 &msg,
643 name,
644 "/",
645 "org.freedesktop.DBus.Peer",
646 "Ping");
647 if (r < 0)
648 return synthetic_reply_method_errno(m, r, NULL);
649
650 r = bus_message_seal(msg, cookie, BUS_DEFAULT_TIMEOUT);
651 if (r < 0)
652 return synthetic_reply_method_errno(m, r, NULL);
653
654 activation = new0(ProxyActivation, 1);
655 if (!activation)
656 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
657
658 r = sd_bus_call_async(a,
659 &activation->slot,
660 msg,
661 driver_activation,
662 activation,
663 0);
664 if (r < 0) {
665 free(activation);
666 return synthetic_reply_method_errno(m, r, NULL);
667 }
668
669 activation->proxy = p;
670 activation->request = sd_bus_message_ref(m);
671 LIST_PREPEND(activations_by_proxy, p->activations, activation);
672 ++p->n_activations;
673 return 1;
674
675 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
676 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
677 _cleanup_strv_free_ char **args = NULL;
678
679 if (!sd_bus_message_has_signature(m, "a{ss}"))
680 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
681
682 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
683 if (r < 0)
684 return synthetic_reply_method_errno(m, r, NULL);
685
686 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
687 _cleanup_free_ char *s = NULL;
688 const char *key;
689 const char *value;
690
691 r = sd_bus_message_read(m, "ss", &key, &value);
692 if (r < 0)
693 return synthetic_reply_method_errno(m, r, NULL);
694
695 s = strjoin(key, "=", value, NULL);
696 if (!s)
697 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
698
699 if (!env_assignment_is_valid(s)) {
700 log_warning("UpdateActivationEnvironment() called with invalid assignment, discarding: %s", s);
701 } else {
702 r = strv_extend(&args, s);
703 if (r < 0)
704 return synthetic_reply_method_errno(m, r, NULL);
705 }
706
707 r = sd_bus_message_exit_container(m);
708 if (r < 0)
709 return synthetic_reply_method_errno(m, r, NULL);
710 }
711
712 r = sd_bus_message_exit_container(m);
713 if (r < 0)
714 return synthetic_reply_method_errno(m, r, NULL);
715
716 if (strv_isempty(args)) /* nothing to do? */
717 return synthetic_reply_method_return(m, NULL);
718
719 r = sd_bus_message_new_method_call(
720 a,
721 &msg,
722 "org.freedesktop.systemd1",
723 "/org/freedesktop/systemd1",
724 "org.freedesktop.systemd1.Manager",
725 "SetEnvironment");
726 if (r < 0)
727 return synthetic_reply_method_errno(m, r, NULL);
728
729 r = sd_bus_message_append_strv(msg, args);
730 if (r < 0)
731 return synthetic_reply_method_errno(m, r, NULL);
732
733 r = sd_bus_call(a, msg, 0, NULL, NULL);
734 if (r < 0)
735 return synthetic_reply_method_errno(m, r, NULL);
736
737 return synthetic_reply_method_return(m, NULL);
738
739 } else {
740 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
741
742 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
743
744 return synthetic_reply_method_errno(m, r, &error);
745 }
746 }