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