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