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