]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-session-dbus.c
bus-util: support details in CheckAuthorization calls
[thirdparty/systemd.git] / src / login / logind-session-dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <string.h>
24
25 #include "util.h"
26 #include "strv.h"
27 #include "bus-util.h"
28 #include "bus-common-errors.h"
29 #include "bus-label.h"
30
31 #include "logind.h"
32 #include "logind-session.h"
33 #include "logind-session-device.h"
34
35 static int property_get_user(
36 sd_bus *bus,
37 const char *path,
38 const char *interface,
39 const char *property,
40 sd_bus_message *reply,
41 void *userdata,
42 sd_bus_error *error) {
43
44 _cleanup_free_ char *p = NULL;
45 Session *s = userdata;
46
47 assert(bus);
48 assert(reply);
49 assert(s);
50
51 p = user_bus_path(s->user);
52 if (!p)
53 return -ENOMEM;
54
55 return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->uid, p);
56 }
57
58 static int property_get_name(
59 sd_bus *bus,
60 const char *path,
61 const char *interface,
62 const char *property,
63 sd_bus_message *reply,
64 void *userdata,
65 sd_bus_error *error) {
66
67 Session *s = userdata;
68
69 assert(bus);
70 assert(reply);
71 assert(s);
72
73 return sd_bus_message_append(reply, "s", s->user->name);
74 }
75
76 static int property_get_seat(
77 sd_bus *bus,
78 const char *path,
79 const char *interface,
80 const char *property,
81 sd_bus_message *reply,
82 void *userdata,
83 sd_bus_error *error) {
84
85 _cleanup_free_ char *p = NULL;
86 Session *s = userdata;
87
88 assert(bus);
89 assert(reply);
90 assert(s);
91
92 p = s->seat ? seat_bus_path(s->seat) : strdup("/");
93 if (!p)
94 return -ENOMEM;
95
96 return sd_bus_message_append(reply, "(so)", s->seat ? s->seat->id : "", p);
97 }
98
99 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
100 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
101
102 static int property_get_active(
103 sd_bus *bus,
104 const char *path,
105 const char *interface,
106 const char *property,
107 sd_bus_message *reply,
108 void *userdata,
109 sd_bus_error *error) {
110
111 Session *s = userdata;
112
113 assert(bus);
114 assert(reply);
115 assert(s);
116
117 return sd_bus_message_append(reply, "b", session_is_active(s));
118 }
119
120 static int property_get_state(
121 sd_bus *bus,
122 const char *path,
123 const char *interface,
124 const char *property,
125 sd_bus_message *reply,
126 void *userdata,
127 sd_bus_error *error) {
128
129 Session *s = userdata;
130
131 assert(bus);
132 assert(reply);
133 assert(s);
134
135 return sd_bus_message_append(reply, "s", session_state_to_string(session_get_state(s)));
136 }
137
138 static int property_get_idle_hint(
139 sd_bus *bus,
140 const char *path,
141 const char *interface,
142 const char *property,
143 sd_bus_message *reply,
144 void *userdata,
145 sd_bus_error *error) {
146
147 Session *s = userdata;
148
149 assert(bus);
150 assert(reply);
151 assert(s);
152
153 return sd_bus_message_append(reply, "b", session_get_idle_hint(s, NULL) > 0);
154 }
155
156 static int property_get_idle_since_hint(
157 sd_bus *bus,
158 const char *path,
159 const char *interface,
160 const char *property,
161 sd_bus_message *reply,
162 void *userdata,
163 sd_bus_error *error) {
164
165 Session *s = userdata;
166 dual_timestamp t = DUAL_TIMESTAMP_NULL;
167 uint64_t u;
168 int r;
169
170 assert(bus);
171 assert(reply);
172 assert(s);
173
174 r = session_get_idle_hint(s, &t);
175 if (r < 0)
176 return r;
177
178 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
179
180 return sd_bus_message_append(reply, "t", u);
181 }
182
183 int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
184 Session *s = userdata;
185 int r;
186
187 assert(message);
188 assert(s);
189
190 r = bus_verify_polkit_async(
191 message,
192 CAP_KILL,
193 "org.freedesktop.login1.manage",
194 NULL,
195 false,
196 s->user->uid,
197 &s->manager->polkit_registry,
198 error);
199 if (r < 0)
200 return r;
201 if (r == 0)
202 return 1; /* Will call us back */
203
204 r = session_stop(s, true);
205 if (r < 0)
206 return r;
207
208 return sd_bus_reply_method_return(message, NULL);
209 }
210
211 int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
212 Session *s = userdata;
213 int r;
214
215 assert(message);
216 assert(s);
217
218 r = session_activate(s);
219 if (r < 0)
220 return r;
221
222 return sd_bus_reply_method_return(message, NULL);
223 }
224
225 int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) {
226 Session *s = userdata;
227 int r;
228
229 assert(message);
230 assert(s);
231
232 r = bus_verify_polkit_async(
233 message,
234 CAP_SYS_ADMIN,
235 "org.freedesktop.login1.lock-sessions",
236 NULL,
237 false,
238 s->user->uid,
239 &s->manager->polkit_registry,
240 error);
241 if (r < 0)
242 return r;
243 if (r == 0)
244 return 1; /* Will call us back */
245
246 r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock"));
247 if (r < 0)
248 return r;
249
250 return sd_bus_reply_method_return(message, NULL);
251 }
252
253 static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
254 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
255 Session *s = userdata;
256 uid_t uid;
257 int r, b;
258
259 assert(message);
260 assert(s);
261
262 r = sd_bus_message_read(message, "b", &b);
263 if (r < 0)
264 return r;
265
266 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
267 if (r < 0)
268 return r;
269
270 r = sd_bus_creds_get_euid(creds, &uid);
271 if (r < 0)
272 return r;
273
274 if (uid != 0 && uid != s->user->uid)
275 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
276
277 session_set_idle_hint(s, b);
278
279 return sd_bus_reply_method_return(message, NULL);
280 }
281
282 int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
283 Session *s = userdata;
284 const char *swho;
285 int32_t signo;
286 KillWho who;
287 int r;
288
289 assert(message);
290 assert(s);
291
292 r = sd_bus_message_read(message, "si", &swho, &signo);
293 if (r < 0)
294 return r;
295
296 if (isempty(swho))
297 who = KILL_ALL;
298 else {
299 who = kill_who_from_string(swho);
300 if (who < 0)
301 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
302 }
303
304 if (signo <= 0 || signo >= _NSIG)
305 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
306
307 r = bus_verify_polkit_async(
308 message,
309 CAP_KILL,
310 "org.freedesktop.login1.manage",
311 NULL,
312 false,
313 s->user->uid,
314 &s->manager->polkit_registry,
315 error);
316 if (r < 0)
317 return r;
318 if (r == 0)
319 return 1; /* Will call us back */
320
321 r = session_kill(s, who, signo);
322 if (r < 0)
323 return r;
324
325 return sd_bus_reply_method_return(message, NULL);
326 }
327
328 static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
329 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
330 Session *s = userdata;
331 int r, force;
332 uid_t uid;
333
334 assert(message);
335 assert(s);
336
337 r = sd_bus_message_read(message, "b", &force);
338 if (r < 0)
339 return r;
340
341 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
342 if (r < 0)
343 return r;
344
345 r = sd_bus_creds_get_euid(creds, &uid);
346 if (r < 0)
347 return r;
348
349 if (uid != 0 && (force || uid != s->user->uid))
350 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
351
352 r = session_set_controller(s, sd_bus_message_get_sender(message), force);
353 if (r < 0)
354 return r;
355
356 return sd_bus_reply_method_return(message, NULL);
357 }
358
359 static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
360 Session *s = userdata;
361
362 assert(message);
363 assert(s);
364
365 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
366 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
367
368 session_drop_controller(s);
369
370 return sd_bus_reply_method_return(message, NULL);
371 }
372
373 static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
374 Session *s = userdata;
375 uint32_t major, minor;
376 SessionDevice *sd;
377 dev_t dev;
378 int r;
379
380 assert(message);
381 assert(s);
382
383 r = sd_bus_message_read(message, "uu", &major, &minor);
384 if (r < 0)
385 return r;
386
387 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
388 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
389
390 dev = makedev(major, minor);
391 sd = hashmap_get(s->devices, &dev);
392 if (sd)
393 /* We don't allow retrieving a device multiple times.
394 * The related ReleaseDevice call is not ref-counted.
395 * The caller should use dup() if it requires more
396 * than one fd (it would be functionally
397 * equivalent). */
398 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
399
400 r = session_device_new(s, dev, &sd);
401 if (r < 0)
402 return r;
403
404 r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
405 if (r < 0)
406 session_device_free(sd);
407
408 return r;
409 }
410
411 static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
412 Session *s = userdata;
413 uint32_t major, minor;
414 SessionDevice *sd;
415 dev_t dev;
416 int r;
417
418 assert(message);
419 assert(s);
420
421 r = sd_bus_message_read(message, "uu", &major, &minor);
422 if (r < 0)
423 return r;
424
425 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
426 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
427
428 dev = makedev(major, minor);
429 sd = hashmap_get(s->devices, &dev);
430 if (!sd)
431 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
432
433 session_device_free(sd);
434 return sd_bus_reply_method_return(message, NULL);
435 }
436
437 static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) {
438 Session *s = userdata;
439 uint32_t major, minor;
440 SessionDevice *sd;
441 dev_t dev;
442 int r;
443
444 assert(message);
445 assert(s);
446
447 r = sd_bus_message_read(message, "uu", &major, &minor);
448 if (r < 0)
449 return r;
450
451 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
452 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
453
454 dev = makedev(major, minor);
455 sd = hashmap_get(s->devices, &dev);
456 if (!sd)
457 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
458
459 session_device_complete_pause(sd);
460
461 return sd_bus_reply_method_return(message, NULL);
462 }
463
464 const sd_bus_vtable session_vtable[] = {
465 SD_BUS_VTABLE_START(0),
466
467 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST),
468 SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST),
469 SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
470 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
471 SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST),
472 SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST),
473 SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST),
474 SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST),
475 SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST),
476 SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
477 SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
478 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
479 SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
480 SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
481 SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST),
482 SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST),
483 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_CONST),
484 SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST),
485 SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
486 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
487 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
488 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
489 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
490
491 SD_BUS_METHOD("Terminate", NULL, NULL, bus_session_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
492 SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
493 SD_BUS_METHOD("Lock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
494 SD_BUS_METHOD("Unlock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
495 SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
496 SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
497 SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED),
498 SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED),
499 SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED),
500 SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED),
501 SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED),
502
503 SD_BUS_SIGNAL("PauseDevice", "uus", 0),
504 SD_BUS_SIGNAL("ResumeDevice", "uuh", 0),
505 SD_BUS_SIGNAL("Lock", NULL, 0),
506 SD_BUS_SIGNAL("Unlock", NULL, 0),
507
508 SD_BUS_VTABLE_END
509 };
510
511 int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
512 Manager *m = userdata;
513 Session *session;
514 int r;
515
516 assert(bus);
517 assert(path);
518 assert(interface);
519 assert(found);
520 assert(m);
521
522 if (streq(path, "/org/freedesktop/login1/session/self")) {
523 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
524 sd_bus_message *message;
525 const char *name;
526
527 message = sd_bus_get_current_message(bus);
528 if (!message)
529 return 0;
530
531 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
532 if (r < 0)
533 return r;
534
535 r = sd_bus_creds_get_session(creds, &name);
536 if (r < 0)
537 return r;
538
539 session = hashmap_get(m->sessions, name);
540 } else {
541 _cleanup_free_ char *e = NULL;
542 const char *p;
543
544 p = startswith(path, "/org/freedesktop/login1/session/");
545 if (!p)
546 return 0;
547
548 e = bus_label_unescape(p);
549 if (!e)
550 return -ENOMEM;
551
552 session = hashmap_get(m->sessions, e);
553 }
554
555 if (!session)
556 return 0;
557
558 *found = session;
559 return 1;
560 }
561
562 char *session_bus_path(Session *s) {
563 _cleanup_free_ char *t = NULL;
564
565 assert(s);
566
567 t = bus_label_escape(s->id);
568 if (!t)
569 return NULL;
570
571 return strappend("/org/freedesktop/login1/session/", t);
572 }
573
574 int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
575 _cleanup_strv_free_ char **l = NULL;
576 sd_bus_message *message;
577 Manager *m = userdata;
578 Session *session;
579 Iterator i;
580 int r;
581
582 assert(bus);
583 assert(path);
584 assert(nodes);
585
586 HASHMAP_FOREACH(session, m->sessions, i) {
587 char *p;
588
589 p = session_bus_path(session);
590 if (!p)
591 return -ENOMEM;
592
593 r = strv_consume(&l, p);
594 if (r < 0)
595 return r;
596 }
597
598 message = sd_bus_get_current_message(bus);
599 if (message) {
600 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
601 const char *name;
602
603 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
604 if (r >= 0) {
605 r = sd_bus_creds_get_session(creds, &name);
606 if (r >= 0) {
607 session = hashmap_get(m->sessions, name);
608 if (session) {
609 r = strv_extend(&l, "/org/freedesktop/login1/session/self");
610 if (r < 0)
611 return r;
612 }
613 }
614 }
615 }
616
617 *nodes = l;
618 l = NULL;
619
620 return 1;
621 }
622
623 int session_send_signal(Session *s, bool new_session) {
624 _cleanup_free_ char *p = NULL;
625
626 assert(s);
627
628 p = session_bus_path(s);
629 if (!p)
630 return -ENOMEM;
631
632 return sd_bus_emit_signal(
633 s->manager->bus,
634 "/org/freedesktop/login1",
635 "org.freedesktop.login1.Manager",
636 new_session ? "SessionNew" : "SessionRemoved",
637 "so", s->id, p);
638 }
639
640 int session_send_changed(Session *s, const char *properties, ...) {
641 _cleanup_free_ char *p = NULL;
642 char **l;
643
644 assert(s);
645
646 if (!s->started)
647 return 0;
648
649 p = session_bus_path(s);
650 if (!p)
651 return -ENOMEM;
652
653 l = strv_from_stdarg_alloca(properties);
654
655 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l);
656 }
657
658 int session_send_lock(Session *s, bool lock) {
659 _cleanup_free_ char *p = NULL;
660
661 assert(s);
662
663 p = session_bus_path(s);
664 if (!p)
665 return -ENOMEM;
666
667 return sd_bus_emit_signal(
668 s->manager->bus,
669 p,
670 "org.freedesktop.login1.Session",
671 lock ? "Lock" : "Unlock",
672 NULL);
673 }
674
675 int session_send_lock_all(Manager *m, bool lock) {
676 Session *session;
677 Iterator i;
678 int r = 0;
679
680 assert(m);
681
682 HASHMAP_FOREACH(session, m->sessions, i) {
683 int k;
684
685 k = session_send_lock(session, lock);
686 if (k < 0)
687 r = k;
688 }
689
690 return r;
691 }
692
693 int session_send_create_reply(Session *s, sd_bus_error *error) {
694 _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
695 _cleanup_close_ int fifo_fd = -1;
696 _cleanup_free_ char *p = NULL;
697
698 assert(s);
699
700 /* This is called after the session scope and the user service
701 * were successfully created, and finishes where
702 * bus_manager_create_session() left off. */
703
704 if (!s->create_message)
705 return 0;
706
707 if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
708 return 0;
709
710 c = s->create_message;
711 s->create_message = NULL;
712
713 if (error)
714 return sd_bus_reply_method_error(c, error);
715
716 fifo_fd = session_create_fifo(s);
717 if (fifo_fd < 0)
718 return fifo_fd;
719
720 /* Update the session state file before we notify the client
721 * about the result. */
722 session_save(s);
723
724 p = session_bus_path(s);
725 if (!p)
726 return -ENOMEM;
727
728 log_debug("Sending reply about created session: "
729 "id=%s object_path=%s uid=%u runtime_path=%s "
730 "session_fd=%d seat=%s vtnr=%u",
731 s->id,
732 p,
733 (uint32_t) s->user->uid,
734 s->user->runtime_path,
735 fifo_fd,
736 s->seat ? s->seat->id : "",
737 (uint32_t) s->vtnr);
738
739 return sd_bus_reply_method_return(
740 c, "soshusub",
741 s->id,
742 p,
743 s->user->runtime_path,
744 fifo_fd,
745 (uint32_t) s->user->uid,
746 s->seat ? s->seat->id : "",
747 (uint32_t) s->vtnr,
748 false);
749 }