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