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