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