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