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