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