]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-session-dbus.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / login / logind-session-dbus.c
CommitLineData
3f49d45a
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2011 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
3f49d45a
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
3f49d45a 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
3f49d45a
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
a185c5aa 23#include <string.h>
3f49d45a 24
b5efdb8a 25#include "alloc-util.h"
96aad8d1 26#include "bus-common-errors.h"
a6278b88 27#include "bus-label.h"
3ffd4af2
LP
28#include "bus-util.h"
29#include "fd-util.h"
118ecf32 30#include "logind-session-device.h"
3ffd4af2
LP
31#include "logind-session.h"
32#include "logind.h"
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
19070062 184int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
185 Session *s = userdata;
186 int r;
0604381b 187
cc377381 188 assert(message);
0604381b
LP
189 assert(s);
190
c529695e
LP
191 r = bus_verify_polkit_async(
192 message,
193 CAP_KILL,
194 "org.freedesktop.login1.manage",
403ed0e5 195 NULL,
c529695e
LP
196 false,
197 s->user->uid,
198 &s->manager->polkit_registry,
199 error);
200 if (r < 0)
201 return r;
202 if (r == 0)
203 return 1; /* Will call us back */
204
9bb69af4 205 r = session_stop(s, true);
cc377381 206 if (r < 0)
ebcf1f97 207 return r;
0604381b 208
df2d202e 209 return sd_bus_reply_method_return(message, NULL);
0604381b
LP
210}
211
19070062 212int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
213 Session *s = userdata;
214 int r;
3f49d45a 215
cc377381
LP
216 assert(message);
217 assert(s);
3f49d45a 218
cc377381
LP
219 r = session_activate(s);
220 if (r < 0)
ebcf1f97 221 return r;
3f49d45a 222
df2d202e 223 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
224}
225
19070062 226int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
227 Session *s = userdata;
228 int r;
229
cc377381
LP
230 assert(message);
231 assert(s);
3f49d45a 232
c529695e
LP
233 r = bus_verify_polkit_async(
234 message,
235 CAP_SYS_ADMIN,
236 "org.freedesktop.login1.lock-sessions",
403ed0e5 237 NULL,
c529695e
LP
238 false,
239 s->user->uid,
240 &s->manager->polkit_registry,
241 error);
242 if (r < 0)
243 return r;
244 if (r == 0)
245 return 1; /* Will call us back */
246
247 r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock"));
cc377381 248 if (r < 0)
ebcf1f97 249 return r;
3f49d45a 250
df2d202e 251 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
252}
253
19070062 254static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
5b12334d 255 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
cc377381
LP
256 Session *s = userdata;
257 uid_t uid;
258 int r, b;
d200735e 259
cc377381
LP
260 assert(message);
261 assert(s);
262
263 r = sd_bus_message_read(message, "b", &b);
264 if (r < 0)
ebcf1f97 265 return r;
d200735e 266
05bae4a6 267 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
5b12334d
LP
268 if (r < 0)
269 return r;
270
05bae4a6 271 r = sd_bus_creds_get_euid(creds, &uid);
cc377381 272 if (r < 0)
ebcf1f97 273 return r;
cc377381
LP
274
275 if (uid != 0 && uid != s->user->uid)
2b233285 276 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
cc377381
LP
277
278 session_set_idle_hint(s, b);
3f49d45a 279
df2d202e 280 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
281}
282
19070062 283int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
284 Session *s = userdata;
285 const char *swho;
286 int32_t signo;
287 KillWho who;
bef422ae
LP
288 int r;
289
3f49d45a 290 assert(message);
cc377381 291 assert(s);
3f49d45a 292
cc377381
LP
293 r = sd_bus_message_read(message, "si", &swho, &signo);
294 if (r < 0)
ebcf1f97 295 return r;
cc377381
LP
296
297 if (isempty(swho))
298 who = KILL_ALL;
299 else {
300 who = kill_who_from_string(swho);
301 if (who < 0)
ebcf1f97 302 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
cc377381 303 }
bef422ae 304
cc377381 305 if (signo <= 0 || signo >= _NSIG)
ebcf1f97 306 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
bef422ae 307
c529695e
LP
308 r = bus_verify_polkit_async(
309 message,
310 CAP_KILL,
311 "org.freedesktop.login1.manage",
403ed0e5 312 NULL,
c529695e
LP
313 false,
314 s->user->uid,
315 &s->manager->polkit_registry,
316 error);
317 if (r < 0)
318 return r;
319 if (r == 0)
320 return 1; /* Will call us back */
321
cc377381
LP
322 r = session_kill(s, who, signo);
323 if (r < 0)
ebcf1f97 324 return r;
bef422ae 325
df2d202e 326 return sd_bus_reply_method_return(message, NULL);
cc377381 327}
bef422ae 328
19070062 329static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
5b12334d 330 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
cc377381
LP
331 Session *s = userdata;
332 int r, force;
333 uid_t uid;
bef422ae 334
cc377381
LP
335 assert(message);
336 assert(s);
bef422ae 337
cc377381
LP
338 r = sd_bus_message_read(message, "b", &force);
339 if (r < 0)
ebcf1f97 340 return r;
bef422ae 341
05bae4a6 342 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
5b12334d
LP
343 if (r < 0)
344 return r;
345
05bae4a6 346 r = sd_bus_creds_get_euid(creds, &uid);
cc377381 347 if (r < 0)
ebcf1f97 348 return r;
bef422ae 349
cc377381 350 if (uid != 0 && (force || uid != s->user->uid))
ebcf1f97 351 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
bef422ae 352
cc377381
LP
353 r = session_set_controller(s, sd_bus_message_get_sender(message), force);
354 if (r < 0)
ebcf1f97 355 return r;
bef422ae 356
df2d202e 357 return sd_bus_reply_method_return(message, NULL);
cc377381 358}
bef422ae 359
19070062 360static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 361 Session *s = userdata;
bef422ae 362
cc377381
LP
363 assert(message);
364 assert(s);
5bc849fd 365
cc377381 366 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 367 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
5bc849fd 368
cc377381 369 session_drop_controller(s);
bef422ae 370
df2d202e 371 return sd_bus_reply_method_return(message, NULL);
cc377381 372}
bef422ae 373
19070062 374static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
375 Session *s = userdata;
376 uint32_t major, minor;
377 SessionDevice *sd;
378 dev_t dev;
379 int r;
de07ab16 380
cc377381
LP
381 assert(message);
382 assert(s);
de07ab16 383
cc377381
LP
384 r = sd_bus_message_read(message, "uu", &major, &minor);
385 if (r < 0)
ebcf1f97 386 return r;
cc377381
LP
387
388 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 389 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
cc377381
LP
390
391 dev = makedev(major, minor);
392 sd = hashmap_get(s->devices, &dev);
393 if (sd)
394 /* We don't allow retrieving a device multiple times.
395 * The related ReleaseDevice call is not ref-counted.
396 * The caller should use dup() if it requires more
397 * than one fd (it would be functionally
398 * equivalent). */
ebcf1f97 399 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
cc377381
LP
400
401 r = session_device_new(s, dev, &sd);
402 if (r < 0)
ebcf1f97 403 return r;
de07ab16 404
df2d202e 405 r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
cc377381
LP
406 if (r < 0)
407 session_device_free(sd);
118ecf32 408
cc377381
LP
409 return r;
410}
118ecf32 411
19070062 412static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
413 Session *s = userdata;
414 uint32_t major, minor;
415 SessionDevice *sd;
416 dev_t dev;
417 int r;
118ecf32 418
cc377381
LP
419 assert(message);
420 assert(s);
118ecf32 421
cc377381
LP
422 r = sd_bus_message_read(message, "uu", &major, &minor);
423 if (r < 0)
ebcf1f97 424 return r;
118ecf32 425
cc377381 426 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 427 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
118ecf32 428
cc377381
LP
429 dev = makedev(major, minor);
430 sd = hashmap_get(s->devices, &dev);
431 if (!sd)
ebcf1f97 432 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
118ecf32 433
cc377381 434 session_device_free(sd);
df2d202e 435 return sd_bus_reply_method_return(message, NULL);
cc377381 436}
118ecf32 437
19070062 438static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
439 Session *s = userdata;
440 uint32_t major, minor;
441 SessionDevice *sd;
442 dev_t dev;
443 int r;
118ecf32 444
cc377381
LP
445 assert(message);
446 assert(s);
bef422ae 447
cc377381
LP
448 r = sd_bus_message_read(message, "uu", &major, &minor);
449 if (r < 0)
ebcf1f97 450 return r;
cc377381
LP
451
452 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 453 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
bef422ae 454
cc377381
LP
455 dev = makedev(major, minor);
456 sd = hashmap_get(s->devices, &dev);
457 if (!sd)
ebcf1f97 458 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
bef422ae 459
cc377381 460 session_device_complete_pause(sd);
bef422ae 461
df2d202e 462 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
463}
464
cc377381
LP
465const sd_bus_vtable session_vtable[] = {
466 SD_BUS_VTABLE_START(0),
467
556089dc
LP
468 SD_BUS_PROPERTY("Id", "s", NULL, offsetof(Session, id), SD_BUS_VTABLE_PROPERTY_CONST),
469 SD_BUS_PROPERTY("User", "(uo)", property_get_user, 0, SD_BUS_VTABLE_PROPERTY_CONST),
470 SD_BUS_PROPERTY("Name", "s", property_get_name, 0, SD_BUS_VTABLE_PROPERTY_CONST),
471 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Session, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
472 SD_BUS_PROPERTY("VTNr", "u", NULL, offsetof(Session, vtnr), SD_BUS_VTABLE_PROPERTY_CONST),
473 SD_BUS_PROPERTY("Seat", "(so)", property_get_seat, 0, SD_BUS_VTABLE_PROPERTY_CONST),
474 SD_BUS_PROPERTY("TTY", "s", NULL, offsetof(Session, tty), SD_BUS_VTABLE_PROPERTY_CONST),
475 SD_BUS_PROPERTY("Display", "s", NULL, offsetof(Session, display), SD_BUS_VTABLE_PROPERTY_CONST),
476 SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST),
477 SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
478 SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
479 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
a4cd87e9 480 SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
481 SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
482 SD_BUS_PROPERTY("Leader", "u", bus_property_get_pid, offsetof(Session, leader), SD_BUS_VTABLE_PROPERTY_CONST),
483 SD_BUS_PROPERTY("Audit", "u", NULL, offsetof(Session, audit_id), SD_BUS_VTABLE_PROPERTY_CONST),
484 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Session, type), SD_BUS_VTABLE_PROPERTY_CONST),
485 SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Session, class), SD_BUS_VTABLE_PROPERTY_CONST),
cc377381
LP
486 SD_BUS_PROPERTY("Active", "b", property_get_active, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
487 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
488 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
489 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
490 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
491
c529695e
LP
492 SD_BUS_METHOD("Terminate", NULL, NULL, bus_session_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
493 SD_BUS_METHOD("Activate", NULL, NULL, bus_session_method_activate, SD_BUS_VTABLE_UNPRIVILEGED),
494 SD_BUS_METHOD("Lock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
495 SD_BUS_METHOD("Unlock", NULL, NULL, bus_session_method_lock, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957 496 SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
c529695e 497 SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
498 SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED),
499 SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED),
500 SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED),
501 SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED),
502 SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED),
cc377381
LP
503
504 SD_BUS_SIGNAL("PauseDevice", "uus", 0),
505 SD_BUS_SIGNAL("ResumeDevice", "uuh", 0),
506 SD_BUS_SIGNAL("Lock", NULL, 0),
507 SD_BUS_SIGNAL("Unlock", NULL, 0),
508
509 SD_BUS_VTABLE_END
510};
3f49d45a 511
f00c3121 512int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
3f49d45a 513 Manager *m = userdata;
cc377381 514 Session *session;
927b1649 515 int r;
3f49d45a 516
cc377381
LP
517 assert(bus);
518 assert(path);
519 assert(interface);
520 assert(found);
521 assert(m);
3f49d45a 522
927b1649 523 if (streq(path, "/org/freedesktop/login1/session/self")) {
5b12334d 524 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
927b1649 525 sd_bus_message *message;
309a29df 526 const char *name;
3f49d45a 527
19befb2d 528 message = sd_bus_get_current_message(bus);
927b1649
LP
529 if (!message)
530 return 0;
531
309a29df 532 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
927b1649 533 if (r < 0)
5b12334d
LP
534 return r;
535
309a29df 536 r = sd_bus_creds_get_session(creds, &name);
5b12334d
LP
537 if (r < 0)
538 return r;
927b1649 539
309a29df 540 session = hashmap_get(m->sessions, name);
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);
927b1649 554 }
3f49d45a 555
309a29df
LP
556 if (!session)
557 return 0;
558
cc377381
LP
559 *found = session;
560 return 1;
3f49d45a
LP
561}
562
3f49d45a 563char *session_bus_path(Session *s) {
9444b1f2 564 _cleanup_free_ char *t = NULL;
3f49d45a
LP
565
566 assert(s);
567
a6278b88 568 t = bus_label_escape(s->id);
3f49d45a
LP
569 if (!t)
570 return NULL;
571
4654e558 572 return strappend("/org/freedesktop/login1/session/", t);
3f49d45a 573}
da119395 574
f00c3121 575int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
cc377381 576 _cleanup_strv_free_ char **l = NULL;
ca56b0a6 577 sd_bus_message *message;
cc377381
LP
578 Manager *m = userdata;
579 Session *session;
580 Iterator i;
581 int r;
582
583 assert(bus);
584 assert(path);
585 assert(nodes);
586
587 HASHMAP_FOREACH(session, m->sessions, i) {
588 char *p;
589
590 p = session_bus_path(session);
591 if (!p)
592 return -ENOMEM;
593
6e18964d
ZJS
594 r = strv_consume(&l, p);
595 if (r < 0)
cc377381 596 return r;
cc377381
LP
597 }
598
ca56b0a6
DH
599 message = sd_bus_get_current_message(bus);
600 if (message) {
601 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
602 const char *name;
603
604 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
605 if (r >= 0) {
606 r = sd_bus_creds_get_session(creds, &name);
607 if (r >= 0) {
608 session = hashmap_get(m->sessions, name);
609 if (session) {
610 r = strv_extend(&l, "/org/freedesktop/login1/session/self");
611 if (r < 0)
612 return r;
613 }
614 }
615 }
616 }
b298e984 617
cc377381
LP
618 *nodes = l;
619 l = NULL;
620
621 return 1;
622}
623
da119395 624int session_send_signal(Session *s, bool new_session) {
ce0fc5f5 625 _cleanup_free_ char *p = NULL;
da119395
LP
626
627 assert(s);
628
da119395
LP
629 p = session_bus_path(s);
630 if (!p)
4654e558 631 return -ENOMEM;
da119395 632
cc377381
LP
633 return sd_bus_emit_signal(
634 s->manager->bus,
635 "/org/freedesktop/login1",
636 "org.freedesktop.login1.Manager",
637 new_session ? "SessionNew" : "SessionRemoved",
638 "so", s->id, p);
da119395 639}
9418f147 640
cc377381 641int session_send_changed(Session *s, const char *properties, ...) {
ce0fc5f5 642 _cleanup_free_ char *p = NULL;
cc377381 643 char **l;
9418f147
LP
644
645 assert(s);
646
ed18b08b
LP
647 if (!s->started)
648 return 0;
649
9418f147
LP
650 p = session_bus_path(s);
651 if (!p)
652 return -ENOMEM;
653
cc377381 654 l = strv_from_stdarg_alloca(properties);
9418f147 655
cc377381 656 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l);
9418f147 657}
88e3dc90
LP
658
659int session_send_lock(Session *s, bool lock) {
ce0fc5f5 660 _cleanup_free_ char *p = NULL;
88e3dc90
LP
661
662 assert(s);
663
664 p = session_bus_path(s);
665 if (!p)
666 return -ENOMEM;
667
cc377381
LP
668 return sd_bus_emit_signal(
669 s->manager->bus,
670 p,
671 "org.freedesktop.login1.Session",
672 lock ? "Lock" : "Unlock",
673 NULL);
88e3dc90 674}
7ba64386
LP
675
676int session_send_lock_all(Manager *m, bool lock) {
677 Session *session;
678 Iterator i;
679 int r = 0;
680
681 assert(m);
682
683 HASHMAP_FOREACH(session, m->sessions, i) {
684 int k;
685
686 k = session_send_lock(session, lock);
687 if (k < 0)
688 r = k;
689 }
690
691 return r;
692}
fb6becb4 693
cc377381
LP
694int session_send_create_reply(Session *s, sd_bus_error *error) {
695 _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
696 _cleanup_close_ int fifo_fd = -1;
697 _cleanup_free_ char *p = NULL;
fb6becb4
LP
698
699 assert(s);
700
dd9b67aa
LP
701 /* This is called after the session scope and the user service
702 * were successfully created, and finishes where
703 * bus_manager_create_session() left off. */
cba38758 704
cc377381
LP
705 if (!s->create_message)
706 return 0;
fb6becb4 707
dd9b67aa
LP
708 if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
709 return 0;
710
cc377381
LP
711 c = s->create_message;
712 s->create_message = NULL;
fb6becb4 713
cc377381 714 if (error)
df2d202e 715 return sd_bus_reply_method_error(c, error);
fb6becb4 716
cc377381
LP
717 fifo_fd = session_create_fifo(s);
718 if (fifo_fd < 0)
719 return fifo_fd;
fb6becb4 720
38fdcbed
TA
721 /* Update the session state file before we notify the client
722 * about the result. */
723 session_save(s);
724
cc377381
LP
725 p = session_bus_path(s);
726 if (!p)
727 return -ENOMEM;
fb6becb4 728
5a330cda 729 log_debug("Sending reply about created session: "
236af516
DH
730 "id=%s object_path=%s uid=%u runtime_path=%s "
731 "session_fd=%d seat=%s vtnr=%u",
5a330cda
ZJS
732 s->id,
733 p,
236af516 734 (uint32_t) s->user->uid,
5a330cda
ZJS
735 s->user->runtime_path,
736 fifo_fd,
737 s->seat ? s->seat->id : "",
738 (uint32_t) s->vtnr);
739
cc377381 740 return sd_bus_reply_method_return(
baae0358 741 c, "soshusub",
cc377381
LP
742 s->id,
743 p,
744 s->user->runtime_path,
745 fifo_fd,
baae0358 746 (uint32_t) s->user->uid,
cc377381
LP
747 s->seat ? s->seat->id : "",
748 (uint32_t) s->vtnr,
749 false);
fb6becb4 750}