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