Branch data 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 : : }
|