]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/login/logind-dbus.c
codespell: fix spelling errors
[thirdparty/systemd.git] / src / login / logind-dbus.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
3f49d45a 2
a185c5aa 3#include <errno.h>
4f5dd394 4#include <pwd.h>
a185c5aa 5#include <string.h>
ca78ad1d 6#include <sys/stat.h>
98a28fef 7#include <unistd.h>
a185c5aa 8
4f209af7 9#include "sd-device.h"
cc377381 10#include "sd-messages.h"
4f5dd394 11
b5efdb8a 12#include "alloc-util.h"
430f0182 13#include "audit-util.h"
31b221cf 14#include "bootspec.h"
96aad8d1 15#include "bus-common-errors.h"
4f5dd394 16#include "bus-error.h"
c8c8ee85 17#include "bus-unit-util.h"
4f5dd394 18#include "bus-util.h"
75100aeb 19#include "cgroup-util.h"
8437c059 20#include "device-util.h"
a0956174 21#include "dirent-util.h"
5bdf2243 22#include "efivars.h"
e667266a 23#include "env-util.h"
4f5dd394 24#include "escape.h"
3ffd4af2 25#include "fd-util.h"
4f5dd394 26#include "fileio-label.h"
ee228be1 27#include "fileio.h"
f97b34a6 28#include "format-util.h"
f4f15635 29#include "fs-util.h"
4f5dd394 30#include "logind.h"
36dd5ffd 31#include "missing_capability.h"
4f5dd394 32#include "mkdir.h"
31b221cf 33#include "parse-util.h"
4f5dd394 34#include "path-util.h"
0b452006 35#include "process-util.h"
428b296a 36#include "reboot-util.h"
4f5dd394
LP
37#include "selinux-util.h"
38#include "sleep-config.h"
39#include "special.h"
31b221cf 40#include "stdio-util.h"
4f5dd394 41#include "strv.h"
288a74cc 42#include "terminal-util.h"
e4de7287 43#include "tmpfile-util.h"
4f5dd394 44#include "unit-name.h"
b1d4f8e1 45#include "user-util.h"
e2fa5721 46#include "utmp-wtmp.h"
428b296a 47#include "virt.h"
3f49d45a 48
aeb07570
AJ
49static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) {
50
4afd3348 51 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
aeb07570 52 const char *name;
309a29df
LP
53 Session *session;
54 int r;
55
7b33c622
AJ
56 /* Get client login session. This is not what you are looking for these days,
57 * as apps may instead belong to a user service unit. This includes terminal
58 * emulators and hence command-line apps. */
aeb07570
AJ
59 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
60 if (r < 0)
61 return r;
62
63 r = sd_bus_creds_get_session(creds, &name);
64 if (r == -ENXIO)
65 goto err_no_session;
66 if (r < 0)
67 return r;
68
69 session = hashmap_get(m->sessions, name);
70 if (!session)
71 goto err_no_session;
72
73 *ret = session;
74 return 0;
75
76err_no_session:
77 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
78 "Caller does not belong to any known session");
79}
80
81int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
82 Session *session;
83
309a29df
LP
84 assert(m);
85 assert(message);
86 assert(ret);
87
aeb07570
AJ
88 if (isempty(name))
89 return get_sender_session(m, message, error, ret);
309a29df
LP
90
91 session = hashmap_get(m->sessions, name);
92 if (!session)
93 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
94
95 *ret = session;
96 return 0;
97}
98
aeb07570
AJ
99static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
100
101 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
102 uid_t uid;
309a29df
LP
103 User *user;
104 int r;
105
aeb07570
AJ
106 /* Note that we get the owner UID of the session, not the actual client UID here! */
107 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
108 if (r < 0)
109 return r;
110
111 r = sd_bus_creds_get_owner_uid(creds, &uid);
112 if (r == -ENXIO)
113 goto err_no_user;
114 if (r < 0)
115 return r;
116
117 user = hashmap_get(m->users, UID_TO_PTR(uid));
118 if (!user)
119 goto err_no_user;
120
121 *ret = user;
122 return 0;
123
124err_no_user:
124d7cb2
ZJS
125 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
126 "Caller does not belong to any logged in user or lingering user");
aeb07570
AJ
127}
128
129int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
130 User *user;
131
309a29df
LP
132 assert(m);
133 assert(message);
134 assert(ret);
135
aeb07570
AJ
136 if (!uid_is_valid(uid))
137 return get_sender_user(m, message, error, ret);
309a29df 138
8cb4ab00 139 user = hashmap_get(m->users, UID_TO_PTR(uid));
309a29df 140 if (!user)
124d7cb2
ZJS
141 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER,
142 "User ID "UID_FMT" is not logged in or lingering", uid);
309a29df
LP
143
144 *ret = user;
145 return 0;
146}
147
148int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
149 Seat *seat;
150 int r;
151
152 assert(m);
153 assert(message);
154 assert(ret);
155
156 if (isempty(name)) {
157 Session *session;
158
159 r = manager_get_session_from_creds(m, message, NULL, error, &session);
160 if (r < 0)
161 return r;
162
163 seat = session->seat;
309a29df
LP
164 if (!seat)
165 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
166 } else {
167 seat = hashmap_get(m->seats, name);
168 if (!seat)
169 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
170 }
171
172 *ret = seat;
173 return 0;
174}
175
ce7f1070
VJ
176static int return_test_polkit(
177 sd_bus_message *message,
178 int capability,
179 const char *action,
180 const char **details,
181 uid_t good_user,
182 sd_bus_error *e) {
183
184 const char *result;
185 bool challenge;
186 int r;
187
188 r = bus_test_polkit(message, capability, action, details, good_user, &challenge, e);
189 if (r < 0)
190 return r;
191
192 if (r > 0)
193 result = "yes";
194 else if (challenge)
195 result = "challenge";
196 else
197 result = "no";
198
199 return sd_bus_reply_method_return(message, "s", result);
200}
201
cc377381
LP
202static int property_get_idle_hint(
203 sd_bus *bus,
204 const char *path,
205 const char *interface,
206 const char *property,
207 sd_bus_message *reply,
ebcf1f97
LP
208 void *userdata,
209 sd_bus_error *error) {
a185c5aa 210
cc377381 211 Manager *m = userdata;
a185c5aa 212
cc377381
LP
213 assert(bus);
214 assert(reply);
215 assert(m);
216
217 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
a185c5aa
LP
218}
219
cc377381
LP
220static int property_get_idle_since_hint(
221 sd_bus *bus,
222 const char *path,
223 const char *interface,
224 const char *property,
225 sd_bus_message *reply,
ebcf1f97
LP
226 void *userdata,
227 sd_bus_error *error) {
cc377381
LP
228
229 Manager *m = userdata;
5cb14b37 230 dual_timestamp t = DUAL_TIMESTAMP_NULL;
a185c5aa 231
cc377381
LP
232 assert(bus);
233 assert(reply);
a185c5aa
LP
234 assert(m);
235
236 manager_get_idle_hint(m, &t);
a185c5aa 237
cc377381 238 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
a185c5aa
LP
239}
240
cc377381
LP
241static int property_get_inhibited(
242 sd_bus *bus,
243 const char *path,
244 const char *interface,
245 const char *property,
246 sd_bus_message *reply,
ebcf1f97
LP
247 void *userdata,
248 sd_bus_error *error) {
cc377381
LP
249
250 Manager *m = userdata;
f8e2fb7b 251 InhibitWhat w;
f8e2fb7b 252
cc377381
LP
253 assert(bus);
254 assert(reply);
255 assert(m);
f8e2fb7b 256
cc377381 257 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
f8e2fb7b 258
cc377381 259 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
f8e2fb7b
LP
260}
261
cc377381
LP
262static int property_get_preparing(
263 sd_bus *bus,
264 const char *path,
265 const char *interface,
266 const char *property,
267 sd_bus_message *reply,
ebcf1f97
LP
268 void *userdata,
269 sd_bus_error *error) {
cc377381
LP
270
271 Manager *m = userdata;
272 bool b;
5e4a79da 273
cc377381
LP
274 assert(bus);
275 assert(reply);
276 assert(m);
5e4a79da
LP
277
278 if (streq(property, "PreparingForShutdown"))
5d904a6a 279 b = m->action_what & INHIBIT_SHUTDOWN;
5e4a79da 280 else
5d904a6a 281 b = m->action_what & INHIBIT_SLEEP;
5e4a79da 282
cc377381 283 return sd_bus_message_append(reply, "b", b);
5e4a79da
LP
284}
285
8aaa023a
DM
286static int property_get_scheduled_shutdown(
287 sd_bus *bus,
288 const char *path,
289 const char *interface,
290 const char *property,
291 sd_bus_message *reply,
292 void *userdata,
293 sd_bus_error *error) {
294
295 Manager *m = userdata;
296 int r;
297
298 assert(bus);
299 assert(reply);
300 assert(m);
301
302 r = sd_bus_message_open_container(reply, 'r', "st");
303 if (r < 0)
304 return r;
305
306 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
307 if (r < 0)
308 return r;
309
310 return sd_bus_message_close_container(reply);
311}
312
cc377381 313static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
01adcd69 314static BUS_DEFINE_PROPERTY_GET(property_get_docked, "b", Manager, manager_is_docked_or_external_displays);
9b9c23da 315static BUS_DEFINE_PROPERTY_GET(property_get_lid_closed, "b", Manager, manager_is_lid_closed);
4e96eb68 316static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_on_external_power, "b", manager_is_on_external_power);
01adcd69
YW
317static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_compat_user_tasks_max, "t", CGROUP_LIMIT_MAX);
318static BUS_DEFINE_PROPERTY_GET_REF(property_get_hashmap_size, "t", Hashmap *, (uint64_t) hashmap_size);
28414939 319
19070062 320static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
321 _cleanup_free_ char *p = NULL;
322 Manager *m = userdata;
323 const char *name;
324 Session *session;
325 int r;
326
cc377381
LP
327 assert(message);
328 assert(m);
329
330 r = sd_bus_message_read(message, "s", &name);
331 if (r < 0)
ebcf1f97 332 return r;
cc377381 333
309a29df
LP
334 r = manager_get_session_from_creds(m, message, name, error, &session);
335 if (r < 0)
336 return r;
cc377381
LP
337
338 p = session_bus_path(session);
339 if (!p)
ebcf1f97 340 return -ENOMEM;
cc377381 341
df2d202e 342 return sd_bus_reply_method_return(message, "o", p);
cc377381
LP
343}
344
7b33c622
AJ
345/* Get login session of a process. This is not what you are looking for these days,
346 * as apps may instead belong to a user service unit. This includes terminal
347 * emulators and hence command-line apps. */
19070062 348static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 349 _cleanup_free_ char *p = NULL;
954449b8 350 Session *session = NULL;
cc377381 351 Manager *m = userdata;
4e724d9c 352 pid_t pid;
cc377381
LP
353 int r;
354
cc377381
LP
355 assert(message);
356 assert(m);
357
4e724d9c
LP
358 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
359
cc377381
LP
360 r = sd_bus_message_read(message, "u", &pid);
361 if (r < 0)
ebcf1f97 362 return r;
07b38ba5 363 if (pid < 0)
06820eaf 364 return -EINVAL;
cc377381 365
06820eaf 366 if (pid == 0) {
309a29df 367 r = manager_get_session_from_creds(m, message, NULL, error, &session);
5b12334d
LP
368 if (r < 0)
369 return r;
309a29df
LP
370 } else {
371 r = manager_get_session_by_pid(m, pid, &session);
4e724d9c 372 if (r < 0)
ebcf1f97 373 return r;
4e724d9c 374
309a29df 375 if (!session)
124d7cb2
ZJS
376 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
377 "PID "PID_FMT" does not belong to any known session", pid);
309a29df 378 }
cc377381
LP
379
380 p = session_bus_path(session);
381 if (!p)
ebcf1f97 382 return -ENOMEM;
cc377381 383
df2d202e 384 return sd_bus_reply_method_return(message, "o", p);
cc377381
LP
385}
386
19070062 387static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
388 _cleanup_free_ char *p = NULL;
389 Manager *m = userdata;
390 uint32_t uid;
391 User *user;
392 int r;
393
cc377381
LP
394 assert(message);
395 assert(m);
396
397 r = sd_bus_message_read(message, "u", &uid);
398 if (r < 0)
ebcf1f97 399 return r;
cc377381 400
309a29df
LP
401 r = manager_get_user_from_creds(m, message, uid, error, &user);
402 if (r < 0)
403 return r;
cc377381
LP
404
405 p = user_bus_path(user);
406 if (!p)
ebcf1f97 407 return -ENOMEM;
cc377381 408
df2d202e 409 return sd_bus_reply_method_return(message, "o", p);
cc377381
LP
410}
411
19070062 412static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
413 _cleanup_free_ char *p = NULL;
414 Manager *m = userdata;
954449b8 415 User *user = NULL;
4e724d9c 416 pid_t pid;
fb6becb4 417 int r;
98a28fef 418
cc377381 419 assert(message);
98a28fef 420 assert(m);
cc377381 421
4e724d9c
LP
422 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
423
cc377381
LP
424 r = sd_bus_message_read(message, "u", &pid);
425 if (r < 0)
ebcf1f97 426 return r;
07b38ba5 427 if (pid < 0)
06820eaf 428 return -EINVAL;
cc377381 429
06820eaf 430 if (pid == 0) {
309a29df 431 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
5b12334d
LP
432 if (r < 0)
433 return r;
309a29df
LP
434 } else {
435 r = manager_get_user_by_pid(m, pid, &user);
4e724d9c 436 if (r < 0)
ebcf1f97 437 return r;
309a29df 438 if (!user)
095b8833
AJ
439 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
440 "PID "PID_FMT" does not belong to any logged in user or lingering user",
441 pid);
4e724d9c
LP
442 }
443
cc377381
LP
444 p = user_bus_path(user);
445 if (!p)
ebcf1f97 446 return -ENOMEM;
cc377381 447
df2d202e 448 return sd_bus_reply_method_return(message, "o", p);
cc377381
LP
449}
450
19070062 451static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
452 _cleanup_free_ char *p = NULL;
453 Manager *m = userdata;
454 const char *name;
455 Seat *seat;
456 int r;
457
98a28fef 458 assert(message);
cc377381 459 assert(m);
98a28fef 460
cc377381
LP
461 r = sd_bus_message_read(message, "s", &name);
462 if (r < 0)
ebcf1f97 463 return r;
98a28fef 464
309a29df
LP
465 r = manager_get_seat_from_creds(m, message, name, error, &seat);
466 if (r < 0)
467 return r;
98a28fef 468
cc377381
LP
469 p = seat_bus_path(seat);
470 if (!p)
ebcf1f97 471 return -ENOMEM;
98a28fef 472
df2d202e 473 return sd_bus_reply_method_return(message, "o", p);
cc377381 474}
98a28fef 475
19070062 476static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 477 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
cc377381
LP
478 Manager *m = userdata;
479 Session *session;
480 Iterator i;
481 int r;
482
cc377381
LP
483 assert(message);
484 assert(m);
98a28fef 485
df2d202e 486 r = sd_bus_message_new_method_return(message, &reply);
cc377381 487 if (r < 0)
ebcf1f97 488 return r;
98a28fef 489
cc377381
LP
490 r = sd_bus_message_open_container(reply, 'a', "(susso)");
491 if (r < 0)
ebcf1f97 492 return r;
cc377381
LP
493
494 HASHMAP_FOREACH(session, m->sessions, i) {
495 _cleanup_free_ char *p = NULL;
496
497 p = session_bus_path(session);
498 if (!p)
ebcf1f97 499 return -ENOMEM;
cc377381
LP
500
501 r = sd_bus_message_append(reply, "(susso)",
502 session->id,
503 (uint32_t) session->user->uid,
504 session->user->name,
505 session->seat ? session->seat->id : "",
506 p);
507 if (r < 0)
ebcf1f97 508 return r;
cc377381
LP
509 }
510
511 r = sd_bus_message_close_container(reply);
512 if (r < 0)
ebcf1f97 513 return r;
cc377381 514
9030ca46 515 return sd_bus_send(NULL, reply, NULL);
cc377381
LP
516}
517
19070062 518static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 519 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
cc377381
LP
520 Manager *m = userdata;
521 User *user;
522 Iterator i;
523 int r;
524
cc377381
LP
525 assert(message);
526 assert(m);
527
df2d202e 528 r = sd_bus_message_new_method_return(message, &reply);
cc377381 529 if (r < 0)
ebcf1f97 530 return r;
cc377381
LP
531
532 r = sd_bus_message_open_container(reply, 'a', "(uso)");
533 if (r < 0)
ebcf1f97 534 return r;
cc377381
LP
535
536 HASHMAP_FOREACH(user, m->users, i) {
537 _cleanup_free_ char *p = NULL;
538
539 p = user_bus_path(user);
540 if (!p)
ebcf1f97 541 return -ENOMEM;
cc377381
LP
542
543 r = sd_bus_message_append(reply, "(uso)",
544 (uint32_t) user->uid,
545 user->name,
546 p);
547 if (r < 0)
ebcf1f97 548 return r;
cc377381
LP
549 }
550
551 r = sd_bus_message_close_container(reply);
552 if (r < 0)
ebcf1f97 553 return r;
cc377381 554
9030ca46 555 return sd_bus_send(NULL, reply, NULL);
cc377381
LP
556}
557
19070062 558static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 559 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
cc377381
LP
560 Manager *m = userdata;
561 Seat *seat;
562 Iterator i;
563 int r;
564
cc377381
LP
565 assert(message);
566 assert(m);
567
df2d202e 568 r = sd_bus_message_new_method_return(message, &reply);
cc377381 569 if (r < 0)
ebcf1f97 570 return r;
cc377381
LP
571
572 r = sd_bus_message_open_container(reply, 'a', "(so)");
573 if (r < 0)
ebcf1f97 574 return r;
cc377381
LP
575
576 HASHMAP_FOREACH(seat, m->seats, i) {
577 _cleanup_free_ char *p = NULL;
578
579 p = seat_bus_path(seat);
580 if (!p)
ebcf1f97 581 return -ENOMEM;
cc377381 582
b8358bce 583 r = sd_bus_message_append(reply, "(so)", seat->id, p);
cc377381 584 if (r < 0)
ebcf1f97 585 return r;
cc377381
LP
586 }
587
588 r = sd_bus_message_close_container(reply);
589 if (r < 0)
ebcf1f97 590 return r;
cc377381 591
9030ca46 592 return sd_bus_send(NULL, reply, NULL);
cc377381
LP
593}
594
19070062 595static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 596 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
cc377381
LP
597 Manager *m = userdata;
598 Inhibitor *inhibitor;
599 Iterator i;
600 int r;
601
19070062
LP
602 assert(message);
603 assert(m);
604
df2d202e 605 r = sd_bus_message_new_method_return(message, &reply);
cc377381 606 if (r < 0)
ebcf1f97 607 return r;
cc377381
LP
608
609 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
610 if (r < 0)
ebcf1f97 611 return r;
cc377381
LP
612
613 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
614
dbfa3fbb 615 r = sd_bus_message_append(reply, "(ssssuu)",
cc377381
LP
616 strempty(inhibit_what_to_string(inhibitor->what)),
617 strempty(inhibitor->who),
618 strempty(inhibitor->why),
619 strempty(inhibit_mode_to_string(inhibitor->mode)),
620 (uint32_t) inhibitor->uid,
621 (uint32_t) inhibitor->pid);
622 if (r < 0)
ebcf1f97 623 return r;
cc377381
LP
624 }
625
626 r = sd_bus_message_close_container(reply);
627 if (r < 0)
ebcf1f97 628 return r;
cc377381 629
9030ca46 630 return sd_bus_send(NULL, reply, NULL);
cc377381
LP
631}
632
19070062 633static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
a4cd87e9 634 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
c7543606 635 _cleanup_free_ char *id = NULL;
cc377381 636 Session *session = NULL;
bc2b6332 637 uint32_t audit_id = 0;
cc377381
LP
638 Manager *m = userdata;
639 User *user = NULL;
640 Seat *seat = NULL;
06820eaf
LP
641 pid_t leader;
642 uid_t uid;
cc377381
LP
643 int remote;
644 uint32_t vtnr = 0;
645 SessionType t;
646 SessionClass c;
647 int r;
648
cc377381
LP
649 assert(message);
650 assert(m);
651
06820eaf
LP
652 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
653 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
654
124d7cb2
ZJS
655 r = sd_bus_message_read(message, "uusssssussbss",
656 &uid, &leader, &service, &type, &class, &desktop, &cseat,
657 &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
cc377381 658 if (r < 0)
ebcf1f97 659 return r;
cc377381 660
06820eaf
LP
661 if (!uid_is_valid(uid))
662 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
bc2b6332 663 if (leader < 0 || leader == 1 || leader == getpid_cached())
ebcf1f97 664 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
98a28fef 665
e2acb67b
LP
666 if (isempty(type))
667 t = _SESSION_TYPE_INVALID;
668 else {
669 t = session_type_from_string(type);
670 if (t < 0)
124d7cb2
ZJS
671 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
672 "Invalid session type %s", type);
e2acb67b 673 }
98a28fef 674
55efac6c 675 if (isempty(class))
e2acb67b
LP
676 c = _SESSION_CLASS_INVALID;
677 else {
55efac6c 678 c = session_class_from_string(class);
e2acb67b 679 if (c < 0)
124d7cb2
ZJS
680 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
681 "Invalid session class %s", class);
e2acb67b 682 }
55efac6c 683
a4cd87e9
LP
684 if (isempty(desktop))
685 desktop = NULL;
686 else {
687 if (!string_is_safe(desktop))
124d7cb2
ZJS
688 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
689 "Invalid desktop string %s", desktop);
a4cd87e9
LP
690 }
691
954449b8
LP
692 if (isempty(cseat))
693 seat = NULL;
98a28fef 694 else {
954449b8
LP
695 seat = hashmap_get(m->seats, cseat);
696 if (!seat)
124d7cb2
ZJS
697 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT,
698 "No seat '%s' known", cseat);
98a28fef
LP
699 }
700
98a28fef 701 if (tty_is_vc(tty)) {
4d6d6518 702 int v;
98a28fef 703
954449b8 704 if (!seat)
92432fcc
DH
705 seat = m->seat0;
706 else if (seat != m->seat0)
124d7cb2
ZJS
707 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
708 "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
98a28fef 709
4d6d6518 710 v = vtnr_from_tty(tty);
4d6d6518 711 if (v <= 0)
124d7cb2
ZJS
712 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
713 "Cannot determine VT number from virtual console TTY %s", tty);
98a28fef 714
bc2b6332 715 if (vtnr == 0)
4d6d6518
LP
716 vtnr = (uint32_t) v;
717 else if (vtnr != (uint32_t) v)
124d7cb2
ZJS
718 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
719 "Specified TTY and VT number do not match");
cc377381 720
d1122ad5
LP
721 } else if (tty_is_console(tty)) {
722
954449b8 723 if (!seat)
92432fcc
DH
724 seat = m->seat0;
725 else if (seat != m->seat0)
124d7cb2
ZJS
726 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
727 "Console TTY specified but seat is not seat0");
d1122ad5
LP
728
729 if (vtnr != 0)
124d7cb2
ZJS
730 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
731 "Console TTY specified but VT number is not 0");
978cf3c7 732 }
98a28fef 733
954449b8 734 if (seat) {
bf7825ae 735 if (seat_has_vts(seat)) {
bc2b6332 736 if (vtnr <= 0 || vtnr > 63)
124d7cb2
ZJS
737 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
738 "VT number out of range");
4d6d6518 739 } else {
d1122ad5 740 if (vtnr != 0)
124d7cb2
ZJS
741 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
742 "Seat has no VTs but VT number not 0");
4d6d6518
LP
743 }
744 }
745
e2acb67b
LP
746 if (t == _SESSION_TYPE_INVALID) {
747 if (!isempty(display))
748 t = SESSION_X11;
749 else if (!isempty(tty))
750 t = SESSION_TTY;
751 else
752 t = SESSION_UNSPECIFIED;
753 }
754
755 if (c == _SESSION_CLASS_INVALID) {
a4cd87e9 756 if (t == SESSION_UNSPECIFIED)
e2acb67b 757 c = SESSION_BACKGROUND;
a4cd87e9
LP
758 else
759 c = SESSION_USER;
e2acb67b
LP
760 }
761
06820eaf 762 if (leader == 0) {
4afd3348 763 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
5b12334d
LP
764
765 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
766 if (r < 0)
767 return r;
768
5b12334d 769 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
cc377381 770 if (r < 0)
ebcf1f97 771 return r;
9444b1f2
LP
772 }
773
124d7cb2
ZJS
774 /* Check if we are already in a logind session. Or if we are in user@.service
775 * which is a special PAM session that avoids creating a logind session. */
bc2b6332 776 r = manager_get_user_by_pid(m, leader, NULL);
e8a3144e
AJ
777 if (r < 0)
778 return r;
bc2b6332 779 if (r > 0)
124d7cb2
ZJS
780 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY,
781 "Already running in a session or user slice");
b80120c4
DH
782
783 /*
784 * Old gdm and lightdm start the user-session on the same VT as
785 * the greeter session. But they destroy the greeter session
786 * after the user-session and want the user-session to take
787 * over the VT. We need to support this for
788 * backwards-compatibility, so make sure we allow new sessions
cc85d562
DH
789 * on a VT that a greeter is running on. Furthermore, to allow
790 * re-logins, we have to allow a greeter to take over a used VT for
791 * the exact same reasons.
b80120c4 792 */
cc85d562
DH
793 if (c != SESSION_GREETER &&
794 vtnr > 0 &&
b80120c4
DH
795 vtnr < m->seat0->position_count &&
796 m->seat0->positions[vtnr] &&
797 m->seat0->positions[vtnr]->class != SESSION_GREETER)
798 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
21c390cc 799
183e0738 800 if (hashmap_size(m->sessions) >= m->sessions_max)
124d7cb2
ZJS
801 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED,
802 "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.",
803 m->sessions_max);
183e0738 804
3a87a86e
LP
805 (void) audit_session_from_pid(leader, &audit_id);
806 if (audit_session_is_valid(audit_id)) {
954449b8 807 /* Keep our session IDs and the audit session IDs in sync */
21c390cc 808
de0671ee 809 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
ebcf1f97 810 return -ENOMEM;
21c390cc 811
954449b8
LP
812 /* Wut? There's already a session by this name and we
813 * didn't find it above? Weird, then let's not trust
814 * the audit data and let's better register a new
815 * ID */
816 if (hashmap_get(m->sessions, id)) {
bc2b6332 817 log_warning("Existing logind session ID %s used by new audit session, ignoring.", id);
3a87a86e 818 audit_id = AUDIT_SESSION_INVALID;
97b11eed 819 id = mfree(id);
07714753 820 }
954449b8 821 }
07714753 822
954449b8 823 if (!id) {
07714753 824 do {
97b11eed 825 id = mfree(id);
07714753 826
cc377381 827 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
ebcf1f97 828 return -ENOMEM;
07714753
LP
829
830 } while (hashmap_get(m->sessions, id));
98a28fef
LP
831 }
832
5238e957 833 /* If we are not watching utmp already, try again */
3d0ef5c7
LP
834 manager_reconnect_utmp(m);
835
954449b8 836 r = manager_add_user_by_uid(m, uid, &user);
ebcf1f97 837 if (r < 0)
954449b8
LP
838 goto fail;
839
9444b1f2 840 r = manager_add_session(m, id, &session);
ebcf1f97 841 if (r < 0)
98a28fef
LP
842 goto fail;
843
9444b1f2 844 session_set_user(session, user);
fe3ab845
YW
845 r = session_set_leader(session, leader);
846 if (r < 0)
847 goto fail;
9444b1f2 848
98a28fef 849 session->type = t;
55efac6c 850 session->class = c;
98a28fef 851 session->remote = remote;
98a28fef
LP
852 session->vtnr = vtnr;
853
98a28fef
LP
854 if (!isempty(tty)) {
855 session->tty = strdup(tty);
856 if (!session->tty) {
ebcf1f97 857 r = -ENOMEM;
98a28fef
LP
858 goto fail;
859 }
3d0ef5c7
LP
860
861 session->tty_validity = TTY_FROM_PAM;
98a28fef
LP
862 }
863
864 if (!isempty(display)) {
865 session->display = strdup(display);
866 if (!session->display) {
ebcf1f97 867 r = -ENOMEM;
98a28fef
LP
868 goto fail;
869 }
870 }
871
872 if (!isempty(remote_user)) {
873 session->remote_user = strdup(remote_user);
874 if (!session->remote_user) {
ebcf1f97 875 r = -ENOMEM;
98a28fef
LP
876 goto fail;
877 }
878 }
879
880 if (!isempty(remote_host)) {
881 session->remote_host = strdup(remote_host);
882 if (!session->remote_host) {
ebcf1f97 883 r = -ENOMEM;
98a28fef
LP
884 goto fail;
885 }
886 }
887
888 if (!isempty(service)) {
889 session->service = strdup(service);
890 if (!session->service) {
ebcf1f97 891 r = -ENOMEM;
98a28fef
LP
892 goto fail;
893 }
894 }
895
a4cd87e9
LP
896 if (!isempty(desktop)) {
897 session->desktop = strdup(desktop);
898 if (!session->desktop) {
899 r = -ENOMEM;
900 goto fail;
901 }
902 }
903
954449b8
LP
904 if (seat) {
905 r = seat_attach_session(seat, session);
ebcf1f97 906 if (r < 0)
98a28fef
LP
907 goto fail;
908 }
909
22f93314
JS
910 r = sd_bus_message_enter_container(message, 'a', "(sv)");
911 if (r < 0)
d88ffeee 912 goto fail;
22f93314 913
25a1ab4e 914 r = session_start(session, message, error);
22f93314
JS
915 if (r < 0)
916 goto fail;
917
918 r = sd_bus_message_exit_container(message);
ebcf1f97 919 if (r < 0)
98a28fef
LP
920 goto fail;
921
cc377381 922 session->create_message = sd_bus_message_ref(message);
98a28fef 923
bc2b6332 924 /* Now, let's wait until the slice unit and stuff got created. We send the reply back from
f7340ab2 925 * session_send_create_reply(). */
cba38758 926
cc377381 927 return 1;
98a28fef
LP
928
929fail:
98a28fef
LP
930 if (session)
931 session_add_to_gc_queue(session);
932
933 if (user)
934 user_add_to_gc_queue(user);
935
98a28fef
LP
936 return r;
937}
938
19070062 939static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
940 Manager *m = userdata;
941 Session *session;
942 const char *name;
943 int r;
314b4b0a 944
cc377381
LP
945 assert(message);
946 assert(m);
947
948 r = sd_bus_message_read(message, "s", &name);
949 if (r < 0)
ebcf1f97 950 return r;
cc377381 951
309a29df
LP
952 r = manager_get_session_from_creds(m, message, name, error, &session);
953 if (r < 0)
954 return r;
cc377381 955
ad8780c9
ZJS
956 r = session_release(session);
957 if (r < 0)
958 return r;
cc377381 959
df2d202e 960 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
961}
962
19070062 963static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
964 Manager *m = userdata;
965 Session *session;
966 const char *name;
967 int r;
f8e2fb7b 968
cc377381 969 assert(message);
f8e2fb7b 970 assert(m);
cc377381
LP
971
972 r = sd_bus_message_read(message, "s", &name);
973 if (r < 0)
ebcf1f97 974 return r;
cc377381 975
309a29df
LP
976 r = manager_get_session_from_creds(m, message, name, error, &session);
977 if (r < 0)
978 return r;
cc377381 979
19070062 980 return bus_session_method_activate(message, session, error);
cc377381
LP
981}
982
19070062 983static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
984 const char *session_name, *seat_name;
985 Manager *m = userdata;
986 Session *session;
987 Seat *seat;
988 int r;
989
f8e2fb7b 990 assert(message);
cc377381 991 assert(m);
f8e2fb7b 992
cc377381
LP
993 /* Same as ActivateSession() but refuses to work if
994 * the seat doesn't match */
f8e2fb7b 995
cc377381
LP
996 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
997 if (r < 0)
ebcf1f97 998 return r;
eecd1362 999
309a29df
LP
1000 r = manager_get_session_from_creds(m, message, session_name, error, &session);
1001 if (r < 0)
1002 return r;
beaafb2e 1003
309a29df
LP
1004 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
1005 if (r < 0)
1006 return r;
314b4b0a 1007
cc377381 1008 if (session->seat != seat)
124d7cb2
ZJS
1009 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT,
1010 "Session %s not on seat %s", session_name, seat_name);
cc377381
LP
1011
1012 r = session_activate(session);
f8e2fb7b 1013 if (r < 0)
ebcf1f97 1014 return r;
f8e2fb7b 1015
df2d202e 1016 return sd_bus_reply_method_return(message, NULL);
cc377381 1017}
f8e2fb7b 1018
19070062 1019static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
1020 Manager *m = userdata;
1021 Session *session;
1022 const char *name;
1023 int r;
f8e2fb7b 1024
cc377381
LP
1025 assert(message);
1026 assert(m);
f8e2fb7b 1027
cc377381
LP
1028 r = sd_bus_message_read(message, "s", &name);
1029 if (r < 0)
ebcf1f97 1030 return r;
f8e2fb7b 1031
309a29df
LP
1032 r = manager_get_session_from_creds(m, message, name, error, &session);
1033 if (r < 0)
1034 return r;
f8e2fb7b 1035
19070062 1036 return bus_session_method_lock(message, session, error);
cc377381 1037}
f8e2fb7b 1038
19070062 1039static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
1040 Manager *m = userdata;
1041 int r;
f8e2fb7b 1042
cc377381
LP
1043 assert(message);
1044 assert(m);
f8e2fb7b 1045
c529695e
LP
1046 r = bus_verify_polkit_async(
1047 message,
1048 CAP_SYS_ADMIN,
1049 "org.freedesktop.login1.lock-sessions",
403ed0e5 1050 NULL,
c529695e
LP
1051 false,
1052 UID_INVALID,
1053 &m->polkit_registry,
1054 error);
1055 if (r < 0)
1056 return r;
1057 if (r == 0)
1058 return 1; /* Will call us back */
1059
cc377381
LP
1060 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
1061 if (r < 0)
ebcf1f97 1062 return r;
f8e2fb7b 1063
df2d202e 1064 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
1065}
1066
19070062 1067static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c529695e 1068 const char *name;
cc377381
LP
1069 Manager *m = userdata;
1070 Session *session;
cc377381
LP
1071 int r;
1072
cc377381
LP
1073 assert(message);
1074 assert(m);
1075
c529695e 1076 r = sd_bus_message_read(message, "s", &name);
cc377381 1077 if (r < 0)
ebcf1f97 1078 return r;
cc377381 1079
309a29df
LP
1080 r = manager_get_session_from_creds(m, message, name, error, &session);
1081 if (r < 0)
1082 return r;
f8e2fb7b 1083
19070062 1084 return bus_session_method_kill(message, session, error);
cc377381 1085}
f8e2fb7b 1086
19070062 1087static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
1088 Manager *m = userdata;
1089 uint32_t uid;
cc377381
LP
1090 User *user;
1091 int r;
f8e2fb7b 1092
cc377381
LP
1093 assert(message);
1094 assert(m);
1095
c529695e 1096 r = sd_bus_message_read(message, "u", &uid);
cc377381 1097 if (r < 0)
ebcf1f97 1098 return r;
cc377381 1099
309a29df
LP
1100 r = manager_get_user_from_creds(m, message, uid, error, &user);
1101 if (r < 0)
1102 return r;
cc377381 1103
19070062 1104 return bus_user_method_kill(message, user, error);
cc377381
LP
1105}
1106
19070062 1107static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
1108 Manager *m = userdata;
1109 const char *name;
1110 Session *session;
1111 int r;
1112
cc377381
LP
1113 assert(message);
1114 assert(m);
1115
1116 r = sd_bus_message_read(message, "s", &name);
1117 if (r < 0)
ebcf1f97 1118 return r;
cc377381 1119
309a29df
LP
1120 r = manager_get_session_from_creds(m, message, name, error, &session);
1121 if (r < 0)
1122 return r;
cc377381 1123
19070062 1124 return bus_session_method_terminate(message, session, error);
cc377381
LP
1125}
1126
19070062 1127static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
1128 Manager *m = userdata;
1129 uint32_t uid;
1130 User *user;
1131 int r;
1132
cc377381
LP
1133 assert(message);
1134 assert(m);
1135
1136 r = sd_bus_message_read(message, "u", &uid);
1137 if (r < 0)
ebcf1f97 1138 return r;
cc377381 1139
309a29df
LP
1140 r = manager_get_user_from_creds(m, message, uid, error, &user);
1141 if (r < 0)
1142 return r;
cc377381 1143
19070062 1144 return bus_user_method_terminate(message, user, error);
cc377381
LP
1145}
1146
19070062 1147static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
1148 Manager *m = userdata;
1149 const char *name;
1150 Seat *seat;
1151 int r;
1152
cc377381
LP
1153 assert(message);
1154 assert(m);
1155
1156 r = sd_bus_message_read(message, "s", &name);
1157 if (r < 0)
ebcf1f97 1158 return r;
cc377381 1159
309a29df
LP
1160 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1161 if (r < 0)
1162 return r;
cc377381 1163
19070062 1164 return bus_seat_method_terminate(message, seat, error);
cc377381
LP
1165}
1166
19070062 1167static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
34160d91 1168 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
cc377381
LP
1169 _cleanup_free_ char *cc = NULL;
1170 Manager *m = userdata;
152199f2 1171 int r, b, interactive;
cc377381
LP
1172 struct passwd *pw;
1173 const char *path;
34160d91 1174 uint32_t uid, auth_uid;
cc377381 1175
cc377381
LP
1176 assert(message);
1177 assert(m);
1178
1179 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1180 if (r < 0)
ebcf1f97 1181 return r;
cc377381 1182
34160d91
AJ
1183 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID |
1184 SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1185 if (r < 0)
1186 return r;
309a29df 1187
34160d91
AJ
1188 if (!uid_is_valid(uid)) {
1189 /* Note that we get the owner UID of the session or user unit,
1190 * not the actual client UID here! */
309a29df
LP
1191 r = sd_bus_creds_get_owner_uid(creds, &uid);
1192 if (r < 0)
1193 return r;
34160d91 1194 }
06820eaf 1195
34160d91
AJ
1196 /* owner_uid is racy, so for authorization we must use euid */
1197 r = sd_bus_creds_get_euid(creds, &auth_uid);
1198 if (r < 0)
1199 return r;
309a29df 1200
cc377381
LP
1201 errno = 0;
1202 pw = getpwuid(uid);
1203 if (!pw)
f5e5c28f 1204 return errno > 0 ? -errno : -ENOENT;
cc377381 1205
f3885791
LP
1206 r = bus_verify_polkit_async(
1207 message,
1208 CAP_SYS_ADMIN,
34160d91
AJ
1209 uid == auth_uid ? "org.freedesktop.login1.set-self-linger" :
1210 "org.freedesktop.login1.set-user-linger",
403ed0e5 1211 NULL,
f3885791 1212 interactive,
c529695e 1213 UID_INVALID,
f3885791
LP
1214 &m->polkit_registry,
1215 error);
cc377381 1216 if (r < 0)
ebcf1f97 1217 return r;
cc377381
LP
1218 if (r == 0)
1219 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1220
6e5dcce4 1221 (void) mkdir_p_label("/var/lib/systemd", 0755);
37c1d5e9 1222 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0, MKDIR_WARN_MODE);
cc377381 1223 if (r < 0)
ebcf1f97 1224 return r;
cc377381
LP
1225
1226 cc = cescape(pw->pw_name);
1227 if (!cc)
ebcf1f97 1228 return -ENOMEM;
cc377381 1229
63c372cb 1230 path = strjoina("/var/lib/systemd/linger/", cc);
cc377381
LP
1231 if (b) {
1232 User *u;
1233
1234 r = touch(path);
1235 if (r < 0)
ebcf1f97 1236 return r;
cc377381
LP
1237
1238 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1239 user_start(u);
1240
1241 } else {
1242 User *u;
1243
1244 r = unlink(path);
1245 if (r < 0 && errno != ENOENT)
ebcf1f97 1246 return -errno;
cc377381 1247
8cb4ab00 1248 u = hashmap_get(m->users, UID_TO_PTR(uid));
cc377381
LP
1249 if (u)
1250 user_add_to_gc_queue(u);
1251 }
1252
df2d202e 1253 return sd_bus_reply_method_return(message, NULL);
f8e2fb7b
LP
1254}
1255
4f209af7
YW
1256static int trigger_device(Manager *m, sd_device *d) {
1257 _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
b668e064
LP
1258 int r;
1259
1260 assert(m);
1261
4f209af7
YW
1262 r = sd_device_enumerator_new(&e);
1263 if (r < 0)
1264 return r;
1265
1266 r = sd_device_enumerator_allow_uninitialized(e);
1267 if (r < 0)
1268 return r;
b668e064 1269
2eb916cd 1270 if (d) {
4f209af7 1271 r = sd_device_enumerator_add_match_parent(e, d);
06acf2d4
LP
1272 if (r < 0)
1273 return r;
2eb916cd
LP
1274 }
1275
8437c059 1276 FOREACH_DEVICE(e, d) {
cc377381 1277 _cleanup_free_ char *t = NULL;
b668e064
LP
1278 const char *p;
1279
4f209af7
YW
1280 r = sd_device_get_syspath(d, &p);
1281 if (r < 0)
1282 return r;
b668e064 1283
b668e064 1284 t = strappend(p, "/uevent");
06acf2d4
LP
1285 if (!t)
1286 return -ENOMEM;
b668e064 1287
57512c89 1288 (void) write_string_file(t, "change", WRITE_STRING_FILE_DISABLE_BUFFER);
b668e064
LP
1289 }
1290
06acf2d4 1291 return 0;
b668e064
LP
1292}
1293
47a26690 1294static int attach_device(Manager *m, const char *seat, const char *sysfs) {
4f209af7 1295 _cleanup_(sd_device_unrefp) sd_device *d = NULL;
7fd1b19b 1296 _cleanup_free_ char *rule = NULL, *file = NULL;
c28fa3d3 1297 const char *id_for_seat;
47a26690
LP
1298 int r;
1299
1300 assert(m);
1301 assert(seat);
1302 assert(sysfs);
1303
4f209af7
YW
1304 r = sd_device_new_from_syspath(&d, sysfs);
1305 if (r < 0)
1306 return r;
47a26690 1307
4f209af7 1308 if (sd_device_has_tag(d, "seat") <= 0)
06acf2d4 1309 return -ENODEV;
47a26690 1310
4f209af7 1311 if (sd_device_get_property_value(d, "ID_FOR_SEAT", &id_for_seat) < 0)
06acf2d4 1312 return -ENODEV;
47a26690 1313
06acf2d4
LP
1314 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1315 return -ENOMEM;
47a26690 1316
06acf2d4
LP
1317 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1318 return -ENOMEM;
47a26690 1319
4f209af7 1320 (void) mkdir_p_label("/etc/udev/rules.d", 0755);
574d5f2d 1321 r = write_string_file_atomic_label(file, rule);
a0a0c7f1 1322 if (r < 0)
06acf2d4 1323 return r;
47a26690 1324
06acf2d4 1325 return trigger_device(m, d);
47a26690
LP
1326}
1327
b668e064 1328static int flush_devices(Manager *m) {
7fd1b19b 1329 _cleanup_closedir_ DIR *d;
b668e064
LP
1330
1331 assert(m);
1332
1333 d = opendir("/etc/udev/rules.d");
1334 if (!d) {
1335 if (errno != ENOENT)
56f64d95 1336 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
b668e064
LP
1337 } else {
1338 struct dirent *de;
1339
8fb3f009 1340 FOREACH_DIRENT_ALL(de, d, break) {
b668e064
LP
1341 if (!dirent_is_file(de))
1342 continue;
1343
1344 if (!startswith(de->d_name, "72-seat-"))
1345 continue;
1346
1347 if (!endswith(de->d_name, ".rules"))
1348 continue;
1349
1350 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
56f64d95 1351 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
b668e064 1352 }
b668e064
LP
1353 }
1354
1355 return trigger_device(m, NULL);
1356}
1357
19070062 1358static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
1359 const char *sysfs, *seat;
1360 Manager *m = userdata;
1361 int interactive, r;
1362
cc377381
LP
1363 assert(message);
1364 assert(m);
1365
1366 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1367 if (r < 0)
ebcf1f97 1368 return r;
cc377381
LP
1369
1370 if (!path_startswith(sysfs, "/sys"))
ebcf1f97 1371 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
cc377381
LP
1372
1373 if (!seat_name_is_valid(seat))
ebcf1f97 1374 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
cc377381 1375
f3885791
LP
1376 r = bus_verify_polkit_async(
1377 message,
1378 CAP_SYS_ADMIN,
1379 "org.freedesktop.login1.attach-device",
403ed0e5 1380 NULL,
f3885791 1381 interactive,
c529695e 1382 UID_INVALID,
f3885791
LP
1383 &m->polkit_registry,
1384 error);
cc377381 1385 if (r < 0)
ebcf1f97 1386 return r;
cc377381
LP
1387 if (r == 0)
1388 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1389
1390 r = attach_device(m, seat, sysfs);
1391 if (r < 0)
ebcf1f97 1392 return r;
cc377381 1393
df2d202e 1394 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
1395}
1396
19070062 1397static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
1398 Manager *m = userdata;
1399 int interactive, r;
1400
cc377381
LP
1401 assert(message);
1402 assert(m);
1403
1404 r = sd_bus_message_read(message, "b", &interactive);
1405 if (r < 0)
ebcf1f97 1406 return r;
cc377381 1407
f3885791
LP
1408 r = bus_verify_polkit_async(
1409 message,
1410 CAP_SYS_ADMIN,
1411 "org.freedesktop.login1.flush-devices",
403ed0e5 1412 NULL,
f3885791 1413 interactive,
c529695e 1414 UID_INVALID,
f3885791
LP
1415 &m->polkit_registry,
1416 error);
cc377381 1417 if (r < 0)
ebcf1f97 1418 return r;
cc377381
LP
1419 if (r == 0)
1420 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1421
1422 r = flush_devices(m);
1423 if (r < 0)
ebcf1f97 1424 return r;
cc377381 1425
df2d202e 1426 return sd_bus_reply_method_return(message, NULL);
cc377381
LP
1427}
1428
89f13440 1429static int have_multiple_sessions(
89f13440 1430 Manager *m,
409133be 1431 uid_t uid) {
89f13440 1432
2154761f
MS
1433 Session *session;
1434 Iterator i;
89f13440
LP
1435
1436 assert(m);
1437
1ca04b87
LP
1438 /* Check for other users' sessions. Greeter sessions do not
1439 * count, and non-login sessions do not count either. */
2154761f 1440 HASHMAP_FOREACH(session, m->sessions, i)
1ca04b87 1441 if (session->class == SESSION_USER &&
1ca04b87 1442 session->user->uid != uid)
2154761f 1443 return true;
89f13440
LP
1444
1445 return false;
1446}
1447
314b4b0a
LP
1448static int bus_manager_log_shutdown(
1449 Manager *m,
314b4b0a
LP
1450 const char *unit_name) {
1451
5744f59a 1452 const char *p, *q;
314b4b0a
LP
1453
1454 assert(m);
1455 assert(unit_name);
1456
314b4b0a 1457 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
f868cb58 1458 p = "MESSAGE=System is powering down";
314b4b0a 1459 q = "SHUTDOWN=power-off";
314b4b0a 1460 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
f868cb58 1461 p = "MESSAGE=System is rebooting";
314b4b0a 1462 q = "SHUTDOWN=reboot";
36b69c31
LP
1463 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1464 p = "MESSAGE=System is halting";
1465 q = "SHUTDOWN=halt";
314b4b0a 1466 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
f868cb58 1467 p = "MESSAGE=System is rebooting with kexec";
314b4b0a
LP
1468 q = "SHUTDOWN=kexec";
1469 } else {
f868cb58 1470 p = "MESSAGE=System is shutting down";
314b4b0a
LP
1471 q = NULL;
1472 }
1473
f868cb58
ZJS
1474 if (isempty(m->wall_message))
1475 p = strjoina(p, ".");
1476 else
1477 p = strjoina(p, " (", m->wall_message, ").");
9ef15026 1478
e2cc6eca 1479 return log_struct(LOG_NOTICE,
2b044526 1480 "MESSAGE_ID=" SD_MESSAGE_SHUTDOWN_STR,
314b4b0a 1481 p,
a1230ff9 1482 q);
314b4b0a
LP
1483}
1484
b5d3e168
KS
1485static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1486 Manager *m = userdata;
1487
1488 assert(e);
1489 assert(m);
1490
1491 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1492 return 0;
1493}
1494
1495int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1496 int r;
1497
1498 assert(m);
1499
1500 if (until <= now(CLOCK_MONOTONIC))
1501 return 0;
1502
1503 /* We want to ignore the lid switch for a while after each
1504 * suspend, and after boot-up. Hence let's install a timer for
1505 * this. As long as the event source exists we ignore the lid
1506 * switch. */
1507
1508 if (m->lid_switch_ignore_event_source) {
1509 usec_t u;
1510
1511 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1512 if (r < 0)
1513 return r;
1514
1515 if (until <= u)
1516 return 0;
1517
1518 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1519 } else
6a0f1f6d
LP
1520 r = sd_event_add_time(
1521 m->event,
1522 &m->lid_switch_ignore_event_source,
1523 CLOCK_MONOTONIC,
1524 until, 0,
1525 lid_switch_ignore_handler, m);
b5d3e168
KS
1526
1527 return r;
1528}
1529
6d7f7fd4 1530static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
6d7f7fd4
AJ
1531 int active = _active;
1532
1533 assert(m);
06c2f0a8 1534 assert(IN_SET(w, INHIBIT_SHUTDOWN, INHIBIT_SLEEP));
6d7f7fd4
AJ
1535
1536 return sd_bus_emit_signal(m->bus,
1537 "/org/freedesktop/login1",
1538 "org.freedesktop.login1.Manager",
06c2f0a8 1539 w == INHIBIT_SHUTDOWN ? "PrepareForShutdown" : "PrepareForSleep",
6d7f7fd4
AJ
1540 "b",
1541 active);
1542}
1543
314b4b0a
LP
1544static int execute_shutdown_or_sleep(
1545 Manager *m,
1546 InhibitWhat w,
1547 const char *unit_name,
cc377381 1548 sd_bus_error *error) {
314b4b0a 1549
4afd3348 1550 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
cc377381 1551 const char *p;
cc377381 1552 int r;
eecd1362 1553
af9792ac 1554 assert(m);
b61fa4e0 1555 assert(w > 0);
314b4b0a 1556 assert(w < _INHIBIT_WHAT_MAX);
d889a206 1557 assert(unit_name);
eecd1362 1558
df75a1a8
AJ
1559 if (w == INHIBIT_SHUTDOWN)
1560 bus_manager_log_shutdown(m, unit_name);
314b4b0a 1561
df75a1a8
AJ
1562 r = sd_bus_call_method(
1563 m->bus,
1564 "org.freedesktop.systemd1",
1565 "/org/freedesktop/systemd1",
1566 "org.freedesktop.systemd1.Manager",
1567 "StartUnit",
1568 error,
1569 &reply,
1570 "ss", unit_name, "replace-irreversibly");
1571 if (r < 0)
6d7f7fd4 1572 goto error;
af9792ac 1573
df75a1a8
AJ
1574 r = sd_bus_message_read(reply, "o", &p);
1575 if (r < 0)
6d7f7fd4 1576 goto error;
af9792ac 1577
6b9f8b71
YW
1578 r = free_and_strdup(&m->action_job, p);
1579 if (r < 0)
6d7f7fd4 1580 goto error;
af9792ac 1581
314b4b0a 1582 m->action_unit = unit_name;
314b4b0a 1583 m->action_what = w;
af9792ac 1584
f9cd6be1 1585 /* Make sure the lid switch is ignored for a while */
9d10cbee 1586 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
f9cd6be1 1587
af9792ac 1588 return 0;
6d7f7fd4
AJ
1589
1590error:
1591 /* Tell people that they now may take a lock again */
401e33ed 1592 (void) send_prepare_for(m, w, false);
6d7f7fd4
AJ
1593
1594 return r;
eecd1362
LP
1595}
1596
418b22b8 1597int manager_dispatch_delayed(Manager *manager, bool timeout) {
c0f32805 1598
4afd3348 1599 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
c0f32805 1600 Inhibitor *offending = NULL;
c0f32805
DM
1601 int r;
1602
1603 assert(manager);
c0f32805
DM
1604
1605 if (manager->action_what == 0 || manager->action_job)
1606 return 0;
1607
1608 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1609 _cleanup_free_ char *comm = NULL, *u = NULL;
1610
418b22b8
DM
1611 if (!timeout)
1612 return 0;
1613
c0f32805
DM
1614 (void) get_process_comm(offending->pid, &comm);
1615 u = uid_to_name(offending->uid);
1616
1617 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1618 offending->uid, strna(u),
1619 offending->pid, strna(comm));
1620 }
1621
1622 /* Actually do the operation */
1623 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1624 if (r < 0) {
6d7f7fd4
AJ
1625 log_warning("Error during inhibitor-delayed operation (already returned success to client): %s",
1626 bus_error_message(&error, r));
c0f32805
DM
1627
1628 manager->action_unit = NULL;
1629 manager->action_what = 0;
418b22b8 1630 return r;
c0f32805
DM
1631 }
1632
418b22b8
DM
1633 return 1;
1634}
1635
1636static int manager_inhibit_timeout_handler(
1637 sd_event_source *s,
1638 uint64_t usec,
1639 void *userdata) {
1640
1641 Manager *manager = userdata;
1642 int r;
1643
1644 assert(manager);
1645 assert(manager->inhibit_timeout_source == s);
1646
1647 r = manager_dispatch_delayed(manager, true);
1648 return (r < 0) ? r : 0;
c0f32805
DM
1649}
1650
314b4b0a
LP
1651static int delay_shutdown_or_sleep(
1652 Manager *m,
1653 InhibitWhat w,
1654 const char *unit_name) {
eecd1362 1655
c0f32805
DM
1656 int r;
1657 usec_t timeout_val;
1658
eecd1362 1659 assert(m);
d889a206
LP
1660 assert(w >= 0);
1661 assert(w < _INHIBIT_WHAT_MAX);
314b4b0a 1662 assert(unit_name);
eecd1362 1663
c0f32805
DM
1664 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1665
1666 if (m->inhibit_timeout_source) {
1667 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1668 if (r < 0)
c2a23db0 1669 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
c0f32805
DM
1670
1671 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1672 if (r < 0)
c2a23db0 1673 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
c0f32805
DM
1674 } else {
1675 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1676 timeout_val, 0, manager_inhibit_timeout_handler, m);
1677 if (r < 0)
1678 return r;
1679 }
1680
314b4b0a
LP
1681 m->action_unit = unit_name;
1682 m->action_what = w;
d889a206
LP
1683
1684 return 0;
1685}
1686
069cfc85
LP
1687int bus_manager_shutdown_or_sleep_now_or_later(
1688 Manager *m,
1689 const char *unit_name,
1690 InhibitWhat w,
cc377381 1691 sd_bus_error *error) {
069cfc85 1692
c8c8ee85 1693 _cleanup_free_ char *load_state = NULL;
069cfc85
LP
1694 bool delayed;
1695 int r;
1696
1697 assert(m);
1698 assert(unit_name);
b61fa4e0 1699 assert(w > 0);
543680f4 1700 assert(w < _INHIBIT_WHAT_MAX);
af9792ac 1701 assert(!m->action_job);
069cfc85 1702
c8c8ee85
ZJS
1703 r = unit_load_state(m->bus, unit_name, &load_state);
1704 if (r < 0)
1705 return r;
1706
baaa35ad
ZJS
1707 if (!streq(load_state, "loaded"))
1708 return log_notice_errno(SYNTHETIC_ERRNO(EACCES),
1709 "Unit %s is %s, refusing operation.",
1710 unit_name, load_state);
c8c8ee85 1711
314b4b0a 1712 /* Tell everybody to prepare for shutdown/sleep */
401e33ed 1713 (void) send_prepare_for(m, w, true);
314b4b0a 1714
069cfc85
LP
1715 delayed =
1716 m->inhibit_delay_max > 0 &&
85a428c6 1717 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
069cfc85
LP
1718
1719 if (delayed)
1720 /* Shutdown is delayed, keep in mind what we
1721 * want to do, and start a timeout */
1722 r = delay_shutdown_or_sleep(m, w, unit_name);
314b4b0a 1723 else
069cfc85
LP
1724 /* Shutdown is not delayed, execute it
1725 * immediately */
314b4b0a 1726 r = execute_shutdown_or_sleep(m, w, unit_name, error);
069cfc85
LP
1727
1728 return r;
1729}
1730
b7aa9589 1731static int verify_shutdown_creds(
d889a206 1732 Manager *m,
cc377381 1733 sd_bus_message *message,
d889a206 1734 InhibitWhat w,
b7aa9589 1735 bool interactive,
d889a206
LP
1736 const char *action,
1737 const char *action_multiple_sessions,
1738 const char *action_ignore_inhibit,
ebcf1f97 1739 sd_bus_error *error) {
d889a206 1740
4afd3348 1741 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
069cfc85 1742 bool multiple_sessions, blocked;
cc377381 1743 uid_t uid;
b7aa9589 1744 int r;
d889a206
LP
1745
1746 assert(m);
d889a206 1747 assert(message);
d889a206
LP
1748 assert(w >= 0);
1749 assert(w <= _INHIBIT_WHAT_MAX);
6524990f 1750
05bae4a6 1751 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
5b12334d
LP
1752 if (r < 0)
1753 return r;
1754
05bae4a6 1755 r = sd_bus_creds_get_euid(creds, &uid);
cc377381 1756 if (r < 0)
ebcf1f97 1757 return r;
409133be 1758
cc377381 1759 r = have_multiple_sessions(m, uid);
d889a206 1760 if (r < 0)
ebcf1f97 1761 return r;
d889a206
LP
1762
1763 multiple_sessions = r > 0;
85a428c6 1764 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
d889a206 1765
b7aa9589 1766 if (multiple_sessions && action_multiple_sessions) {
403ed0e5 1767 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
d889a206 1768 if (r < 0)
ebcf1f97 1769 return r;
055d4066
ZJS
1770 if (r == 0)
1771 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
d889a206
LP
1772 }
1773
b7aa9589 1774 if (blocked && action_ignore_inhibit) {
403ed0e5 1775 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
d889a206 1776 if (r < 0)
ebcf1f97 1777 return r;
055d4066
ZJS
1778 if (r == 0)
1779 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
d889a206
LP
1780 }
1781
b7aa9589 1782 if (!multiple_sessions && !blocked && action) {
403ed0e5 1783 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
d889a206 1784 if (r < 0)
ebcf1f97 1785 return r;
055d4066
ZJS
1786 if (r == 0)
1787 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
d889a206
LP
1788 }
1789
b7aa9589
DM
1790 return 0;
1791}
1792
1793static int method_do_shutdown_or_sleep(
1794 Manager *m,
1795 sd_bus_message *message,
1796 const char *unit_name,
1797 InhibitWhat w,
1798 const char *action,
1799 const char *action_multiple_sessions,
1800 const char *action_ignore_inhibit,
1801 const char *sleep_verb,
1802 sd_bus_error *error) {
1803
1804 int interactive, r;
1805
1806 assert(m);
1807 assert(message);
1808 assert(unit_name);
1809 assert(w >= 0);
1810 assert(w <= _INHIBIT_WHAT_MAX);
1811
1812 r = sd_bus_message_read(message, "b", &interactive);
1813 if (r < 0)
1814 return r;
1815
1816 /* Don't allow multiple jobs being executed at the same time */
f8bfa318 1817 if (m->action_what > 0)
124d7cb2
ZJS
1818 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
1819 "There's already a shutdown or sleep operation in progress");
b7aa9589
DM
1820
1821 if (sleep_verb) {
1822 r = can_sleep(sleep_verb);
b71c9758 1823 if (r == -ENOSPC)
8340b762
ZJS
1824 return sd_bus_error_set(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
1825 "Not enough swap space for hibernation");
b71c9758 1826 if (r == 0)
8340b762
ZJS
1827 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED,
1828 "Sleep verb \"%s\" not supported", sleep_verb);
b7aa9589
DM
1829 if (r < 0)
1830 return r;
b7aa9589
DM
1831 }
1832
1833 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1834 action_ignore_inhibit, error);
1835 if (r != 0)
1836 return r;
1837
ebcf1f97 1838 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
d889a206 1839 if (r < 0)
ebcf1f97 1840 return r;
d889a206 1841
df2d202e 1842 return sd_bus_reply_method_return(message, NULL);
eecd1362
LP
1843}
1844
19070062 1845static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
3f49d45a
LP
1846 Manager *m = userdata;
1847
cc377381
LP
1848 return method_do_shutdown_or_sleep(
1849 m, message,
1850 SPECIAL_POWEROFF_TARGET,
1851 INHIBIT_SHUTDOWN,
1852 "org.freedesktop.login1.power-off",
1853 "org.freedesktop.login1.power-off-multiple-sessions",
1854 "org.freedesktop.login1.power-off-ignore-inhibit",
1855 NULL,
ebcf1f97 1856 error);
cc377381 1857}
88e3dc90 1858
19070062 1859static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 1860 Manager *m = userdata;
88e3dc90 1861
cc377381
LP
1862 return method_do_shutdown_or_sleep(
1863 m, message,
1864 SPECIAL_REBOOT_TARGET,
1865 INHIBIT_SHUTDOWN,
1866 "org.freedesktop.login1.reboot",
1867 "org.freedesktop.login1.reboot-multiple-sessions",
1868 "org.freedesktop.login1.reboot-ignore-inhibit",
1869 NULL,
ebcf1f97 1870 error);
cc377381 1871}
88e3dc90 1872
36b69c31
LP
1873static int method_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1874 Manager *m = userdata;
1875
1876 return method_do_shutdown_or_sleep(
1877 m, message,
1878 SPECIAL_HALT_TARGET,
1879 INHIBIT_SHUTDOWN,
1880 "org.freedesktop.login1.halt",
1881 "org.freedesktop.login1.halt-multiple-sessions",
1882 "org.freedesktop.login1.halt-ignore-inhibit",
1883 NULL,
1884 error);
1885}
1886
19070062 1887static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 1888 Manager *m = userdata;
88e3dc90 1889
cc377381
LP
1890 return method_do_shutdown_or_sleep(
1891 m, message,
1892 SPECIAL_SUSPEND_TARGET,
1893 INHIBIT_SLEEP,
1894 "org.freedesktop.login1.suspend",
1895 "org.freedesktop.login1.suspend-multiple-sessions",
1896 "org.freedesktop.login1.suspend-ignore-inhibit",
1897 "suspend",
ebcf1f97 1898 error);
cc377381 1899}
88e3dc90 1900
15e99a43
LP
1901static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1902 Manager *m = userdata;
1903
1904 return method_do_shutdown_or_sleep(
1905 m, message,
1906 SPECIAL_HIBERNATE_TARGET,
1907 INHIBIT_SLEEP,
1908 "org.freedesktop.login1.hibernate",
1909 "org.freedesktop.login1.hibernate-multiple-sessions",
1910 "org.freedesktop.login1.hibernate-ignore-inhibit",
1911 "hibernate",
1912 error);
1913}
1914
1915static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1916 Manager *m = userdata;
1917
1918 return method_do_shutdown_or_sleep(
1919 m, message,
1920 SPECIAL_HYBRID_SLEEP_TARGET,
1921 INHIBIT_SLEEP,
1922 "org.freedesktop.login1.hibernate",
1923 "org.freedesktop.login1.hibernate-multiple-sessions",
1924 "org.freedesktop.login1.hibernate-ignore-inhibit",
1925 "hybrid-sleep",
1926 error);
1927}
1928
e68c79db 1929static int method_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c58493c0
ML
1930 Manager *m = userdata;
1931
1932 return method_do_shutdown_or_sleep(
1933 m, message,
e68c79db 1934 SPECIAL_SUSPEND_THEN_HIBERNATE_TARGET,
c58493c0
ML
1935 INHIBIT_SLEEP,
1936 "org.freedesktop.login1.hibernate",
1937 "org.freedesktop.login1.hibernate-multiple-sessions",
1938 "org.freedesktop.login1.hibernate-ignore-inhibit",
1939 "hybrid-sleep",
1940 error);
1941}
1942
867c37f6
DM
1943static int nologin_timeout_handler(
1944 sd_event_source *s,
1945 uint64_t usec,
1946 void *userdata) {
1947
1948 Manager *m = userdata;
867c37f6
DM
1949
1950 log_info("Creating /run/nologin, blocking further logins...");
1951
6e11e7e6
LP
1952 m->unlink_nologin =
1953 create_shutdown_run_nologin_or_warn() >= 0;
867c37f6
DM
1954
1955 return 0;
1956}
1957
1958static int update_schedule_file(Manager *m) {
91b3e7fb 1959 _cleanup_free_ char *temp_path = NULL;
867c37f6 1960 _cleanup_fclose_ FILE *f = NULL;
91b3e7fb 1961 int r;
867c37f6
DM
1962
1963 assert(m);
1964
37c1d5e9 1965 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0, MKDIR_WARN_MODE);
867c37f6
DM
1966 if (r < 0)
1967 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1968
867c37f6
DM
1969 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1970 if (r < 0)
1971 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1972
1973 (void) fchmod(fileno(f), 0644);
1974
1975 fprintf(f,
1976 "USEC="USEC_FMT"\n"
1977 "WARN_WALL=%i\n"
1978 "MODE=%s\n",
1979 m->scheduled_shutdown_timeout,
1980 m->enable_wall_messages,
1981 m->scheduled_shutdown_type);
1982
91b3e7fb
LP
1983 if (!isempty(m->wall_message)) {
1984 _cleanup_free_ char *t;
1985
1986 t = cescape(m->wall_message);
1987 if (!t) {
1988 r = -ENOMEM;
1989 goto fail;
1990 }
1991
867c37f6 1992 fprintf(f, "WALL_MESSAGE=%s\n", t);
91b3e7fb 1993 }
867c37f6 1994
dacd6cee
LP
1995 r = fflush_and_check(f);
1996 if (r < 0)
1997 goto fail;
867c37f6 1998
dacd6cee 1999 if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
867c37f6 2000 r = -errno;
dacd6cee 2001 goto fail;
867c37f6
DM
2002 }
2003
dacd6cee
LP
2004 return 0;
2005
2006fail:
2007 (void) unlink(temp_path);
2008 (void) unlink("/run/systemd/shutdown/scheduled");
2009
2010 return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
867c37f6
DM
2011}
2012
df75a1a8 2013static void reset_scheduled_shutdown(Manager *m) {
36b69c31
LP
2014 assert(m);
2015
df75a1a8
AJ
2016 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2017 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
2018 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
36b69c31 2019
df75a1a8
AJ
2020 m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
2021 m->scheduled_shutdown_timeout = 0;
2022 m->shutdown_dry_run = false;
2023
2024 if (m->unlink_nologin) {
af229d7a 2025 (void) unlink_or_warn("/run/nologin");
df75a1a8
AJ
2026 m->unlink_nologin = false;
2027 }
36b69c31 2028
df75a1a8
AJ
2029 (void) unlink("/run/systemd/shutdown/scheduled");
2030}
2031
8aaa023a
DM
2032static int manager_scheduled_shutdown_handler(
2033 sd_event_source *s,
2034 uint64_t usec,
2035 void *userdata) {
2036
4afd3348 2037 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
8aaa023a
DM
2038 Manager *m = userdata;
2039 const char *target;
2040 int r;
2041
2042 assert(m);
2043
2044 if (isempty(m->scheduled_shutdown_type))
2045 return 0;
2046
36b69c31 2047 if (streq(m->scheduled_shutdown_type, "poweroff"))
8aaa023a 2048 target = SPECIAL_POWEROFF_TARGET;
36b69c31 2049 else if (streq(m->scheduled_shutdown_type, "reboot"))
8aaa023a 2050 target = SPECIAL_REBOOT_TARGET;
36b69c31
LP
2051 else if (streq(m->scheduled_shutdown_type, "halt"))
2052 target = SPECIAL_HALT_TARGET;
2053 else
2054 assert_not_reached("unexpected shutdown type");
8aaa023a 2055
b498d6ea 2056 /* Don't allow multiple jobs being executed at the same time */
f8bfa318 2057 if (m->action_what > 0) {
6d7f7fd4 2058 r = -EALREADY;
b498d6ea 2059 log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target);
6d7f7fd4 2060 goto error;
b498d6ea
AJ
2061 }
2062
df75a1a8
AJ
2063 if (m->shutdown_dry_run) {
2064 /* We do not process delay inhibitors here. Otherwise, we
2065 * would have to be considered "in progress" (like the check
2066 * above) for some seconds after our admin has seen the final
2067 * wall message. */
2068
2069 bus_manager_log_shutdown(m, target);
2070 log_info("Running in dry run, suppressing action.");
2071 reset_scheduled_shutdown(m);
2072
2073 return 0;
2074 }
2075
2076 r = bus_manager_shutdown_or_sleep_now_or_later(m, target, INHIBIT_SHUTDOWN, &error);
6d7f7fd4
AJ
2077 if (r < 0) {
2078 log_error_errno(r, "Scheduled shutdown to %s failed: %m", target);
2079 goto error;
2080 }
8aaa023a
DM
2081
2082 return 0;
6d7f7fd4
AJ
2083
2084error:
2085 reset_scheduled_shutdown(m);
2086 return r;
8aaa023a
DM
2087}
2088
19070062 2089static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
8aaa023a 2090 Manager *m = userdata;
4afd3348 2091 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
8aaa023a
DM
2092 const char *action_multiple_sessions = NULL;
2093 const char *action_ignore_inhibit = NULL;
2094 const char *action = NULL;
2095 uint64_t elapse;
2096 char *type;
2097 int r;
d13f5e16 2098 bool dry_run = false;
8aaa023a
DM
2099
2100 assert(m);
2101 assert(message);
2102
2103 r = sd_bus_message_read(message, "st", &type, &elapse);
2104 if (r < 0)
2105 return r;
2106
1389f4b9
DM
2107 if (startswith(type, "dry-")) {
2108 type += 4;
d13f5e16 2109 dry_run = true;
1389f4b9
DM
2110 }
2111
36b69c31
LP
2112 if (streq(type, "poweroff")) {
2113 action = "org.freedesktop.login1.power-off";
2114 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
2115 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
2116 } else if (streq(type, "reboot")) {
8aaa023a
DM
2117 action = "org.freedesktop.login1.reboot";
2118 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
2119 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
2120 } else if (streq(type, "halt")) {
2121 action = "org.freedesktop.login1.halt";
2122 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
2123 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
8aaa023a
DM
2124 } else
2125 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
2126
2127 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
2128 action, action_multiple_sessions, action_ignore_inhibit, error);
2129 if (r != 0)
2130 return r;
2131
2132 if (m->scheduled_shutdown_timeout_source) {
2133 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
2134 if (r < 0)
c2a23db0 2135 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
8aaa023a
DM
2136
2137 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2138 if (r < 0)
c2a23db0 2139 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
8aaa023a
DM
2140 } else {
2141 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2142 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2143 if (r < 0)
c2a23db0 2144 return log_error_errno(r, "sd_event_add_time() failed: %m");
8aaa023a
DM
2145 }
2146
2147 r = free_and_strdup(&m->scheduled_shutdown_type, type);
2148 if (r < 0) {
2149 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2150 return log_oom();
2151 }
2152
d13f5e16
LP
2153 m->shutdown_dry_run = dry_run;
2154
867c37f6
DM
2155 if (m->nologin_timeout_source) {
2156 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2157 if (r < 0)
c2a23db0 2158 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
867c37f6
DM
2159
2160 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2161 if (r < 0)
c2a23db0 2162 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
867c37f6
DM
2163 } else {
2164 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2165 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2166 if (r < 0)
c2a23db0 2167 return log_error_errno(r, "sd_event_add_time() failed: %m");
867c37f6
DM
2168 }
2169
8aaa023a
DM
2170 m->scheduled_shutdown_timeout = elapse;
2171
e2fa5721
DM
2172 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2173 if (r >= 0) {
011062f3 2174 const char *tty = NULL;
e2fa5721
DM
2175
2176 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2177 (void) sd_bus_creds_get_tty(creds, &tty);
2178
2179 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2180 if (r < 0) {
2181 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2182 return log_oom();
2183 }
2184 }
2185
2186 r = manager_setup_wall_message_timer(m);
2187 if (r < 0)
2188 return r;
2189
f8169e62
AJ
2190 r = update_schedule_file(m);
2191 if (r < 0)
2192 return r;
867c37f6 2193
8aaa023a
DM
2194 return sd_bus_reply_method_return(message, NULL);
2195}
2196
19070062 2197static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
8aaa023a
DM
2198 Manager *m = userdata;
2199 bool cancelled;
2200
2201 assert(m);
2202 assert(message);
2203
2204 cancelled = m->scheduled_shutdown_type != NULL;
1389f4b9 2205 reset_scheduled_shutdown(m);
fb91034c 2206
6e78fa4a 2207 if (cancelled && m->enable_wall_messages) {
4afd3348 2208 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
e99742ef 2209 _cleanup_free_ char *username = NULL;
e2fa5721
DM
2210 const char *tty = NULL;
2211 uid_t uid = 0;
2212 int r;
2213
2214 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2215 if (r >= 0) {
2216 (void) sd_bus_creds_get_uid(creds, &uid);
2217 (void) sd_bus_creds_get_tty(creds, &tty);
2218 }
2219
e99742ef 2220 username = uid_to_name(uid);
e2fa5721 2221 utmp_wall("The system shutdown has been cancelled",
e99742ef 2222 username, tty, logind_wall_tty_filter, m);
e2fa5721
DM
2223 }
2224
8aaa023a
DM
2225 return sd_bus_reply_method_return(message, "b", cancelled);
2226}
2227
cc377381
LP
2228static int method_can_shutdown_or_sleep(
2229 Manager *m,
2230 sd_bus_message *message,
2231 InhibitWhat w,
2232 const char *action,
2233 const char *action_multiple_sessions,
2234 const char *action_ignore_inhibit,
ebcf1f97
LP
2235 const char *sleep_verb,
2236 sd_bus_error *error) {
de07ab16 2237
4afd3348 2238 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
c8c8ee85 2239 HandleAction handle;
cc377381
LP
2240 bool multiple_sessions, challenge, blocked;
2241 const char *result = NULL;
2242 uid_t uid;
2243 int r;
de07ab16 2244
cc377381
LP
2245 assert(m);
2246 assert(message);
2247 assert(w >= 0);
2248 assert(w <= _INHIBIT_WHAT_MAX);
2249 assert(action);
2250 assert(action_multiple_sessions);
2251 assert(action_ignore_inhibit);
de07ab16 2252
cc377381
LP
2253 if (sleep_verb) {
2254 r = can_sleep(sleep_verb);
8340b762 2255 if (IN_SET(r, 0, -ENOSPC))
b71c9758 2256 return sd_bus_reply_method_return(message, "s", "na");
de07ab16 2257 if (r < 0)
ebcf1f97 2258 return r;
cc377381 2259 }
de07ab16 2260
05bae4a6 2261 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
5b12334d
LP
2262 if (r < 0)
2263 return r;
2264
05bae4a6 2265 r = sd_bus_creds_get_euid(creds, &uid);
cc377381 2266 if (r < 0)
ebcf1f97 2267 return r;
de07ab16 2268
cc377381
LP
2269 r = have_multiple_sessions(m, uid);
2270 if (r < 0)
ebcf1f97 2271 return r;
de07ab16 2272
cc377381 2273 multiple_sessions = r > 0;
85a428c6 2274 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
de07ab16 2275
c8c8ee85
ZJS
2276 handle = handle_action_from_string(sleep_verb);
2277 if (handle >= 0) {
2278 const char *target;
2279
2280 target = manager_target_for_action(handle);
2281 if (target) {
2282 _cleanup_free_ char *load_state = NULL;
2283
2284 r = unit_load_state(m->bus, target, &load_state);
2285 if (r < 0)
2286 return r;
2287
2288 if (!streq(load_state, "loaded")) {
2289 result = "no";
2290 goto finish;
2291 }
2292 }
2293 }
2294
cc377381 2295 if (multiple_sessions) {
403ed0e5 2296 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
de07ab16 2297 if (r < 0)
ebcf1f97 2298 return r;
bef422ae 2299
cc377381
LP
2300 if (r > 0)
2301 result = "yes";
2302 else if (challenge)
2303 result = "challenge";
2304 else
2305 result = "no";
2306 }
bef422ae 2307
cc377381 2308 if (blocked) {
403ed0e5 2309 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
bef422ae 2310 if (r < 0)
ebcf1f97 2311 return r;
bef422ae 2312
0c093a62
HT
2313 if (r > 0) {
2314 if (!result)
2315 result = "yes";
2316 } else if (challenge) {
2317 if (!result || streq(result, "yes"))
2318 result = "challenge";
2319 } else
cc377381
LP
2320 result = "no";
2321 }
bef422ae 2322
cc377381
LP
2323 if (!multiple_sessions && !blocked) {
2324 /* If neither inhibit nor multiple sessions
2325 * apply then just check the normal policy */
bef422ae 2326
403ed0e5 2327 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
bef422ae 2328 if (r < 0)
ebcf1f97 2329 return r;
bef422ae 2330
cc377381
LP
2331 if (r > 0)
2332 result = "yes";
2333 else if (challenge)
2334 result = "challenge";
2335 else
2336 result = "no";
2337 }
bef422ae 2338
c8c8ee85 2339 finish:
df2d202e 2340 return sd_bus_reply_method_return(message, "s", result);
cc377381 2341}
bef422ae 2342
19070062 2343static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 2344 Manager *m = userdata;
bef422ae 2345
cc377381
LP
2346 return method_can_shutdown_or_sleep(
2347 m, message,
2348 INHIBIT_SHUTDOWN,
2349 "org.freedesktop.login1.power-off",
2350 "org.freedesktop.login1.power-off-multiple-sessions",
2351 "org.freedesktop.login1.power-off-ignore-inhibit",
ebcf1f97
LP
2352 NULL,
2353 error);
cc377381 2354}
bef422ae 2355
19070062 2356static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 2357 Manager *m = userdata;
bef422ae 2358
cc377381
LP
2359 return method_can_shutdown_or_sleep(
2360 m, message,
2361 INHIBIT_SHUTDOWN,
2362 "org.freedesktop.login1.reboot",
2363 "org.freedesktop.login1.reboot-multiple-sessions",
2364 "org.freedesktop.login1.reboot-ignore-inhibit",
ebcf1f97
LP
2365 NULL,
2366 error);
cc377381 2367}
bef422ae 2368
36b69c31
LP
2369static int method_can_halt(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2370 Manager *m = userdata;
2371
2372 return method_can_shutdown_or_sleep(
2373 m, message,
2374 INHIBIT_SHUTDOWN,
2375 "org.freedesktop.login1.halt",
2376 "org.freedesktop.login1.halt-multiple-sessions",
2377 "org.freedesktop.login1.halt-ignore-inhibit",
2378 NULL,
2379 error);
2380}
2381
19070062 2382static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 2383 Manager *m = userdata;
7f7bb946 2384
cc377381
LP
2385 return method_can_shutdown_or_sleep(
2386 m, message,
2387 INHIBIT_SLEEP,
2388 "org.freedesktop.login1.suspend",
2389 "org.freedesktop.login1.suspend-multiple-sessions",
2390 "org.freedesktop.login1.suspend-ignore-inhibit",
ebcf1f97
LP
2391 "suspend",
2392 error);
cc377381 2393}
7f7bb946 2394
19070062 2395static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 2396 Manager *m = userdata;
02b16a19 2397
cc377381
LP
2398 return method_can_shutdown_or_sleep(
2399 m, message,
2400 INHIBIT_SLEEP,
2401 "org.freedesktop.login1.hibernate",
2402 "org.freedesktop.login1.hibernate-multiple-sessions",
2403 "org.freedesktop.login1.hibernate-ignore-inhibit",
ebcf1f97
LP
2404 "hibernate",
2405 error);
cc377381 2406}
7f7bb946 2407
19070062 2408static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 2409 Manager *m = userdata;
7f7bb946 2410
cc377381
LP
2411 return method_can_shutdown_or_sleep(
2412 m, message,
2413 INHIBIT_SLEEP,
2414 "org.freedesktop.login1.hibernate",
2415 "org.freedesktop.login1.hibernate-multiple-sessions",
2416 "org.freedesktop.login1.hibernate-ignore-inhibit",
ebcf1f97
LP
2417 "hybrid-sleep",
2418 error);
cc377381 2419}
38f3fc7d 2420
e68c79db 2421static int method_can_suspend_then_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
c58493c0
ML
2422 Manager *m = userdata;
2423
2424 return method_can_shutdown_or_sleep(
2425 m, message,
2426 INHIBIT_SLEEP,
2427 "org.freedesktop.login1.hibernate",
2428 "org.freedesktop.login1.hibernate-multiple-sessions",
2429 "org.freedesktop.login1.hibernate-ignore-inhibit",
e68c79db 2430 "suspend-then-hibernate",
c58493c0
ML
2431 error);
2432}
2433
428b296a
VJ
2434static int property_get_reboot_parameter(
2435 sd_bus *bus,
2436 const char *path,
2437 const char *interface,
2438 const char *property,
2439 sd_bus_message *reply,
2440 void *userdata,
2441 sd_bus_error *error) {
2442 _cleanup_free_ char *parameter = NULL;
2443 int r;
2444
2445 assert(bus);
2446 assert(reply);
2447 assert(userdata);
2448
2449 r = read_reboot_parameter(&parameter);
2450 if (r < 0)
2451 return r;
2452
2453 return sd_bus_message_append(reply, "s", parameter);
2454}
2455
2456static int method_set_reboot_parameter(
2457 sd_bus_message *message,
2458 void *userdata,
2459 sd_bus_error *error) {
2460
2461 Manager *m = userdata;
2462 const char *arg;
2463 int r;
2464
2465 assert(message);
2466 assert(m);
2467
2468 r = sd_bus_message_read(message, "s", &arg);
2469 if (r < 0)
2470 return r;
2471
2472 r = detect_container();
2473 if (r < 0)
2474 return r;
2475 if (r > 0)
2476 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
2477 "Reboot parameter not supported in containers, refusing.");
2478
2479 r = bus_verify_polkit_async(message,
2480 CAP_SYS_ADMIN,
2481 "org.freedesktop.login1.set-reboot-parameter",
2482 NULL,
2483 false,
2484 UID_INVALID,
2485 &m->polkit_registry,
2486 error);
2487 if (r < 0)
2488 return r;
2489 if (r == 0)
2490 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2491
2492 r = update_reboot_parameter_and_warn(arg, false);
2493 if (r < 0)
2494 return r;
2495
2496 return sd_bus_reply_method_return(message, NULL);
2497}
2498
2499static int method_can_reboot_parameter(
2500 sd_bus_message *message,
2501 void *userdata,
2502 sd_bus_error *error) {
2503
2504 Manager *m = userdata;
2505 int r;
2506
2507 assert(message);
2508 assert(m);
2509
2510 r = detect_container();
2511 if (r < 0)
2512 return r;
2513 if (r > 0) /* Inside containers, specifying a reboot parameter, doesn't make much sense */
2514 return sd_bus_reply_method_return(message, "s", "na");
2515
2516 return return_test_polkit(
2517 message,
2518 CAP_SYS_ADMIN,
2519 "org.freedesktop.login1.set-reboot-parameter",
2520 NULL,
2521 UID_INVALID,
2522 error);
2523}
2524
5bdf2243
JJ
2525static int property_get_reboot_to_firmware_setup(
2526 sd_bus *bus,
2527 const char *path,
2528 const char *interface,
2529 const char *property,
2530 sd_bus_message *reply,
2531 void *userdata,
2532 sd_bus_error *error) {
2533 int r;
2534
2535 assert(bus);
2536 assert(reply);
2537 assert(userdata);
2538
e667266a
LP
2539 r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
2540 if (r == -ENXIO) {
2541 /* EFI case: let's see what is currently configured in the EFI variables */
2542 r = efi_get_reboot_to_firmware();
2543 if (r < 0 && r != -EOPNOTSUPP)
2544 log_warning_errno(r, "Failed to determine reboot-to-firmware-setup state: %m");
2545 } else if (r < 0)
2546 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
2547 else if (r > 0) {
2548 /* Non-EFI case: let's see whether /run/systemd/reboot-to-firmware-setup exists. */
2549 if (access("/run/systemd/reboot-to-firmware-setup", F_OK) < 0) {
2550 if (errno != ENOENT)
2551 log_warning_errno(errno, "Failed to check whether /run/systemd/reboot-to-firmware-setup exists: %m");
2552
2553 r = false;
2554 } else
2555 r = true;
2556 }
5bdf2243
JJ
2557
2558 return sd_bus_message_append(reply, "b", r > 0);
2559}
2560
2561static int method_set_reboot_to_firmware_setup(
5bdf2243
JJ
2562 sd_bus_message *message,
2563 void *userdata,
2564 sd_bus_error *error) {
2565
5bdf2243 2566 Manager *m = userdata;
e667266a
LP
2567 bool use_efi;
2568 int b, r;
5bdf2243 2569
5bdf2243
JJ
2570 assert(message);
2571 assert(m);
2572
889f25b2 2573 r = sd_bus_message_read(message, "b", &b);
5bdf2243
JJ
2574 if (r < 0)
2575 return r;
2576
e667266a
LP
2577 r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
2578 if (r == -ENXIO) {
2579 /* EFI case: let's see what the firmware supports */
2580
2581 r = efi_reboot_to_firmware_supported();
2582 if (r == -EOPNOTSUPP)
2583 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
2584 if (r < 0)
2585 return r;
2586
2587 use_efi = true;
2588
2589 } else if (r <= 0) {
2590 /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to off */
2591
2592 if (r < 0)
2593 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
2594
2595 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Firmware does not support boot into firmware.");
2596 } else
2597 /* non-EFI case: $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP is set to on */
2598 use_efi = false;
2599
5bdf2243
JJ
2600 r = bus_verify_polkit_async(message,
2601 CAP_SYS_ADMIN,
2602 "org.freedesktop.login1.set-reboot-to-firmware-setup",
403ed0e5 2603 NULL,
889f25b2 2604 false,
5bdf2243
JJ
2605 UID_INVALID,
2606 &m->polkit_registry,
2607 error);
2608 if (r < 0)
2609 return r;
2610 if (r == 0)
2611 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2612
e667266a
LP
2613 if (use_efi) {
2614 r = efi_set_reboot_to_firmware(b);
2615 if (r < 0)
2616 return r;
2617 } else {
2618 if (b) {
2619 r = touch("/run/systemd/reboot-to-firmware-setup");
2620 if (r < 0)
2621 return r;
2622 } else {
2623 if (unlink("/run/systemd/reboot-to-firmware-setup") < 0 && errno != ENOENT)
2624 return -errno;
2625 }
2626 }
5bdf2243
JJ
2627
2628 return sd_bus_reply_method_return(message, NULL);
2629}
2630
2631static int method_can_reboot_to_firmware_setup(
5bdf2243
JJ
2632 sd_bus_message *message,
2633 void *userdata,
2634 sd_bus_error *error) {
2635
5bdf2243 2636 Manager *m = userdata;
e667266a 2637 int r;
5bdf2243 2638
5bdf2243
JJ
2639 assert(message);
2640 assert(m);
2641
e667266a
LP
2642 r = getenv_bool("SYSTEMD_REBOOT_TO_FIRMWARE_SETUP");
2643 if (r == -ENXIO) {
2644 /* EFI case: let's see what the firmware supports */
2645
2646 r = efi_reboot_to_firmware_supported();
2647 if (r < 0) {
2648 if (r != -EOPNOTSUPP)
2649 log_warning_errno(r, "Failed to determine whether reboot to firmware is supported: %m");
2650
350f9518 2651 return sd_bus_reply_method_return(message, "s", "na");
e667266a 2652 }
6f302ce6 2653
e667266a
LP
2654 } else if (r <= 0) {
2655 /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP */
2656
2657 if (r < 0)
2658 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_FIRMWARE_SETUP: %m");
2659
350f9518 2660 return sd_bus_reply_method_return(message, "s", "na");
6f302ce6 2661 }
5bdf2243 2662
350f9518
LP
2663 return return_test_polkit(
2664 message,
2665 CAP_SYS_ADMIN,
2666 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2667 NULL,
2668 UID_INVALID,
2669 error);
5bdf2243
JJ
2670}
2671
31b221cf
LP
2672static int property_get_reboot_to_boot_loader_menu(
2673 sd_bus *bus,
2674 const char *path,
2675 const char *interface,
2676 const char *property,
2677 sd_bus_message *reply,
2678 void *userdata,
2679 sd_bus_error *error) {
2680
2681 uint64_t x = UINT64_MAX;
2682 int r;
2683
2684 assert(bus);
2685 assert(reply);
2686 assert(userdata);
2687
2688 r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
2689 if (r == -ENXIO) {
2690 _cleanup_free_ char *v = NULL;
2691
2692 /* EFI case: returns the current value of LoaderConfigTimeoutOneShot. Three cases are distuingished:
2693 *
2694 * 1. Variable not set, boot into boot loader menu is not enabled (we return UINT64_MAX to the user)
2695 * 2. Variable set to "0", boot into boot loader menu is enabled with no timeout (we return 0 to the user)
2696 * 3. Variable set to numeric value formatted in ASCII, boot into boot loader menu with the specified timeout in seconds
2697 */
2698
2699 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", &v);
2700 if (r < 0) {
2701 if (r != -ENOENT)
2702 log_warning_errno(r, "Failed to read LoaderConfigTimeoutOneShot variable: %m");
2703 } else {
2704 uint64_t sec;
2705
2706 r = safe_atou64(v, &sec);
2707 if (r < 0)
2708 log_warning_errno(r, "Failed to parse LoaderConfigTimeoutOneShot value '%s': %m", v);
2709 else if (sec > (USEC_INFINITY / USEC_PER_SEC))
2710 log_warning("LoaderConfigTimeoutOneShot too large, ignoring: %m");
2711 else
2712 x = sec * USEC_PER_SEC; /* return in µs */
2713 }
2714
2715 } else if (r < 0)
2716 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
2717 else if (r > 0) {
2718 _cleanup_free_ char *v = NULL;
2719
2720 /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-menu. */
2721
2722 r = read_one_line_file("/run/systemd/reboot-to-boot-loader-menu", &v);
2723 if (r < 0) {
2724 if (r != -ENOENT)
2725 log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-menu: %m");
2726 } else {
2727 r = safe_atou64(v, &x);
2728 if (r < 0)
2729 log_warning_errno(r, "Failed to parse /run/systemd/reboot-to-boot-loader-menu: %m");
2730 }
2731 }
2732
2733 return sd_bus_message_append(reply, "t", x);
2734}
2735
2736static int method_set_reboot_to_boot_loader_menu(
2737 sd_bus_message *message,
2738 void *userdata,
2739 sd_bus_error *error) {
2740
2741 Manager *m = userdata;
2742 bool use_efi;
2743 uint64_t x;
2744 int r;
2745
2746 assert(message);
2747 assert(m);
2748
2749 r = sd_bus_message_read(message, "t", &x);
2750 if (r < 0)
2751 return r;
2752
2753 r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
2754 if (r == -ENXIO) {
2755 uint64_t features;
2756
2757 /* EFI case: let's see if booting into boot loader menu is supported. */
2758
2759 r = efi_loader_get_features(&features);
2760 if (r < 0)
2761 log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
2762 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
2763 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
2764
2765 use_efi = true;
2766
2767 } else if (r <= 0) {
2768 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to off */
2769
2770 if (r < 0)
2771 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
2772
2773 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader does not support boot into boot loader menu.");
2774 } else
2775 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU is set to on */
2776 use_efi = false;
2777
2778 r = bus_verify_polkit_async(message,
2779 CAP_SYS_ADMIN,
2780 "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
2781 NULL,
2782 false,
2783 UID_INVALID,
2784 &m->polkit_registry,
2785 error);
2786 if (r < 0)
2787 return r;
2788 if (r == 0)
2789 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2790
2791 if (use_efi) {
2792 if (x == UINT64_MAX)
2793 r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", NULL, 0);
2794 else {
2795 char buf[DECIMAL_STR_MAX(uint64_t) + 1];
2796 xsprintf(buf, "%" PRIu64, DIV_ROUND_UP(x, USEC_PER_SEC)); /* second granularity */
2797
2798 r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderConfigTimeoutOneShot", buf);
2799 }
2800 if (r < 0)
2801 return r;
2802 } else {
2803 if (x == UINT64_MAX) {
2804 if (unlink("/run/systemd/reboot-to-loader-menu") < 0 && errno != ENOENT)
2805 return -errno;
2806 } else {
2807 char buf[DECIMAL_STR_MAX(uint64_t) + 1];
2808
2809 xsprintf(buf, "%" PRIu64, x); /* µs granularity */
2810
2811 r = write_string_file_atomic_label("/run/systemd/reboot-to-loader-menu", buf);
2812 if (r < 0)
2813 return r;
2814 }
2815 }
2816
2817 return sd_bus_reply_method_return(message, NULL);
2818}
2819
2820static int method_can_reboot_to_boot_loader_menu(
2821 sd_bus_message *message,
2822 void *userdata,
2823 sd_bus_error *error) {
2824
31b221cf 2825 Manager *m = userdata;
31b221cf
LP
2826 int r;
2827
31b221cf
LP
2828 assert(message);
2829 assert(m);
2830
2831 r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU");
2832 if (r == -ENXIO) {
2833 uint64_t features = 0;
2834
2835 /* EFI case, let's see if booting into boot loader menu is supported. */
2836
2837 r = efi_loader_get_features(&features);
2838 if (r < 0)
2839 log_warning_errno(r, "Failed to determine whether reboot to boot loader menu is supported: %m");
2840 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_CONFIG_TIMEOUT_ONE_SHOT))
350f9518 2841 return sd_bus_reply_method_return(message, "s", "na");
31b221cf
LP
2842
2843 } else if (r <= 0) {
2844 /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU */
2845
2846 if (r < 0)
2847 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_MENU: %m");
2848
350f9518 2849 return sd_bus_reply_method_return(message, "s", "na");
31b221cf
LP
2850 }
2851
350f9518
LP
2852 return return_test_polkit(
2853 message,
2854 CAP_SYS_ADMIN,
2855 "org.freedesktop.login1.set-reboot-to-boot-loader-menu",
2856 NULL,
2857 UID_INVALID,
2858 error);
31b221cf
LP
2859}
2860
2861static int property_get_reboot_to_boot_loader_entry(
2862 sd_bus *bus,
2863 const char *path,
2864 const char *interface,
2865 const char *property,
2866 sd_bus_message *reply,
2867 void *userdata,
2868 sd_bus_error *error) {
2869
2870 _cleanup_free_ char *v = NULL;
2871 int r;
2872
2873 assert(bus);
2874 assert(reply);
2875 assert(userdata);
2876
2877 r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
2878 if (r == -ENXIO) {
2879 /* EFI case: let's read the LoaderEntryOneShot variable */
2880
2881 r = efi_get_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", &v);
2882 if (r < 0) {
2883 if (r != -ENOENT)
2884 log_warning_errno(r, "Failed to read LoaderEntryOneShot variable: %m");
2885 } else if (!efi_loader_entry_name_valid(v)) {
2886 log_warning("LoaderEntryOneShot contains invalid entry name '%s', ignoring.", v);
2887 v = mfree(v);
2888 }
2889 } else if (r < 0)
2890 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
2891 else if (r > 0) {
2892
2893 /* Non-EFI case, let's process /run/systemd/reboot-to-boot-loader-entry. */
2894
2895 r = read_one_line_file("/run/systemd/reboot-to-boot-loader-entry", &v);
2896 if (r < 0) {
2897 if (r != -ENOENT)
2898 log_warning_errno(r, "Failed to read /run/systemd/reboot-to-boot-loader-entry: %m");
2899 } else if (!efi_loader_entry_name_valid(v)) {
2900 log_warning("/run/systemd/reboot-to-boot-loader-entry is not valid, ignoring.");
2901 v = mfree(v);
2902 }
2903 }
2904
2905 return sd_bus_message_append(reply, "s", v);
2906}
2907
2908static int boot_loader_entry_exists(const char *id) {
2909 _cleanup_(boot_config_free) BootConfig config = {};
2910 int r;
2911
2912 assert(id);
2913
2914 r = boot_entries_load_config_auto(NULL, NULL, &config);
cc5957dc 2915 if (r < 0 && r != -ENOKEY) /* don't complain if no GPT is found, hence skip ENOKEY */
31b221cf
LP
2916 return r;
2917
2918 (void) boot_entries_augment_from_loader(&config, true);
2919
2920 return boot_config_has_entry(&config, id);
2921}
2922
2923static int method_set_reboot_to_boot_loader_entry(
2924 sd_bus_message *message,
2925 void *userdata,
2926 sd_bus_error *error) {
2927
2928 Manager *m = userdata;
2929 bool use_efi;
2930 const char *v;
2931 int r;
2932
2933 assert(message);
2934 assert(m);
2935
2936 r = sd_bus_message_read(message, "s", &v);
2937 if (r < 0)
2938 return r;
2939
2940 if (isempty(v))
2941 v = NULL;
2942 else if (efi_loader_entry_name_valid(v)) {
2943 r = boot_loader_entry_exists(v);
2944 if (r < 0)
2945 return r;
2946 if (r == 0)
2947 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Boot loader entry '%s' is not known.", v);
2948 } else
2949 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Boot loader entry name '%s' is not valid, refusing.", v);
2950
2951 r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
2952 if (r == -ENXIO) {
2953 uint64_t features;
2954
2955 /* EFI case: let's see if booting into boot loader entry is supported. */
2956
2957 r = efi_loader_get_features(&features);
2958 if (r < 0)
2959 log_warning_errno(r, "Failed to determine whether reboot into boot loader entry is supported: %m");
2960 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
2961 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
2962
2963 use_efi = true;
2964
2965 } else if (r <= 0) {
2966 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to off */
2967
2968 if (r < 0)
2969 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
2970
2971 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Loader does not support boot into boot loader entry.");
2972 } else
2973 /* non-EFI case: $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY is set to on */
2974 use_efi = false;
2975
2976 r = bus_verify_polkit_async(message,
2977 CAP_SYS_ADMIN,
2978 "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
2979 NULL,
2980 false,
2981 UID_INVALID,
2982 &m->polkit_registry,
2983 error);
2984 if (r < 0)
2985 return r;
2986 if (r == 0)
2987 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2988
2989 if (use_efi) {
2990 if (isempty(v))
2991 /* Delete item */
2992 r = efi_set_variable(EFI_VENDOR_LOADER, "LoaderEntryOneShot", NULL, 0);
2993 else
2994 r = efi_set_variable_string(EFI_VENDOR_LOADER, "LoaderEntryOneShot", v);
2995 if (r < 0)
2996 return r;
2997 } else {
2998 if (isempty(v)) {
2999 if (unlink("/run/systemd/reboot-to-boot-loader-entry") < 0 && errno != ENOENT)
3000 return -errno;
3001 } else {
3002 r = write_string_file_atomic_label("/run/systemd/reboot-boot-to-loader-entry", v);
3003 if (r < 0)
3004 return r;
3005 }
3006 }
3007
3008 return sd_bus_reply_method_return(message, NULL);
3009}
3010
3011static int method_can_reboot_to_boot_loader_entry(
3012 sd_bus_message *message,
3013 void *userdata,
3014 sd_bus_error *error) {
3015
31b221cf 3016 Manager *m = userdata;
31b221cf
LP
3017 int r;
3018
3019 assert(message);
3020 assert(m);
3021
3022 r = getenv_bool("SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY");
3023 if (r == -ENXIO) {
3024 uint64_t features = 0;
3025
3026 /* EFI case, let's see if booting into boot loader entry is supported. */
3027
3028 r = efi_loader_get_features(&features);
3029 if (r < 0)
3030 log_warning_errno(r, "Failed to determine whether reboot to boot loader entry is supported: %m");
3031 if (r < 0 || !FLAGS_SET(features, EFI_LOADER_FEATURE_ENTRY_ONESHOT))
350f9518 3032 return sd_bus_reply_method_return(message, "s", "na");
31b221cf
LP
3033
3034 } else if (r <= 0) {
3035 /* Non-EFI case: let's trust $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY */
3036
3037 if (r < 0)
3038 log_warning_errno(r, "Failed to parse $SYSTEMD_REBOOT_TO_BOOT_LOADER_ENTRY: %m");
3039
350f9518 3040 return sd_bus_reply_method_return(message, "s", "na");
31b221cf
LP
3041 }
3042
350f9518
LP
3043 return return_test_polkit(
3044 message,
3045 CAP_SYS_ADMIN,
3046 "org.freedesktop.login1.set-reboot-to-boot-loader-entry",
3047 NULL,
3048 UID_INVALID,
3049 error);
31b221cf
LP
3050}
3051
3052static int property_get_boot_loader_entries(
3053 sd_bus *bus,
3054 const char *path,
3055 const char *interface,
3056 const char *property,
3057 sd_bus_message *reply,
3058 void *userdata,
3059 sd_bus_error *error) {
3060
3061 _cleanup_(boot_config_free) BootConfig config = {};
3062 size_t i;
3063 int r;
3064
3065 assert(bus);
3066 assert(reply);
3067 assert(userdata);
3068
3069 r = boot_entries_load_config_auto(NULL, NULL, &config);
cc5957dc 3070 if (r < 0 && r != -ENOKEY) /* don't complain if there's no GPT found */
31b221cf
LP
3071 return r;
3072
3073 (void) boot_entries_augment_from_loader(&config, true);
3074
3075 r = sd_bus_message_open_container(reply, 'a', "s");
3076 if (r < 0)
3077 return r;
3078
3079 for (i = 0; i < config.n_entries; i++) {
3080 BootEntry *e = config.entries + i;
3081
3082 r = sd_bus_message_append(reply, "s", e->id);
3083 if (r < 0)
3084 return r;
3085 }
3086
3087 return sd_bus_message_close_container(reply);
3088}
3089
9ef15026
JS
3090static int method_set_wall_message(
3091 sd_bus_message *message,
3092 void *userdata,
3093 sd_bus_error *error) {
3094
3095 int r;
3096 Manager *m = userdata;
3097 char *wall_message;
c9482b88 3098 unsigned enable_wall_messages;
9ef15026
JS
3099
3100 assert(message);
3101 assert(m);
3102
3103 r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
3104 if (r < 0)
3105 return r;
3106
3107 r = bus_verify_polkit_async(message,
3108 CAP_SYS_ADMIN,
3109 "org.freedesktop.login1.set-wall-message",
403ed0e5 3110 NULL,
9ef15026
JS
3111 false,
3112 UID_INVALID,
3113 &m->polkit_registry,
3114 error);
9ef15026
JS
3115 if (r < 0)
3116 return r;
3117 if (r == 0)
3118 return 1; /* Will call us back */
3119
28a9ec44
ZJS
3120 r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
3121 if (r < 0)
3122 return log_oom();
5744f59a 3123
9ef15026
JS
3124 m->enable_wall_messages = enable_wall_messages;
3125
3126 return sd_bus_reply_method_return(message, NULL);
3127}
3128
19070062 3129static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4afd3348 3130 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
cc377381
LP
3131 const char *who, *why, *what, *mode;
3132 _cleanup_free_ char *id = NULL;
3133 _cleanup_close_ int fifo_fd = -1;
3134 Manager *m = userdata;
3135 Inhibitor *i = NULL;
3136 InhibitMode mm;
3137 InhibitWhat w;
3138 pid_t pid;
3139 uid_t uid;
3140 int r;
7f7bb946 3141
cc377381
LP
3142 assert(message);
3143 assert(m);
38f3fc7d 3144
cc377381
LP
3145 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
3146 if (r < 0)
ebcf1f97 3147 return r;
38f3fc7d 3148
cc377381
LP
3149 w = inhibit_what_from_string(what);
3150 if (w <= 0)
124d7cb2
ZJS
3151 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
3152 "Invalid what specification %s", what);
38f3fc7d 3153
cc377381
LP
3154 mm = inhibit_mode_from_string(mode);
3155 if (mm < 0)
124d7cb2
ZJS
3156 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
3157 "Invalid mode specification %s", mode);
7f7bb946 3158
cc377381
LP
3159 /* Delay is only supported for shutdown/sleep */
3160 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
124d7cb2
ZJS
3161 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
3162 "Delay inhibitors only supported for shutdown and sleep");
38f3fc7d 3163
cc377381
LP
3164 /* Don't allow taking delay locks while we are already
3165 * executing the operation. We shouldn't create the impression
3166 * that the lock was successful if the machine is about to go
3167 * down/suspend any moment. */
3168 if (m->action_what & w)
124d7cb2
ZJS
3169 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
3170 "The operation inhibition has been requested for is already running");
cc377381 3171
c529695e
LP
3172 r = bus_verify_polkit_async(
3173 message,
3174 CAP_SYS_BOOT,
3175 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
3176 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
3177 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
3178 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
3179 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
3180 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
3181 "org.freedesktop.login1.inhibit-handle-lid-switch",
403ed0e5 3182 NULL,
c529695e
LP
3183 false,
3184 UID_INVALID,
3185 &m->polkit_registry,
3186 error);
cc377381 3187 if (r < 0)
ebcf1f97 3188 return r;
cc377381
LP
3189 if (r == 0)
3190 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
7f7bb946 3191
05bae4a6 3192 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
5b12334d
LP
3193 if (r < 0)
3194 return r;
3195
05bae4a6 3196 r = sd_bus_creds_get_euid(creds, &uid);
cc377381 3197 if (r < 0)
ebcf1f97 3198 return r;
7f7bb946 3199
5b12334d 3200 r = sd_bus_creds_get_pid(creds, &pid);
cc377381 3201 if (r < 0)
ebcf1f97 3202 return r;
47a26690 3203
c5a11ae2 3204 if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
124d7cb2
ZJS
3205 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED,
3206 "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.",
3207 m->inhibitors_max);
c5a11ae2 3208
cc377381 3209 do {
97b11eed 3210 id = mfree(id);
47a26690 3211
cc377381 3212 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
ebcf1f97 3213 return -ENOMEM;
47a26690 3214
cc377381 3215 } while (hashmap_get(m->inhibitors, id));
47a26690 3216
cc377381
LP
3217 r = manager_add_inhibitor(m, id, &i);
3218 if (r < 0)
ebcf1f97 3219 return r;
47a26690 3220
cc377381
LP
3221 i->what = w;
3222 i->mode = mm;
3223 i->pid = pid;
3224 i->uid = uid;
3225 i->why = strdup(why);
3226 i->who = strdup(who);
7f7bb946 3227
cc377381 3228 if (!i->why || !i->who) {
ebcf1f97 3229 r = -ENOMEM;
cc377381
LP
3230 goto fail;
3231 }
b668e064 3232
cc377381
LP
3233 fifo_fd = inhibitor_create_fifo(i);
3234 if (fifo_fd < 0) {
ebcf1f97 3235 r = fifo_fd;
cc377381
LP
3236 goto fail;
3237 }
b668e064 3238
cc377381 3239 inhibitor_start(i);
b668e064 3240
df2d202e 3241 return sd_bus_reply_method_return(message, "h", fifo_fd);
b668e064 3242
cc377381
LP
3243fail:
3244 if (i)
3245 inhibitor_free(i);
89f13440 3246
cc377381
LP
3247 return r;
3248}
3f49d45a 3249
cc377381
LP
3250const sd_bus_vtable manager_vtable[] = {
3251 SD_BUS_VTABLE_START(0),
3252
e2fa5721
DM
3253 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
3254 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
3255
556089dc
LP
3256 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
3257 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
3258 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
3259 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
428b296a 3260 SD_BUS_PROPERTY("RebootParameter", "s", property_get_reboot_parameter, 0, 0),
c30e0d7b 3261 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, 0),
31b221cf
LP
3262 SD_BUS_PROPERTY("RebootToBootLoaderMenu", "t", property_get_reboot_to_boot_loader_menu, 0, 0),
3263 SD_BUS_PROPERTY("RebootToBootLoaderEntry", "s", property_get_reboot_to_boot_loader_entry, 0, 0),
3264 SD_BUS_PROPERTY("BootLoaderEntries", "as", property_get_boot_loader_entries, 0, SD_BUS_VTABLE_PROPERTY_CONST),
cc377381
LP
3265 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3266 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3267 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3268 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
3269 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
556089dc 3270 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
9afe9efb 3271 SD_BUS_PROPERTY("UserStopDelayUSec", "t", NULL, offsetof(Manager, user_stop_delay), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
3272 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
3273 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
3274 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
3275 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
e25937a3 3276 SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST),
3c56cab4 3277 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
9d10cbee 3278 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
3279 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
3280 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
cc377381
LP
3281 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
3282 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
8aaa023a 3283 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
14856079 3284 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
9b9c23da 3285 SD_BUS_PROPERTY("LidClosed", "b", property_get_lid_closed, 0, 0),
4e96eb68 3286 SD_BUS_PROPERTY("OnExternalPower", "b", property_get_on_external_power, 0, 0),
6d97d3c6 3287 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
a7b46b7d 3288 SD_BUS_PROPERTY("RuntimeDirectorySize", "t", NULL, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
c5a11ae2 3289 SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
01adcd69 3290 SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_hashmap_size, offsetof(Manager, inhibitors), 0),
183e0738 3291 SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
01adcd69 3292 SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_hashmap_size, offsetof(Manager, sessions), 0),
28414939 3293 SD_BUS_PROPERTY("UserTasksMax", "t", property_get_compat_user_tasks_max, 0, SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
cc377381 3294
adacb957
LP
3295 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
3296 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
3297 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
3298 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
3299 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
3300 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
3301 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
3302 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
3303 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
a4cd87e9 3304 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
cc377381 3305 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
adacb957
LP
3306 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
3307 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
c529695e
LP
3308 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
3309 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
3310 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
3311 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
3312 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
3313 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
3314 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
3315 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
3316 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
3317 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
3318 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
3319 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
3320 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
3321 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
36b69c31 3322 SD_BUS_METHOD("Halt", "b", NULL, method_halt, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
3323 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
3324 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
3325 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
e68c79db 3326 SD_BUS_METHOD("SuspendThenHibernate", "b", NULL, method_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
3327 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
3328 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
36b69c31 3329 SD_BUS_METHOD("CanHalt", NULL, "s", method_can_halt, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957
LP
3330 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
3331 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
3332 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
e68c79db 3333 SD_BUS_METHOD("CanSuspendThenHibernate", NULL, "s", method_can_suspend_then_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
559b5cc2
LP
3334 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
3335 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
adacb957 3336 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
428b296a
VJ
3337 SD_BUS_METHOD("CanRebootParameter", NULL, "s", method_can_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED),
3338 SD_BUS_METHOD("SetRebootParameter", "s", NULL, method_set_reboot_parameter, SD_BUS_VTABLE_UNPRIVILEGED),
5bdf2243 3339 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
889f25b2 3340 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
31b221cf
LP
3341 SD_BUS_METHOD("CanRebootToBootLoaderMenu", NULL, "s", method_can_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
3342 SD_BUS_METHOD("SetRebootToBootLoaderMenu", "t", NULL, method_set_reboot_to_boot_loader_menu, SD_BUS_VTABLE_UNPRIVILEGED),
3343 SD_BUS_METHOD("CanRebootToBootLoaderEntry", NULL, "s", method_can_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
3344 SD_BUS_METHOD("SetRebootToBootLoaderEntry", "s", NULL, method_set_reboot_to_boot_loader_entry, SD_BUS_VTABLE_UNPRIVILEGED),
9ef15026 3345 SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
cc377381
LP
3346
3347 SD_BUS_SIGNAL("SessionNew", "so", 0),
3348 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
3349 SD_BUS_SIGNAL("UserNew", "uo", 0),
3350 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
3351 SD_BUS_SIGNAL("SeatNew", "so", 0),
3352 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
3353 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
3354 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
3355
3356 SD_BUS_VTABLE_END
3357};
3f49d45a 3358
99e7e392 3359static int session_jobs_reply(Session *s, const char *unit, const char *result) {
99e7e392
DH
3360 assert(s);
3361 assert(unit);
3362
3363 if (!s->started)
25a1ab4e 3364 return 0;
99e7e392 3365
25a1ab4e 3366 if (result && !streq(result, "done")) {
4afd3348 3367 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
99e7e392 3368
124d7cb2
ZJS
3369 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED,
3370 "Start job for unit '%s' failed with '%s'", unit, result);
25a1ab4e 3371 return session_send_create_reply(s, &e);
99e7e392
DH
3372 }
3373
25a1ab4e 3374 return session_send_create_reply(s, NULL);
99e7e392
DH
3375}
3376
19070062 3377int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
3378 const char *path, *result, *unit;
3379 Manager *m = userdata;
3380 Session *session;
3381 uint32_t id;
3382 User *user;
3383 int r;
3f49d45a 3384
cc377381
LP
3385 assert(message);
3386 assert(m);
3f49d45a 3387
cc377381
LP
3388 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
3389 if (r < 0) {
ebcf1f97 3390 bus_log_parse_error(r);
65d73cf0 3391 return 0;
cc377381 3392 }
3f49d45a 3393
cc377381 3394 if (m->action_job && streq(m->action_job, path)) {
af4efb51 3395 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
3f49d45a 3396
cc377381 3397 /* Tell people that they now may take a lock again */
401e33ed 3398 (void) send_prepare_for(m, m->action_what, false);
3f49d45a 3399
491ac9f2 3400 m->action_job = mfree(m->action_job);
cc377381
LP
3401 m->action_unit = NULL;
3402 m->action_what = 0;
3403 return 0;
3404 }
3f49d45a 3405
cc377381 3406 session = hashmap_get(m->session_units, unit);
25a1ab4e
LP
3407 if (session) {
3408 if (streq_ptr(path, session->scope_job)) {
3409 session->scope_job = mfree(session->scope_job);
3410 (void) session_jobs_reply(session, unit, result);
3411
3412 session_save(session);
3413 user_save(session->user);
3414 }
3f49d45a 3415
cc377381
LP
3416 session_add_to_gc_queue(session);
3417 }
3f49d45a 3418
cc377381 3419 user = hashmap_get(m->user_units, unit);
25a1ab4e
LP
3420 if (user) {
3421 if (streq_ptr(path, user->service_job)) {
491ac9f2 3422 user->service_job = mfree(user->service_job);
3f49d45a 3423
25a1ab4e
LP
3424 LIST_FOREACH(sessions_by_user, session, user->sessions)
3425 (void) session_jobs_reply(session, unit, NULL /* don't propagate user service failures to the client */);
3f49d45a 3426
25a1ab4e
LP
3427 user_save(user);
3428 }
dd9b67aa 3429
cc377381 3430 user_add_to_gc_queue(user);
3f49d45a
LP
3431 }
3432
cc377381 3433 return 0;
3f49d45a
LP
3434}
3435
19070062 3436int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381 3437 const char *path, *unit;
1713813d 3438 Manager *m = userdata;
cc377381
LP
3439 Session *session;
3440 User *user;
3441 int r;
1713813d 3442
1713813d 3443 assert(message);
cc377381 3444 assert(m);
1713813d 3445
cc377381
LP
3446 r = sd_bus_message_read(message, "so", &unit, &path);
3447 if (r < 0) {
ebcf1f97 3448 bus_log_parse_error(r);
65d73cf0 3449 return 0;
cc377381 3450 }
fb6becb4 3451
cc377381
LP
3452 session = hashmap_get(m->session_units, unit);
3453 if (session)
3454 session_add_to_gc_queue(session);
fb6becb4 3455
cc377381
LP
3456 user = hashmap_get(m->user_units, unit);
3457 if (user)
3458 user_add_to_gc_queue(user);
fb6becb4 3459
cc377381
LP
3460 return 0;
3461}
fb6becb4 3462
19070062 3463int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
3464 _cleanup_free_ char *unit = NULL;
3465 Manager *m = userdata;
3466 const char *path;
3467 Session *session;
3468 User *user;
ebcf1f97 3469 int r;
fb6becb4 3470
cc377381
LP
3471 assert(message);
3472 assert(m);
fb6becb4 3473
cc377381
LP
3474 path = sd_bus_message_get_path(message);
3475 if (!path)
3476 return 0;
fb6becb4 3477
ebcf1f97 3478 r = unit_name_from_dbus_path(path, &unit);
e5f5b5b9
LP
3479 if (r == -EINVAL) /* not a unit */
3480 return 0;
65d73cf0
LP
3481 if (r < 0) {
3482 log_oom();
3483 return 0;
3484 }
fb6becb4 3485
cc377381
LP
3486 session = hashmap_get(m->session_units, unit);
3487 if (session)
3488 session_add_to_gc_queue(session);
fb6becb4 3489
cc377381
LP
3490 user = hashmap_get(m->user_units, unit);
3491 if (user)
3492 user_add_to_gc_queue(user);
fb6becb4 3493
cc377381
LP
3494 return 0;
3495}
6fa48533 3496
19070062 3497int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cc377381
LP
3498 Manager *m = userdata;
3499 Session *session;
3500 Iterator i;
3501 int b, r;
943aca8e 3502
19070062
LP
3503 assert(message);
3504 assert(m);
943aca8e 3505
cc377381
LP
3506 r = sd_bus_message_read(message, "b", &b);
3507 if (r < 0) {
ebcf1f97 3508 bus_log_parse_error(r);
65d73cf0 3509 return 0;
cc377381 3510 }
943aca8e 3511
cc377381
LP
3512 if (b)
3513 return 0;
943aca8e 3514
cc377381
LP
3515 /* systemd finished reloading, let's recheck all our sessions */
3516 log_debug("System manager has been reloaded, rechecking sessions...");
6797c324 3517
cc377381
LP
3518 HASHMAP_FOREACH(session, m->sessions, i)
3519 session_add_to_gc_queue(session);
6797c324 3520
cc377381
LP
3521 return 0;
3522}
943aca8e 3523
cc377381
LP
3524int manager_send_changed(Manager *manager, const char *property, ...) {
3525 char **l;
9418f147
LP
3526
3527 assert(manager);
3528
cc377381 3529 l = strv_from_stdarg_alloca(property);
9418f147 3530
cc377381
LP
3531 return sd_bus_emit_properties_changed_strv(
3532 manager->bus,
3533 "/org/freedesktop/login1",
3534 "org.freedesktop.login1.Manager",
3535 l);
9418f147 3536}
eecd1362 3537
2adae5ac
ZJS
3538static int strdup_job(sd_bus_message *reply, char **job) {
3539 const char *j;
3540 char *copy;
3541 int r;
3542
3543 r = sd_bus_message_read(reply, "o", &j);
3544 if (r < 0)
3545 return r;
3546
3547 copy = strdup(j);
3548 if (!copy)
3549 return -ENOMEM;
3550
3551 *job = copy;
3552 return 1;
3553}
3554
fb6becb4
LP
3555int manager_start_scope(
3556 Manager *manager,
3557 const char *scope,
3558 pid_t pid,
3559 const char *slice,
3560 const char *description,
25a1ab4e
LP
3561 char **wants,
3562 char **after,
d5ac9d06 3563 const char *requires_mounts_for,
22f93314 3564 sd_bus_message *more_properties,
cc377381 3565 sd_bus_error *error,
fb6becb4
LP
3566 char **job) {
3567
4afd3348 3568 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
25a1ab4e 3569 char **i;
cc377381 3570 int r;
fb6becb4
LP
3571
3572 assert(manager);
3573 assert(scope);
3574 assert(pid > 1);
2adae5ac 3575 assert(job);
fb6becb4 3576
cc377381
LP
3577 r = sd_bus_message_new_method_call(
3578 manager->bus,
151b9b96 3579 &m,
fb6becb4
LP
3580 "org.freedesktop.systemd1",
3581 "/org/freedesktop/systemd1",
3582 "org.freedesktop.systemd1.Manager",
151b9b96 3583 "StartTransientUnit");
cc377381
LP
3584 if (r < 0)
3585 return r;
fb6becb4 3586
cc377381
LP
3587 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
3588 if (r < 0)
3589 return r;
fb6becb4 3590
cc377381
LP
3591 r = sd_bus_message_open_container(m, 'a', "(sv)");
3592 if (r < 0)
3593 return r;
fb6becb4
LP
3594
3595 if (!isempty(slice)) {
cc377381
LP
3596 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
3597 if (r < 0)
3598 return r;
fb6becb4
LP
3599 }
3600
3601 if (!isempty(description)) {
cc377381
LP
3602 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
3603 if (r < 0)
3604 return r;
fb6becb4
LP
3605 }
3606
25a1ab4e
LP
3607 STRV_FOREACH(i, wants) {
3608 r = sd_bus_message_append(m, "(sv)", "Wants", "as", 1, *i);
cc377381
LP
3609 if (r < 0)
3610 return r;
7fb3ee51
LP
3611 }
3612
25a1ab4e
LP
3613 STRV_FOREACH(i, after) {
3614 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, *i);
ba4c5d93
LP
3615 if (r < 0)
3616 return r;
3617 }
3618
d5ac9d06
LP
3619 if (!empty_or_root(requires_mounts_for)) {
3620 r = sd_bus_message_append(m, "(sv)", "RequiresMountsFor", "as", 1, requires_mounts_for);
3621 if (r < 0)
3622 return r;
3623 }
3624
e743bca2
LP
3625 /* Make sure that the session shells are terminated with SIGHUP since bash and friends tend to ignore
3626 * SIGTERM */
cc377381
LP
3627 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
3628 if (r < 0)
3629 return r;
3630
3631 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
3632 if (r < 0)
3633 return r;
3634
22f93314
JS
3635 /* disable TasksMax= for the session scope, rely on the slice setting for it */
3636 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", (uint64_t)-1);
90558f31 3637 if (r < 0)
22f93314
JS
3638 return bus_log_create_error(r);
3639
3640 if (more_properties) {
3641 /* If TasksMax also appears here, it will overwrite the default value set above */
3642 r = sd_bus_message_copy(m, more_properties, true);
3643 if (r < 0)
3644 return r;
3645 }
90558f31 3646
cc377381
LP
3647 r = sd_bus_message_close_container(m);
3648 if (r < 0)
3649 return r;
86b8d289
LP
3650
3651 r = sd_bus_message_append(m, "a(sa(sv))", 0);
3652 if (r < 0)
3653 return r;
cc377381 3654
c49b30a2 3655 r = sd_bus_call(manager->bus, m, 0, error, &reply);
cc377381
LP
3656 if (r < 0)
3657 return r;
fb6becb4 3658
2adae5ac 3659 return strdup_job(reply, job);
fb6becb4
LP
3660}
3661
cc377381 3662int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
4afd3348 3663 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
fb6becb4
LP
3664 int r;
3665
3666 assert(manager);
3667 assert(unit);
2adae5ac 3668 assert(job);
fb6becb4 3669
cc377381 3670 r = sd_bus_call_method(
fb6becb4
LP
3671 manager->bus,
3672 "org.freedesktop.systemd1",
3673 "/org/freedesktop/systemd1",
3674 "org.freedesktop.systemd1.Manager",
3675 "StartUnit",
fb6becb4 3676 error,
cc377381 3677 &reply,
79ee4ad1 3678 "ss", unit, "replace");
cc377381 3679 if (r < 0)
fb6becb4 3680 return r;
fb6becb4 3681
2adae5ac 3682 return strdup_job(reply, job);
fb6becb4
LP
3683}
3684
cc377381 3685int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
4afd3348 3686 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
fb6becb4
LP
3687 int r;
3688
3689 assert(manager);
3690 assert(unit);
2adae5ac 3691 assert(job);
fb6becb4 3692
cc377381 3693 r = sd_bus_call_method(
fb6becb4
LP
3694 manager->bus,
3695 "org.freedesktop.systemd1",
3696 "/org/freedesktop/systemd1",
3697 "org.freedesktop.systemd1.Manager",
3698 "StopUnit",
fb6becb4 3699 error,
cc377381
LP
3700 &reply,
3701 "ss", unit, "fail");
fb6becb4 3702 if (r < 0) {
cc377381
LP
3703 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3704 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
6797c324 3705
2adae5ac 3706 *job = NULL;
cc377381 3707 sd_bus_error_free(error);
6797c324
LP
3708 return 0;
3709 }
3710
fb6becb4
LP
3711 return r;
3712 }
3713
2adae5ac 3714 return strdup_job(reply, job);
fb6becb4
LP
3715}
3716
ea3a7cf6
LP
3717int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *ret_error) {
3718 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
5f41d1f1
LP
3719 _cleanup_free_ char *path = NULL;
3720 int r;
3721
3722 assert(manager);
3723 assert(scope);
3724
3725 path = unit_dbus_path_from_name(scope);
3726 if (!path)
3727 return -ENOMEM;
3728
3729 r = sd_bus_call_method(
3730 manager->bus,
3731 "org.freedesktop.systemd1",
3732 path,
3733 "org.freedesktop.systemd1.Scope",
3734 "Abandon",
ea3a7cf6 3735 &error,
5f41d1f1
LP
3736 NULL,
3737 NULL);
3738 if (r < 0) {
ea3a7cf6
LP
3739 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3740 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED) ||
3741 sd_bus_error_has_name(&error, BUS_ERROR_SCOPE_NOT_RUNNING))
5f41d1f1 3742 return 0;
5f41d1f1 3743
ea3a7cf6 3744 sd_bus_error_move(ret_error, &error);
5f41d1f1
LP
3745 return r;
3746 }
3747
3748 return 1;
3749}
3750
cc377381 3751int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
fb6becb4
LP
3752 assert(manager);
3753 assert(unit);
3754
cc377381 3755 return sd_bus_call_method(
fb6becb4
LP
3756 manager->bus,
3757 "org.freedesktop.systemd1",
3758 "/org/freedesktop/systemd1",
3759 "org.freedesktop.systemd1.Manager",
3760 "KillUnit",
fb6becb4 3761 error,
cc377381
LP
3762 NULL,
3763 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
fb6becb4
LP
3764}
3765
bd26aee1 3766int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *ret_error) {
4afd3348
LP
3767 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3768 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
fb6becb4 3769 _cleanup_free_ char *path = NULL;
fb6becb4 3770 const char *state;
fb6becb4
LP
3771 int r;
3772
3773 assert(manager);
3774 assert(unit);
3775
fb6becb4
LP
3776 path = unit_dbus_path_from_name(unit);
3777 if (!path)
3778 return -ENOMEM;
3779
cc377381 3780 r = sd_bus_get_property(
fb6becb4
LP
3781 manager->bus,
3782 "org.freedesktop.systemd1",
3783 path,
cc377381
LP
3784 "org.freedesktop.systemd1.Unit",
3785 "ActiveState",
fb6becb4 3786 &error,
cc377381
LP
3787 &reply,
3788 "s");
fb6becb4 3789 if (r < 0) {
ebcf6976 3790 /* systemd might have dropped off momentarily, let's
cc377381
LP
3791 * not make this an error */
3792 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3793 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
6797c324 3794 return true;
6797c324 3795
cc377381
LP
3796 /* If the unit is already unloaded then it's not
3797 * active */
3798 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3799 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
6797c324 3800 return false;
6797c324 3801
bd26aee1 3802 sd_bus_error_move(ret_error, &error);
fb6becb4
LP
3803 return r;
3804 }
3805
cc377381
LP
3806 r = sd_bus_message_read(reply, "s", &state);
3807 if (r < 0)
bd26aee1 3808 return r;
fb6becb4 3809
bd26aee1 3810 return !STR_IN_SET(state, "inactive", "failed");
cc377381
LP
3811}
3812
bd26aee1 3813int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *ret_error) {
4afd3348
LP
3814 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3815 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
cc377381
LP
3816 int r;
3817
3818 assert(manager);
3819 assert(path);
3820
3821 r = sd_bus_get_property(
3822 manager->bus,
3823 "org.freedesktop.systemd1",
3824 path,
3825 "org.freedesktop.systemd1.Job",
3826 "State",
3827 &error,
3828 &reply,
3829 "s");
3830 if (r < 0) {
3831 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3832 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3833 return true;
3834
3835 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3836 return false;
3837
bd26aee1 3838 sd_bus_error_move(ret_error, &error);
cc377381 3839 return r;
fb6becb4
LP
3840 }
3841
cc377381
LP
3842 /* We don't actually care about the state really. The fact
3843 * that we could read the job state is enough for us */
fb6becb4 3844
cc377381 3845 return true;
fb6becb4 3846}