]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-session-dbus.c
shared: split out property get helpers
[thirdparty/systemd.git] / src / login / logind-session-dbus.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4
5 #include "alloc-util.h"
6 #include "bus-common-errors.h"
7 #include "bus-get-properties.h"
8 #include "bus-label.h"
9 #include "bus-polkit.h"
10 #include "bus-util.h"
11 #include "fd-util.h"
12 #include "logind-brightness.h"
13 #include "logind-dbus.h"
14 #include "logind-seat-dbus.h"
15 #include "logind-session-dbus.h"
16 #include "logind-session-device.h"
17 #include "logind-session.h"
18 #include "logind-user-dbus.h"
19 #include "logind.h"
20 #include "missing_capability.h"
21 #include "path-util.h"
22 #include "signal-util.h"
23 #include "stat-util.h"
24 #include "strv.h"
25 #include "user-util.h"
26 #include "util.h"
27
28 static int property_get_user(
29 sd_bus *bus,
30 const char *path,
31 const char *interface,
32 const char *property,
33 sd_bus_message *reply,
34 void *userdata,
35 sd_bus_error *error) {
36
37 _cleanup_free_ char *p = NULL;
38 Session *s = userdata;
39
40 assert(bus);
41 assert(reply);
42 assert(s);
43
44 p = user_bus_path(s->user);
45 if (!p)
46 return -ENOMEM;
47
48 return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->user_record->uid, p);
49 }
50
51 static int property_get_name(
52 sd_bus *bus,
53 const char *path,
54 const char *interface,
55 const char *property,
56 sd_bus_message *reply,
57 void *userdata,
58 sd_bus_error *error) {
59
60 Session *s = userdata;
61
62 assert(bus);
63 assert(reply);
64 assert(s);
65
66 return sd_bus_message_append(reply, "s", s->user->user_record->user_name);
67 }
68
69 static int property_get_seat(
70 sd_bus *bus,
71 const char *path,
72 const char *interface,
73 const char *property,
74 sd_bus_message *reply,
75 void *userdata,
76 sd_bus_error *error) {
77
78 _cleanup_free_ char *p = NULL;
79 Session *s = userdata;
80
81 assert(bus);
82 assert(reply);
83 assert(s);
84
85 p = s->seat ? seat_bus_path(s->seat) : strdup("/");
86 if (!p)
87 return -ENOMEM;
88
89 return sd_bus_message_append(reply, "(so)", s->seat ? s->seat->id : "", p);
90 }
91
92 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
93 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
94 static BUS_DEFINE_PROPERTY_GET(property_get_active, "b", Session, session_is_active);
95 static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Session, session_get_state, session_state_to_string);
96
97 static int property_get_idle_hint(
98 sd_bus *bus,
99 const char *path,
100 const char *interface,
101 const char *property,
102 sd_bus_message *reply,
103 void *userdata,
104 sd_bus_error *error) {
105
106 Session *s = userdata;
107
108 assert(bus);
109 assert(reply);
110 assert(s);
111
112 return sd_bus_message_append(reply, "b", session_get_idle_hint(s, NULL) > 0);
113 }
114
115 static int property_get_idle_since_hint(
116 sd_bus *bus,
117 const char *path,
118 const char *interface,
119 const char *property,
120 sd_bus_message *reply,
121 void *userdata,
122 sd_bus_error *error) {
123
124 Session *s = userdata;
125 dual_timestamp t = DUAL_TIMESTAMP_NULL;
126 uint64_t u;
127 int r;
128
129 assert(bus);
130 assert(reply);
131 assert(s);
132
133 r = session_get_idle_hint(s, &t);
134 if (r < 0)
135 return r;
136
137 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
138
139 return sd_bus_message_append(reply, "t", u);
140 }
141
142 static int property_get_locked_hint(
143 sd_bus *bus,
144 const char *path,
145 const char *interface,
146 const char *property,
147 sd_bus_message *reply,
148 void *userdata,
149 sd_bus_error *error) {
150
151 Session *s = userdata;
152
153 assert(bus);
154 assert(reply);
155 assert(s);
156
157 return sd_bus_message_append(reply, "b", session_get_locked_hint(s) > 0);
158 }
159
160 int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
161 Session *s = userdata;
162 int r;
163
164 assert(message);
165 assert(s);
166
167 r = bus_verify_polkit_async(
168 message,
169 CAP_KILL,
170 "org.freedesktop.login1.manage",
171 NULL,
172 false,
173 s->user->user_record->uid,
174 &s->manager->polkit_registry,
175 error);
176 if (r < 0)
177 return r;
178 if (r == 0)
179 return 1; /* Will call us back */
180
181 r = session_stop(s, true);
182 if (r < 0)
183 return r;
184
185 return sd_bus_reply_method_return(message, NULL);
186 }
187
188 int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
189 Session *s = userdata;
190 int r;
191
192 assert(message);
193 assert(s);
194
195 r = bus_verify_polkit_async(
196 message,
197 CAP_SYS_ADMIN,
198 "org.freedesktop.login1.chvt",
199 NULL,
200 false,
201 UID_INVALID,
202 &s->manager->polkit_registry,
203 error);
204 if (r < 0)
205 return r;
206 if (r == 0)
207 return 1; /* Will call us back */
208
209 r = session_activate(s);
210 if (r < 0)
211 return r;
212
213 return sd_bus_reply_method_return(message, NULL);
214 }
215
216 int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) {
217 Session *s = userdata;
218 int r;
219
220 assert(message);
221 assert(s);
222
223 r = bus_verify_polkit_async(
224 message,
225 CAP_SYS_ADMIN,
226 "org.freedesktop.login1.lock-sessions",
227 NULL,
228 false,
229 s->user->user_record->uid,
230 &s->manager->polkit_registry,
231 error);
232 if (r < 0)
233 return r;
234 if (r == 0)
235 return 1; /* Will call us back */
236
237 r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock"));
238 if (r < 0)
239 return r;
240
241 return sd_bus_reply_method_return(message, NULL);
242 }
243
244 static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
245 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
246 Session *s = userdata;
247 uid_t uid;
248 int r, b;
249
250 assert(message);
251 assert(s);
252
253 r = sd_bus_message_read(message, "b", &b);
254 if (r < 0)
255 return r;
256
257 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
258 if (r < 0)
259 return r;
260
261 r = sd_bus_creds_get_euid(creds, &uid);
262 if (r < 0)
263 return r;
264
265 if (uid != 0 && uid != s->user->user_record->uid)
266 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
267
268 r = session_set_idle_hint(s, b);
269 if (r == -ENOTTY)
270 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical sessions.");
271 if (r < 0)
272 return r;
273
274 return sd_bus_reply_method_return(message, NULL);
275 }
276
277 static int method_set_locked_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
278 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
279 Session *s = userdata;
280 uid_t uid;
281 int r, b;
282
283 assert(message);
284 assert(s);
285
286 r = sd_bus_message_read(message, "b", &b);
287 if (r < 0)
288 return r;
289
290 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
291 if (r < 0)
292 return r;
293
294 r = sd_bus_creds_get_euid(creds, &uid);
295 if (r < 0)
296 return r;
297
298 if (uid != 0 && uid != s->user->user_record->uid)
299 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint");
300
301 session_set_locked_hint(s, b);
302
303 return sd_bus_reply_method_return(message, NULL);
304 }
305
306 int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
307 Session *s = userdata;
308 const char *swho;
309 int32_t signo;
310 KillWho who;
311 int r;
312
313 assert(message);
314 assert(s);
315
316 r = sd_bus_message_read(message, "si", &swho, &signo);
317 if (r < 0)
318 return r;
319
320 if (isempty(swho))
321 who = KILL_ALL;
322 else {
323 who = kill_who_from_string(swho);
324 if (who < 0)
325 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
326 }
327
328 if (!SIGNAL_VALID(signo))
329 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
330
331 r = bus_verify_polkit_async(
332 message,
333 CAP_KILL,
334 "org.freedesktop.login1.manage",
335 NULL,
336 false,
337 s->user->user_record->uid,
338 &s->manager->polkit_registry,
339 error);
340 if (r < 0)
341 return r;
342 if (r == 0)
343 return 1; /* Will call us back */
344
345 r = session_kill(s, who, signo);
346 if (r < 0)
347 return r;
348
349 return sd_bus_reply_method_return(message, NULL);
350 }
351
352 static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
353 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
354 Session *s = userdata;
355 int r, force;
356 uid_t uid;
357
358 assert(message);
359 assert(s);
360
361 r = sd_bus_message_read(message, "b", &force);
362 if (r < 0)
363 return r;
364
365 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
366 if (r < 0)
367 return r;
368
369 r = sd_bus_creds_get_euid(creds, &uid);
370 if (r < 0)
371 return r;
372
373 if (uid != 0 && (force || uid != s->user->user_record->uid))
374 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
375
376 r = session_set_controller(s, sd_bus_message_get_sender(message), force, true);
377 if (r < 0)
378 return r;
379
380 return sd_bus_reply_method_return(message, NULL);
381 }
382
383 static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
384 Session *s = userdata;
385
386 assert(message);
387 assert(s);
388
389 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
390 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
391
392 session_drop_controller(s);
393
394 return sd_bus_reply_method_return(message, NULL);
395 }
396
397 static int method_set_type(sd_bus_message *message, void *userdata, sd_bus_error *error) {
398 Session *s = userdata;
399 const char *t;
400 SessionType type;
401 int r;
402
403 assert(message);
404 assert(s);
405
406 r = sd_bus_message_read(message, "s", &t);
407 if (r < 0)
408 return r;
409
410 type = session_type_from_string(t);
411 if (type < 0)
412 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
413 "Invalid session type '%s'", t);
414
415 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
416 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You must be in control of this session to set type");
417
418 session_set_type(s, type);
419
420 return sd_bus_reply_method_return(message, NULL);
421 }
422
423 static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
424 Session *s = userdata;
425 uint32_t major, minor;
426 SessionDevice *sd;
427 dev_t dev;
428 int r;
429
430 assert(message);
431 assert(s);
432
433 r = sd_bus_message_read(message, "uu", &major, &minor);
434 if (r < 0)
435 return r;
436
437 if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
438 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
439
440 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
441 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
442
443 dev = makedev(major, minor);
444 sd = hashmap_get(s->devices, &dev);
445 if (sd)
446 /* We don't allow retrieving a device multiple times.
447 * The related ReleaseDevice call is not ref-counted.
448 * The caller should use dup() if it requires more
449 * than one fd (it would be functionally
450 * equivalent). */
451 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
452
453 r = session_device_new(s, dev, true, &sd);
454 if (r < 0)
455 return r;
456
457 r = session_device_save(sd);
458 if (r < 0)
459 goto error;
460
461 r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
462 if (r < 0)
463 goto error;
464
465 session_save(s);
466 return 1;
467
468 error:
469 session_device_free(sd);
470 return r;
471 }
472
473 static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
474 Session *s = userdata;
475 uint32_t major, minor;
476 SessionDevice *sd;
477 dev_t dev;
478 int r;
479
480 assert(message);
481 assert(s);
482
483 r = sd_bus_message_read(message, "uu", &major, &minor);
484 if (r < 0)
485 return r;
486
487 if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
488 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
489
490 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
491 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
492
493 dev = makedev(major, minor);
494 sd = hashmap_get(s->devices, &dev);
495 if (!sd)
496 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
497
498 session_device_free(sd);
499 session_save(s);
500
501 return sd_bus_reply_method_return(message, NULL);
502 }
503
504 static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) {
505 Session *s = userdata;
506 uint32_t major, minor;
507 SessionDevice *sd;
508 dev_t dev;
509 int r;
510
511 assert(message);
512 assert(s);
513
514 r = sd_bus_message_read(message, "uu", &major, &minor);
515 if (r < 0)
516 return r;
517
518 if (!DEVICE_MAJOR_VALID(major) || !DEVICE_MINOR_VALID(minor))
519 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Device major/minor is not valid.");
520
521 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
522 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
523
524 dev = makedev(major, minor);
525 sd = hashmap_get(s->devices, &dev);
526 if (!sd)
527 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
528
529 session_device_complete_pause(sd);
530
531 return sd_bus_reply_method_return(message, NULL);
532 }
533
534 static int method_set_brightness(sd_bus_message *message, void *userdata, sd_bus_error *error) {
535 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
536 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
537 const char *subsystem, *name, *seat;
538 Session *s = userdata;
539 uint32_t brightness;
540 uid_t uid;
541 int r;
542
543 assert(message);
544 assert(s);
545
546 r = sd_bus_message_read(message, "ssu", &subsystem, &name, &brightness);
547 if (r < 0)
548 return r;
549
550 if (!STR_IN_SET(subsystem, "backlight", "leds"))
551 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Subsystem type %s not supported, must be one of 'backlight' or 'leds'.", subsystem);
552 if (!filename_is_valid(name))
553 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not a valid device name %s, refusing.", name);
554
555 if (!s->seat)
556 return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Your session has no seat, refusing.");
557 if (s->seat->active != s)
558 return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Session is not in foreground, refusing.");
559
560 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
561 if (r < 0)
562 return r;
563
564 r = sd_bus_creds_get_euid(creds, &uid);
565 if (r < 0)
566 return r;
567
568 if (uid != 0 && uid != s->user->user_record->uid)
569 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may change brightness.");
570
571 r = sd_device_new_from_subsystem_sysname(&d, subsystem, name);
572 if (r < 0)
573 return sd_bus_error_set_errnof(error, r, "Failed to open device %s:%s: %m", subsystem, name);
574
575 if (sd_device_get_property_value(d, "ID_SEAT", &seat) >= 0 && !streq_ptr(seat, s->seat->id))
576 return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Device %s:%s does not belong to your seat %s, refusing.", subsystem, name, s->seat->id);
577
578 r = manager_write_brightness(s->manager, d, brightness, message);
579 if (r < 0)
580 return r;
581
582 return 1;
583 }
584
585 static int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
586 _cleanup_free_ char *e = NULL;
587 sd_bus_message *message;
588 Manager *m = userdata;
589 Session *session;
590 const char *p;
591 int r;
592
593 assert(bus);
594 assert(path);
595 assert(interface);
596 assert(found);
597 assert(m);
598
599 p = startswith(path, "/org/freedesktop/login1/session/");
600 if (!p)
601 return 0;
602
603 e = bus_label_unescape(p);
604 if (!e)
605 return -ENOMEM;
606
607 message = sd_bus_get_current_message(bus);
608
609 r = manager_get_session_from_creds(m, message, e, error, &session);
610 if (r == -ENXIO) {
611 sd_bus_error_free(error);
612 return 0;
613 }
614 if (r < 0)
615 return r;
616
617 *found = session;
618 return 1;
619 }
620
621 char *session_bus_path(Session *s) {
622 _cleanup_free_ char *t = NULL;
623
624 assert(s);
625
626 t = bus_label_escape(s->id);
627 if (!t)
628 return NULL;
629
630 return strjoin("/org/freedesktop/login1/session/", t);
631 }
632
633 static int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
634 _cleanup_strv_free_ char **l = NULL;
635 sd_bus_message *message;
636 Manager *m = userdata;
637 Session *session;
638 Iterator i;
639 int r;
640
641 assert(bus);
642 assert(path);
643 assert(nodes);
644
645 HASHMAP_FOREACH(session, m->sessions, i) {
646 char *p;
647
648 p = session_bus_path(session);
649 if (!p)
650 return -ENOMEM;
651
652 r = strv_consume(&l, p);
653 if (r < 0)
654 return r;
655 }
656
657 message = sd_bus_get_current_message(bus);
658 if (message) {
659 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
660
661 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
662 if (r >= 0) {
663 bool may_auto = false;
664 const char *name;
665
666 r = sd_bus_creds_get_session(creds, &name);
667 if (r >= 0) {
668 session = hashmap_get(m->sessions, name);
669 if (session) {
670 r = strv_extend(&l, "/org/freedesktop/login1/session/self");
671 if (r < 0)
672 return r;
673
674 may_auto = true;
675 }
676 }
677
678 if (!may_auto) {
679 uid_t uid;
680
681 r = sd_bus_creds_get_owner_uid(creds, &uid);
682 if (r >= 0) {
683 User *user;
684
685 user = hashmap_get(m->users, UID_TO_PTR(uid));
686 may_auto = user && user->display;
687 }
688 }
689
690 if (may_auto) {
691 r = strv_extend(&l, "/org/freedesktop/login1/session/auto");
692 if (r < 0)
693 return r;
694 }
695 }
696 }
697
698 *nodes = TAKE_PTR(l);
699 return 1;
700 }
701
702 int session_send_signal(Session *s, bool new_session) {
703 _cleanup_free_ char *p = NULL;
704
705 assert(s);
706
707 p = session_bus_path(s);
708 if (!p)
709 return -ENOMEM;
710
711 return sd_bus_emit_signal(
712 s->manager->bus,
713 "/org/freedesktop/login1",
714 "org.freedesktop.login1.Manager",
715 new_session ? "SessionNew" : "SessionRemoved",
716 "so", s->id, p);
717 }
718
719 int session_send_changed(Session *s, const char *properties, ...) {
720 _cleanup_free_ char *p = NULL;
721 char **l;
722
723 assert(s);
724
725 if (!s->started)
726 return 0;
727
728 p = session_bus_path(s);
729 if (!p)
730 return -ENOMEM;
731
732 l = strv_from_stdarg_alloca(properties);
733
734 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l);
735 }
736
737 int session_send_lock(Session *s, bool lock) {
738 _cleanup_free_ char *p = NULL;
739
740 assert(s);
741
742 p = session_bus_path(s);
743 if (!p)
744 return -ENOMEM;
745
746 return sd_bus_emit_signal(
747 s->manager->bus,
748 p,
749 "org.freedesktop.login1.Session",
750 lock ? "Lock" : "Unlock",
751 NULL);
752 }
753
754 int session_send_lock_all(Manager *m, bool lock) {
755 Session *session;
756 Iterator i;
757 int r = 0;
758
759 assert(m);
760
761 HASHMAP_FOREACH(session, m->sessions, i) {
762 int k;
763
764 k = session_send_lock(session, lock);
765 if (k < 0)
766 r = k;
767 }
768
769 return r;
770 }
771
772 static bool session_ready(Session *s) {
773 assert(s);
774
775 /* Returns true when the session is ready, i.e. all jobs we enqueued for it are done (regardless if successful or not) */
776
777 return !s->scope_job &&
778 !s->user->service_job;
779 }
780
781 int session_send_create_reply(Session *s, sd_bus_error *error) {
782 _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
783 _cleanup_close_ int fifo_fd = -1;
784 _cleanup_free_ char *p = NULL;
785
786 assert(s);
787
788 /* This is called after the session scope and the user service were successfully created, and finishes where
789 * bus_manager_create_session() left off. */
790
791 if (!s->create_message)
792 return 0;
793
794 if (!sd_bus_error_is_set(error) && !session_ready(s))
795 return 0;
796
797 c = TAKE_PTR(s->create_message);
798 if (error)
799 return sd_bus_reply_method_error(c, error);
800
801 fifo_fd = session_create_fifo(s);
802 if (fifo_fd < 0)
803 return fifo_fd;
804
805 /* Update the session state file before we notify the client about the result. */
806 session_save(s);
807
808 p = session_bus_path(s);
809 if (!p)
810 return -ENOMEM;
811
812 log_debug("Sending reply about created session: "
813 "id=%s object_path=%s uid=%u runtime_path=%s "
814 "session_fd=%d seat=%s vtnr=%u",
815 s->id,
816 p,
817 (uint32_t) s->user->user_record->uid,
818 s->user->runtime_path,
819 fifo_fd,
820 s->seat ? s->seat->id : "",
821 (uint32_t) s->vtnr);
822
823 return sd_bus_reply_method_return(
824 c, "soshusub",
825 s->id,
826 p,
827 s->user->runtime_path,
828 fifo_fd,
829 (uint32_t) s->user->user_record->uid,
830 s->seat ? s->seat->id : "",
831 (uint32_t) s->vtnr,
832 false);
833 }
834
835 static const sd_bus_vtable session_vtable[] = {
836 SD_BUS_VTABLE_START(0),
837
838 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST),
839 SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST),
840 SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
841 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
842 SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST),
843 SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST),
844 SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST),
845 SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST),
846 SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST),
847 SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
848 SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
849 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
850 SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
851 SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
852 SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST),
853 SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST),
854 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
855 SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST),
856 SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
857 SD_BUS_PROPERTY("State", "s", property_get_state, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
858 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
859 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
860 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
861 SD_BUS_PROPERTY("LockedHint", "b", property_get_locked_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
862
863 SD_BUS_METHOD("Terminate",
864 NULL,
865 NULL,
866 bus_session_method_terminate,
867 SD_BUS_VTABLE_UNPRIVILEGED),
868 SD_BUS_METHOD("Activate",
869 NULL,
870 NULL,
871 bus_session_method_activate,
872 SD_BUS_VTABLE_UNPRIVILEGED),
873 SD_BUS_METHOD("Lock",
874 NULL,
875 NULL,
876 bus_session_method_lock,
877 SD_BUS_VTABLE_UNPRIVILEGED),
878 SD_BUS_METHOD("Unlock",
879 NULL,
880 NULL,
881 bus_session_method_lock,
882 SD_BUS_VTABLE_UNPRIVILEGED),
883 SD_BUS_METHOD_WITH_NAMES("SetIdleHint",
884 "b",
885 SD_BUS_PARAM(idle),
886 NULL,,
887 method_set_idle_hint,
888 SD_BUS_VTABLE_UNPRIVILEGED),
889 SD_BUS_METHOD_WITH_NAMES("SetLockedHint",
890 "b",
891 SD_BUS_PARAM(locked),
892 NULL,,
893 method_set_locked_hint,
894 SD_BUS_VTABLE_UNPRIVILEGED),
895 SD_BUS_METHOD_WITH_NAMES("Kill",
896 "si",
897 SD_BUS_PARAM(who)
898 SD_BUS_PARAM(signal_number),
899 NULL,,
900 bus_session_method_kill,
901 SD_BUS_VTABLE_UNPRIVILEGED),
902 SD_BUS_METHOD_WITH_NAMES("TakeControl",
903 "b",
904 SD_BUS_PARAM(force),
905 NULL,,
906 method_take_control,
907 SD_BUS_VTABLE_UNPRIVILEGED),
908 SD_BUS_METHOD("ReleaseControl",
909 NULL,
910 NULL,
911 method_release_control,
912 SD_BUS_VTABLE_UNPRIVILEGED),
913 SD_BUS_METHOD_WITH_NAMES("SetType",
914 "s",
915 SD_BUS_PARAM(type),
916 NULL,,
917 method_set_type,
918 SD_BUS_VTABLE_UNPRIVILEGED),
919 SD_BUS_METHOD_WITH_NAMES("TakeDevice",
920 "uu",
921 SD_BUS_PARAM(major)
922 SD_BUS_PARAM(minor),
923 "hb",
924 SD_BUS_PARAM(fd)
925 SD_BUS_PARAM(inactive),
926 method_take_device,
927 SD_BUS_VTABLE_UNPRIVILEGED),
928 SD_BUS_METHOD_WITH_NAMES("ReleaseDevice",
929 "uu",
930 SD_BUS_PARAM(major)
931 SD_BUS_PARAM(minor),
932 NULL,,
933 method_release_device,
934 SD_BUS_VTABLE_UNPRIVILEGED),
935 SD_BUS_METHOD_WITH_NAMES("PauseDeviceComplete",
936 "uu",
937 SD_BUS_PARAM(major)
938 SD_BUS_PARAM(minor),
939 NULL,,
940 method_pause_device_complete,
941 SD_BUS_VTABLE_UNPRIVILEGED),
942 SD_BUS_METHOD_WITH_NAMES("SetBrightness",
943 "ssu",
944 SD_BUS_PARAM(subsystem)
945 SD_BUS_PARAM(name)
946 SD_BUS_PARAM(brightness),
947 NULL,,
948 method_set_brightness,
949 SD_BUS_VTABLE_UNPRIVILEGED),
950
951 SD_BUS_SIGNAL_WITH_NAMES("PauseDevice",
952 "uus",
953 SD_BUS_PARAM(major)
954 SD_BUS_PARAM(minor)
955 SD_BUS_PARAM(type),
956 0),
957 SD_BUS_SIGNAL_WITH_NAMES("ResumeDevice",
958 "uuh",
959 SD_BUS_PARAM(major)
960 SD_BUS_PARAM(minor)
961 SD_BUS_PARAM(fd),
962 0),
963 SD_BUS_SIGNAL("Lock", NULL, 0),
964 SD_BUS_SIGNAL("Unlock", NULL, 0),
965
966 SD_BUS_VTABLE_END
967 };
968
969 const BusObjectImplementation session_object = {
970 "/org/freedesktop/login1/session",
971 "org.freedesktop.login1.Session",
972 .fallback_vtables = BUS_FALLBACK_VTABLES({session_vtable, session_object_find}),
973 .node_enumerator = session_node_enumerator,
974 };