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