]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-session-dbus.c
Merge pull request #1140 from poettering/sd-event-signals
[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
cc377381
LP
25#include "util.h"
26#include "strv.h"
27#include "bus-util.h"
96aad8d1 28#include "bus-common-errors.h"
a6278b88 29#include "bus-label.h"
cc377381 30
3f49d45a
LP
31#include "logind.h"
32#include "logind-session.h"
118ecf32 33#include "logind-session-device.h"
3f49d45a 34
cc377381
LP
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,
ebcf1f97
LP
41 void *userdata,
42 sd_bus_error *error) {
cc377381
LP
43
44 _cleanup_free_ char *p = NULL;
45 Session *s = userdata;
46
47 assert(bus);
48 assert(reply);
3f49d45a
LP
49 assert(s);
50
cc377381
LP
51 p = user_bus_path(s->user);
52 if (!p)
3f49d45a
LP
53 return -ENOMEM;
54
cc377381
LP
55 return sd_bus_message_append(reply, "(uo)", (uint32_t) s->user->uid, p);
56}
3f49d45a 57
cc377381
LP
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,
ebcf1f97
LP
64 void *userdata,
65 sd_bus_error *error) {
3f49d45a 66
cc377381 67 Session *s = userdata;
3f49d45a 68
cc377381
LP
69 assert(bus);
70 assert(reply);
71 assert(s);
3f49d45a 72
cc377381 73 return sd_bus_message_append(reply, "s", s->user->name);
3f49d45a
LP
74}
75
cc377381
LP
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,
ebcf1f97
LP
82 void *userdata,
83 sd_bus_error *error) {
3f49d45a 84
cc377381
LP
85 _cleanup_free_ char *p = NULL;
86 Session *s = userdata;
3f49d45a 87
cc377381
LP
88 assert(bus);
89 assert(reply);
90 assert(s);
3f49d45a 91
cc377381 92 p = s->seat ? seat_bus_path(s->seat) : strdup("/");
3f49d45a
LP
93 if (!p)
94 return -ENOMEM;
95
cc377381
LP
96 return sd_bus_message_append(reply, "(so)", s->seat ? s->seat->id : "", p);
97}
3f49d45a 98
cc377381
LP
99static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, session_type, SessionType);
100static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, session_class, SessionClass);
3f49d45a 101
cc377381
LP
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,
ebcf1f97
LP
108 void *userdata,
109 sd_bus_error *error) {
3f49d45a 110
cc377381 111 Session *s = userdata;
3f49d45a 112
cc377381
LP
113 assert(bus);
114 assert(reply);
3f49d45a
LP
115 assert(s);
116
cc377381 117 return sd_bus_message_append(reply, "b", session_is_active(s));
3f49d45a
LP
118}
119
cc377381
LP
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,
ebcf1f97
LP
126 void *userdata,
127 sd_bus_error *error) {
a185c5aa 128
cc377381
LP
129 Session *s = userdata;
130
131 assert(bus);
132 assert(reply);
a185c5aa
LP
133 assert(s);
134
cc377381
LP
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,
ebcf1f97
LP
144 void *userdata,
145 sd_bus_error *error) {
a185c5aa 146
cc377381
LP
147 Session *s = userdata;
148
149 assert(bus);
150 assert(reply);
151 assert(s);
152
153 return sd_bus_message_append(reply, "b", session_get_idle_hint(s, NULL) > 0);
a185c5aa
LP
154}
155
cc377381
LP
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,
ebcf1f97
LP
162 void *userdata,
163 sd_bus_error *error) {
cc377381
LP
164
165 Session *s = userdata;
5cb14b37 166 dual_timestamp t = DUAL_TIMESTAMP_NULL;
a185c5aa 167 uint64_t u;
ca4f2b6d 168 int r;
a185c5aa 169
cc377381
LP
170 assert(bus);
171 assert(reply);
a185c5aa
LP
172 assert(s);
173
ca4f2b6d
VP
174 r = session_get_idle_hint(s, &t);
175 if (r < 0)
176 return r;
177
a185c5aa
LP
178 u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
179
cc377381 180 return sd_bus_message_append(reply, "t", u);
a185c5aa
LP
181}
182
19070062 183int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
184 Session *s = userdata;
185 int r;
0604381b 186
cc377381 187 assert(message);
0604381b
LP
188 assert(s);
189
c529695e
LP
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
9bb69af4 203 r = session_stop(s, true);
cc377381 204 if (r < 0)
ebcf1f97 205 return r;
0604381b 206
df2d202e 207 return sd_bus_reply_method_return(message, NULL);
0604381b
LP
208}
209
19070062 210int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
211 Session *s = userdata;
212 int r;
3f49d45a 213
cc377381
LP
214 assert(message);
215 assert(s);
3f49d45a 216
cc377381
LP
217 r = session_activate(s);
218 if (r < 0)
ebcf1f97 219 return r;
3f49d45a 220
df2d202e 221 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
222}
223
19070062 224int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
225 Session *s = userdata;
226 int r;
227
cc377381
LP
228 assert(message);
229 assert(s);
3f49d45a 230
c529695e
LP
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"));
cc377381 245 if (r < 0)
ebcf1f97 246 return r;
3f49d45a 247
df2d202e 248 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
249}
250
19070062 251static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_error *error) {
5b12334d 252 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
cc377381
LP
253 Session *s = userdata;
254 uid_t uid;
255 int r, b;
d200735e 256
cc377381
LP
257 assert(message);
258 assert(s);
259
260 r = sd_bus_message_read(message, "b", &b);
261 if (r < 0)
ebcf1f97 262 return r;
d200735e 263
05bae4a6 264 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
5b12334d
LP
265 if (r < 0)
266 return r;
267
05bae4a6 268 r = sd_bus_creds_get_euid(creds, &uid);
cc377381 269 if (r < 0)
ebcf1f97 270 return r;
cc377381
LP
271
272 if (uid != 0 && uid != s->user->uid)
2b233285 273 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set idle hint");
cc377381
LP
274
275 session_set_idle_hint(s, b);
3f49d45a 276
df2d202e 277 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
278}
279
19070062 280int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
281 Session *s = userdata;
282 const char *swho;
283 int32_t signo;
284 KillWho who;
bef422ae
LP
285 int r;
286
3f49d45a 287 assert(message);
cc377381 288 assert(s);
3f49d45a 289
cc377381
LP
290 r = sd_bus_message_read(message, "si", &swho, &signo);
291 if (r < 0)
ebcf1f97 292 return r;
cc377381
LP
293
294 if (isempty(swho))
295 who = KILL_ALL;
296 else {
297 who = kill_who_from_string(swho);
298 if (who < 0)
ebcf1f97 299 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
cc377381 300 }
bef422ae 301
cc377381 302 if (signo <= 0 || signo >= _NSIG)
ebcf1f97 303 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
bef422ae 304
c529695e
LP
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
cc377381
LP
318 r = session_kill(s, who, signo);
319 if (r < 0)
ebcf1f97 320 return r;
bef422ae 321
df2d202e 322 return sd_bus_reply_method_return(message, NULL);
cc377381 323}
bef422ae 324
19070062 325static int method_take_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
5b12334d 326 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
cc377381
LP
327 Session *s = userdata;
328 int r, force;
329 uid_t uid;
bef422ae 330
cc377381
LP
331 assert(message);
332 assert(s);
bef422ae 333
cc377381
LP
334 r = sd_bus_message_read(message, "b", &force);
335 if (r < 0)
ebcf1f97 336 return r;
bef422ae 337
05bae4a6 338 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
5b12334d
LP
339 if (r < 0)
340 return r;
341
05bae4a6 342 r = sd_bus_creds_get_euid(creds, &uid);
cc377381 343 if (r < 0)
ebcf1f97 344 return r;
bef422ae 345
cc377381 346 if (uid != 0 && (force || uid != s->user->uid))
ebcf1f97 347 return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may take control");
bef422ae 348
cc377381
LP
349 r = session_set_controller(s, sd_bus_message_get_sender(message), force);
350 if (r < 0)
ebcf1f97 351 return r;
bef422ae 352
df2d202e 353 return sd_bus_reply_method_return(message, NULL);
cc377381 354}
bef422ae 355
19070062 356static int method_release_control(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 357 Session *s = userdata;
bef422ae 358
cc377381
LP
359 assert(message);
360 assert(s);
5bc849fd 361
cc377381 362 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 363 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
5bc849fd 364
cc377381 365 session_drop_controller(s);
bef422ae 366
df2d202e 367 return sd_bus_reply_method_return(message, NULL);
cc377381 368}
bef422ae 369
19070062 370static int method_take_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
371 Session *s = userdata;
372 uint32_t major, minor;
373 SessionDevice *sd;
374 dev_t dev;
375 int r;
de07ab16 376
cc377381
LP
377 assert(message);
378 assert(s);
de07ab16 379
cc377381
LP
380 r = sd_bus_message_read(message, "uu", &major, &minor);
381 if (r < 0)
ebcf1f97 382 return r;
cc377381
LP
383
384 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 385 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
cc377381
LP
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). */
ebcf1f97 395 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_IS_TAKEN, "Device already taken");
cc377381
LP
396
397 r = session_device_new(s, dev, &sd);
398 if (r < 0)
ebcf1f97 399 return r;
de07ab16 400
df2d202e 401 r = sd_bus_reply_method_return(message, "hb", sd->fd, !sd->active);
cc377381
LP
402 if (r < 0)
403 session_device_free(sd);
118ecf32 404
cc377381
LP
405 return r;
406}
118ecf32 407
19070062 408static int method_release_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
409 Session *s = userdata;
410 uint32_t major, minor;
411 SessionDevice *sd;
412 dev_t dev;
413 int r;
118ecf32 414
cc377381
LP
415 assert(message);
416 assert(s);
118ecf32 417
cc377381
LP
418 r = sd_bus_message_read(message, "uu", &major, &minor);
419 if (r < 0)
ebcf1f97 420 return r;
118ecf32 421
cc377381 422 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 423 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
118ecf32 424
cc377381
LP
425 dev = makedev(major, minor);
426 sd = hashmap_get(s->devices, &dev);
427 if (!sd)
ebcf1f97 428 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
118ecf32 429
cc377381 430 session_device_free(sd);
df2d202e 431 return sd_bus_reply_method_return(message, NULL);
cc377381 432}
118ecf32 433
19070062 434static int method_pause_device_complete(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
435 Session *s = userdata;
436 uint32_t major, minor;
437 SessionDevice *sd;
438 dev_t dev;
439 int r;
118ecf32 440
cc377381
LP
441 assert(message);
442 assert(s);
bef422ae 443
cc377381
LP
444 r = sd_bus_message_read(message, "uu", &major, &minor);
445 if (r < 0)
ebcf1f97 446 return r;
cc377381
LP
447
448 if (!session_is_controller(s, sd_bus_message_get_sender(message)))
ebcf1f97 449 return sd_bus_error_setf(error, BUS_ERROR_NOT_IN_CONTROL, "You are not in control of this session");
bef422ae 450
cc377381
LP
451 dev = makedev(major, minor);
452 sd = hashmap_get(s->devices, &dev);
453 if (!sd)
ebcf1f97 454 return sd_bus_error_setf(error, BUS_ERROR_DEVICE_NOT_TAKEN, "Device not taken");
bef422ae 455
cc377381 456 session_device_complete_pause(sd);
bef422ae 457
df2d202e 458 return sd_bus_reply_method_return(message, NULL);
3f49d45a
LP
459}
460
cc377381
LP
461const sd_bus_vtable session_vtable[] = {
462 SD_BUS_VTABLE_START(0),
463
556089dc
LP
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),
a4cd87e9 476 SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
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),
cc377381
LP
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
c529695e
LP
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),
adacb957 492 SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED),
c529695e 493 SD_BUS_METHOD("Kill", "si", NULL, bus_session_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
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),
cc377381
LP
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};
3f49d45a 507
f00c3121 508int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
3f49d45a 509 Manager *m = userdata;
cc377381 510 Session *session;
927b1649 511 int r;
3f49d45a 512
cc377381
LP
513 assert(bus);
514 assert(path);
515 assert(interface);
516 assert(found);
517 assert(m);
3f49d45a 518
927b1649 519 if (streq(path, "/org/freedesktop/login1/session/self")) {
5b12334d 520 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
927b1649 521 sd_bus_message *message;
309a29df 522 const char *name;
3f49d45a 523
19befb2d 524 message = sd_bus_get_current_message(bus);
927b1649
LP
525 if (!message)
526 return 0;
527
309a29df 528 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
927b1649 529 if (r < 0)
5b12334d
LP
530 return r;
531
309a29df 532 r = sd_bus_creds_get_session(creds, &name);
5b12334d
LP
533 if (r < 0)
534 return r;
927b1649 535
309a29df 536 session = hashmap_get(m->sessions, name);
927b1649
LP
537 } else {
538 _cleanup_free_ char *e = NULL;
539 const char *p;
3f49d45a 540
927b1649
LP
541 p = startswith(path, "/org/freedesktop/login1/session/");
542 if (!p)
543 return 0;
544
a6278b88 545 e = bus_label_unescape(p);
927b1649
LP
546 if (!e)
547 return -ENOMEM;
548
549 session = hashmap_get(m->sessions, e);
927b1649 550 }
3f49d45a 551
309a29df
LP
552 if (!session)
553 return 0;
554
cc377381
LP
555 *found = session;
556 return 1;
3f49d45a
LP
557}
558
3f49d45a 559char *session_bus_path(Session *s) {
9444b1f2 560 _cleanup_free_ char *t = NULL;
3f49d45a
LP
561
562 assert(s);
563
a6278b88 564 t = bus_label_escape(s->id);
3f49d45a
LP
565 if (!t)
566 return NULL;
567
4654e558 568 return strappend("/org/freedesktop/login1/session/", t);
3f49d45a 569}
da119395 570
f00c3121 571int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
cc377381 572 _cleanup_strv_free_ char **l = NULL;
ca56b0a6 573 sd_bus_message *message;
cc377381
LP
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
6e18964d
ZJS
590 r = strv_consume(&l, p);
591 if (r < 0)
cc377381 592 return r;
cc377381
LP
593 }
594
ca56b0a6
DH
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 }
b298e984 613
cc377381
LP
614 *nodes = l;
615 l = NULL;
616
617 return 1;
618}
619
da119395 620int session_send_signal(Session *s, bool new_session) {
ce0fc5f5 621 _cleanup_free_ char *p = NULL;
da119395
LP
622
623 assert(s);
624
da119395
LP
625 p = session_bus_path(s);
626 if (!p)
4654e558 627 return -ENOMEM;
da119395 628
cc377381
LP
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);
da119395 635}
9418f147 636
cc377381 637int session_send_changed(Session *s, const char *properties, ...) {
ce0fc5f5 638 _cleanup_free_ char *p = NULL;
cc377381 639 char **l;
9418f147
LP
640
641 assert(s);
642
ed18b08b
LP
643 if (!s->started)
644 return 0;
645
9418f147
LP
646 p = session_bus_path(s);
647 if (!p)
648 return -ENOMEM;
649
cc377381 650 l = strv_from_stdarg_alloca(properties);
9418f147 651
cc377381 652 return sd_bus_emit_properties_changed_strv(s->manager->bus, p, "org.freedesktop.login1.Session", l);
9418f147 653}
88e3dc90
LP
654
655int session_send_lock(Session *s, bool lock) {
ce0fc5f5 656 _cleanup_free_ char *p = NULL;
88e3dc90
LP
657
658 assert(s);
659
660 p = session_bus_path(s);
661 if (!p)
662 return -ENOMEM;
663
cc377381
LP
664 return sd_bus_emit_signal(
665 s->manager->bus,
666 p,
667 "org.freedesktop.login1.Session",
668 lock ? "Lock" : "Unlock",
669 NULL);
88e3dc90 670}
7ba64386
LP
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}
fb6becb4 689
cc377381
LP
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;
fb6becb4
LP
694
695 assert(s);
696
dd9b67aa
LP
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. */
cba38758 700
cc377381
LP
701 if (!s->create_message)
702 return 0;
fb6becb4 703
dd9b67aa
LP
704 if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job))
705 return 0;
706
cc377381
LP
707 c = s->create_message;
708 s->create_message = NULL;
fb6becb4 709
cc377381 710 if (error)
df2d202e 711 return sd_bus_reply_method_error(c, error);
fb6becb4 712
cc377381
LP
713 fifo_fd = session_create_fifo(s);
714 if (fifo_fd < 0)
715 return fifo_fd;
fb6becb4 716
38fdcbed
TA
717 /* Update the session state file before we notify the client
718 * about the result. */
719 session_save(s);
720
cc377381
LP
721 p = session_bus_path(s);
722 if (!p)
723 return -ENOMEM;
fb6becb4 724
5a330cda 725 log_debug("Sending reply about created session: "
236af516
DH
726 "id=%s object_path=%s uid=%u runtime_path=%s "
727 "session_fd=%d seat=%s vtnr=%u",
5a330cda
ZJS
728 s->id,
729 p,
236af516 730 (uint32_t) s->user->uid,
5a330cda
ZJS
731 s->user->runtime_path,
732 fifo_fd,
733 s->seat ? s->seat->id : "",
734 (uint32_t) s->vtnr);
735
cc377381 736 return sd_bus_reply_method_return(
baae0358 737 c, "soshusub",
cc377381
LP
738 s->id,
739 p,
740 s->user->runtime_path,
741 fifo_fd,
baae0358 742 (uint32_t) s->user->uid,
cc377381
LP
743 s->seat ? s->seat->id : "",
744 (uint32_t) s->vtnr,
745 false);
fb6becb4 746}