]>
Commit | Line | Data |
---|---|---|
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 |
40 | static 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 |
62 | static 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 |
79 | static 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 |
101 | static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType); |
102 | static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass); | |
01adcd69 YW |
103 | static BUS_DEFINE_PROPERTY_GET(property_get_active, "b", Session, session_is_active); |
104 | static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Session, session_get_state, session_state_to_string); | |
cc377381 LP |
105 | |
106 | static 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 |
123 | static 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 | ||
140 | static 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 |
157 | static 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 |
183 | static 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 | 200 | int 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 | 226 | int 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 | 245 | int 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 | 273 | static 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 |
305 | static 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 | 337 | int 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 | 381 | static 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 | 411 | static 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 | 424 | static 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 |
452 | static 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 |
508 | static 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 |
532 | static 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 | 567 | static 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 | 617 | static 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 | 647 | static 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 |
676 | static 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 | 729 | static 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 | 764 | char* 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 | 776 | static 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 | 844 | int 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 | 861 | int 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 | |
876 | int 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 | |
896 | int 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 | 913 | int 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 | 958 | int 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 |
978 | static 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 | ||
1107 | const 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 | }; |