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