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