]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/logind-dbus.c
Trivial typo fixes and code refactorings (#5191)
[thirdparty/systemd.git] / src / login / logind-dbus.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2011 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <pwd.h>
22 #include <string.h>
23 #include <unistd.h>
24
25 #include "sd-messages.h"
26
27 #include "alloc-util.h"
28 #include "audit-util.h"
29 #include "bus-common-errors.h"
30 #include "bus-error.h"
31 #include "bus-util.h"
32 #include "dirent-util.h"
33 #include "efivars.h"
34 #include "escape.h"
35 #include "fd-util.h"
36 #include "fileio-label.h"
37 #include "format-util.h"
38 #include "fs-util.h"
39 #include "logind.h"
40 #include "mkdir.h"
41 #include "path-util.h"
42 #include "process-util.h"
43 #include "selinux-util.h"
44 #include "sleep-config.h"
45 #include "special.h"
46 #include "strv.h"
47 #include "terminal-util.h"
48 #include "udev-util.h"
49 #include "unit-name.h"
50 #include "user-util.h"
51 #include "utmp-wtmp.h"
52
53 int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
54 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
55 Session *session;
56 int r;
57
58 assert(m);
59 assert(message);
60 assert(ret);
61
62 if (isempty(name)) {
63 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
64 if (r < 0)
65 return r;
66
67 r = sd_bus_creds_get_session(creds, &name);
68 if (r < 0)
69 return r;
70 }
71
72 session = hashmap_get(m->sessions, name);
73 if (!session)
74 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
75
76 *ret = session;
77 return 0;
78 }
79
80 int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
81 User *user;
82 int r;
83
84 assert(m);
85 assert(message);
86 assert(ret);
87
88 if (uid == UID_INVALID) {
89 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
90
91 /* Note that we get the owner UID of the session, not the actual client UID here! */
92 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
93 if (r < 0)
94 return r;
95
96 r = sd_bus_creds_get_owner_uid(creds, &uid);
97 if (r < 0)
98 return r;
99 }
100
101 user = hashmap_get(m->users, UID_TO_PTR(uid));
102 if (!user)
103 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
104
105 *ret = user;
106 return 0;
107 }
108
109 int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
110 Seat *seat;
111 int r;
112
113 assert(m);
114 assert(message);
115 assert(ret);
116
117 if (isempty(name)) {
118 Session *session;
119
120 r = manager_get_session_from_creds(m, message, NULL, error, &session);
121 if (r < 0)
122 return r;
123
124 seat = session->seat;
125 if (!seat)
126 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
127 } else {
128 seat = hashmap_get(m->seats, name);
129 if (!seat)
130 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
131 }
132
133 *ret = seat;
134 return 0;
135 }
136
137 static int property_get_idle_hint(
138 sd_bus *bus,
139 const char *path,
140 const char *interface,
141 const char *property,
142 sd_bus_message *reply,
143 void *userdata,
144 sd_bus_error *error) {
145
146 Manager *m = userdata;
147
148 assert(bus);
149 assert(reply);
150 assert(m);
151
152 return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
153 }
154
155 static int property_get_idle_since_hint(
156 sd_bus *bus,
157 const char *path,
158 const char *interface,
159 const char *property,
160 sd_bus_message *reply,
161 void *userdata,
162 sd_bus_error *error) {
163
164 Manager *m = userdata;
165 dual_timestamp t = DUAL_TIMESTAMP_NULL;
166
167 assert(bus);
168 assert(reply);
169 assert(m);
170
171 manager_get_idle_hint(m, &t);
172
173 return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
174 }
175
176 static int property_get_inhibited(
177 sd_bus *bus,
178 const char *path,
179 const char *interface,
180 const char *property,
181 sd_bus_message *reply,
182 void *userdata,
183 sd_bus_error *error) {
184
185 Manager *m = userdata;
186 InhibitWhat w;
187
188 assert(bus);
189 assert(reply);
190 assert(m);
191
192 w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
193
194 return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
195 }
196
197 static int property_get_preparing(
198 sd_bus *bus,
199 const char *path,
200 const char *interface,
201 const char *property,
202 sd_bus_message *reply,
203 void *userdata,
204 sd_bus_error *error) {
205
206 Manager *m = userdata;
207 bool b;
208
209 assert(bus);
210 assert(reply);
211 assert(m);
212
213 if (streq(property, "PreparingForShutdown"))
214 b = !!(m->action_what & INHIBIT_SHUTDOWN);
215 else
216 b = !!(m->action_what & INHIBIT_SLEEP);
217
218 return sd_bus_message_append(reply, "b", b);
219 }
220
221 static int property_get_scheduled_shutdown(
222 sd_bus *bus,
223 const char *path,
224 const char *interface,
225 const char *property,
226 sd_bus_message *reply,
227 void *userdata,
228 sd_bus_error *error) {
229
230 Manager *m = userdata;
231 int r;
232
233 assert(bus);
234 assert(reply);
235 assert(m);
236
237 r = sd_bus_message_open_container(reply, 'r', "st");
238 if (r < 0)
239 return r;
240
241 r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
242 if (r < 0)
243 return r;
244
245 return sd_bus_message_close_container(reply);
246 }
247
248 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
249
250 static int property_get_docked(
251 sd_bus *bus,
252 const char *path,
253 const char *interface,
254 const char *property,
255 sd_bus_message *reply,
256 void *userdata,
257 sd_bus_error *error) {
258
259 Manager *m = userdata;
260
261 assert(bus);
262 assert(reply);
263 assert(m);
264
265 return sd_bus_message_append(reply, "b", manager_is_docked_or_external_displays(m));
266 }
267
268 static int property_get_current_sessions(
269 sd_bus *bus,
270 const char *path,
271 const char *interface,
272 const char *property,
273 sd_bus_message *reply,
274 void *userdata,
275 sd_bus_error *error) {
276
277 Manager *m = userdata;
278
279 assert(bus);
280 assert(reply);
281 assert(m);
282
283 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->sessions));
284 }
285
286 static int property_get_current_inhibitors(
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
297 assert(bus);
298 assert(reply);
299 assert(m);
300
301 return sd_bus_message_append(reply, "t", (uint64_t) hashmap_size(m->inhibitors));
302 }
303
304 static int method_get_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
305 _cleanup_free_ char *p = NULL;
306 Manager *m = userdata;
307 const char *name;
308 Session *session;
309 int r;
310
311 assert(message);
312 assert(m);
313
314 r = sd_bus_message_read(message, "s", &name);
315 if (r < 0)
316 return r;
317
318 r = manager_get_session_from_creds(m, message, name, error, &session);
319 if (r < 0)
320 return r;
321
322 p = session_bus_path(session);
323 if (!p)
324 return -ENOMEM;
325
326 return sd_bus_reply_method_return(message, "o", p);
327 }
328
329 static int method_get_session_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
330 _cleanup_free_ char *p = NULL;
331 Session *session = NULL;
332 Manager *m = userdata;
333 pid_t pid;
334 int r;
335
336 assert(message);
337 assert(m);
338
339 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
340
341 r = sd_bus_message_read(message, "u", &pid);
342 if (r < 0)
343 return r;
344 if (pid < 0)
345 return -EINVAL;
346
347 if (pid == 0) {
348 r = manager_get_session_from_creds(m, message, NULL, error, &session);
349 if (r < 0)
350 return r;
351 } else {
352 r = manager_get_session_by_pid(m, pid, &session);
353 if (r < 0)
354 return r;
355
356 if (!session)
357 return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
358 }
359
360 p = session_bus_path(session);
361 if (!p)
362 return -ENOMEM;
363
364 return sd_bus_reply_method_return(message, "o", p);
365 }
366
367 static int method_get_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
368 _cleanup_free_ char *p = NULL;
369 Manager *m = userdata;
370 uint32_t uid;
371 User *user;
372 int r;
373
374 assert(message);
375 assert(m);
376
377 r = sd_bus_message_read(message, "u", &uid);
378 if (r < 0)
379 return r;
380
381 r = manager_get_user_from_creds(m, message, uid, error, &user);
382 if (r < 0)
383 return r;
384
385 p = user_bus_path(user);
386 if (!p)
387 return -ENOMEM;
388
389 return sd_bus_reply_method_return(message, "o", p);
390 }
391
392 static int method_get_user_by_pid(sd_bus_message *message, void *userdata, sd_bus_error *error) {
393 _cleanup_free_ char *p = NULL;
394 Manager *m = userdata;
395 User *user = NULL;
396 pid_t pid;
397 int r;
398
399 assert(message);
400 assert(m);
401
402 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
403
404 r = sd_bus_message_read(message, "u", &pid);
405 if (r < 0)
406 return r;
407 if (pid < 0)
408 return -EINVAL;
409
410 if (pid == 0) {
411 r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
412 if (r < 0)
413 return r;
414 } else {
415 r = manager_get_user_by_pid(m, pid, &user);
416 if (r < 0)
417 return r;
418 if (!user)
419 return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
420 }
421
422 p = user_bus_path(user);
423 if (!p)
424 return -ENOMEM;
425
426 return sd_bus_reply_method_return(message, "o", p);
427 }
428
429 static int method_get_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
430 _cleanup_free_ char *p = NULL;
431 Manager *m = userdata;
432 const char *name;
433 Seat *seat;
434 int r;
435
436 assert(message);
437 assert(m);
438
439 r = sd_bus_message_read(message, "s", &name);
440 if (r < 0)
441 return r;
442
443 r = manager_get_seat_from_creds(m, message, name, error, &seat);
444 if (r < 0)
445 return r;
446
447 p = seat_bus_path(seat);
448 if (!p)
449 return -ENOMEM;
450
451 return sd_bus_reply_method_return(message, "o", p);
452 }
453
454 static int method_list_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
455 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
456 Manager *m = userdata;
457 Session *session;
458 Iterator i;
459 int r;
460
461 assert(message);
462 assert(m);
463
464 r = sd_bus_message_new_method_return(message, &reply);
465 if (r < 0)
466 return r;
467
468 r = sd_bus_message_open_container(reply, 'a', "(susso)");
469 if (r < 0)
470 return r;
471
472 HASHMAP_FOREACH(session, m->sessions, i) {
473 _cleanup_free_ char *p = NULL;
474
475 p = session_bus_path(session);
476 if (!p)
477 return -ENOMEM;
478
479 r = sd_bus_message_append(reply, "(susso)",
480 session->id,
481 (uint32_t) session->user->uid,
482 session->user->name,
483 session->seat ? session->seat->id : "",
484 p);
485 if (r < 0)
486 return r;
487 }
488
489 r = sd_bus_message_close_container(reply);
490 if (r < 0)
491 return r;
492
493 return sd_bus_send(NULL, reply, NULL);
494 }
495
496 static int method_list_users(sd_bus_message *message, void *userdata, sd_bus_error *error) {
497 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
498 Manager *m = userdata;
499 User *user;
500 Iterator i;
501 int r;
502
503 assert(message);
504 assert(m);
505
506 r = sd_bus_message_new_method_return(message, &reply);
507 if (r < 0)
508 return r;
509
510 r = sd_bus_message_open_container(reply, 'a', "(uso)");
511 if (r < 0)
512 return r;
513
514 HASHMAP_FOREACH(user, m->users, i) {
515 _cleanup_free_ char *p = NULL;
516
517 p = user_bus_path(user);
518 if (!p)
519 return -ENOMEM;
520
521 r = sd_bus_message_append(reply, "(uso)",
522 (uint32_t) user->uid,
523 user->name,
524 p);
525 if (r < 0)
526 return r;
527 }
528
529 r = sd_bus_message_close_container(reply);
530 if (r < 0)
531 return r;
532
533 return sd_bus_send(NULL, reply, NULL);
534 }
535
536 static int method_list_seats(sd_bus_message *message, void *userdata, sd_bus_error *error) {
537 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
538 Manager *m = userdata;
539 Seat *seat;
540 Iterator i;
541 int r;
542
543 assert(message);
544 assert(m);
545
546 r = sd_bus_message_new_method_return(message, &reply);
547 if (r < 0)
548 return r;
549
550 r = sd_bus_message_open_container(reply, 'a', "(so)");
551 if (r < 0)
552 return r;
553
554 HASHMAP_FOREACH(seat, m->seats, i) {
555 _cleanup_free_ char *p = NULL;
556
557 p = seat_bus_path(seat);
558 if (!p)
559 return -ENOMEM;
560
561 r = sd_bus_message_append(reply, "(so)", seat->id, p);
562 if (r < 0)
563 return r;
564 }
565
566 r = sd_bus_message_close_container(reply);
567 if (r < 0)
568 return r;
569
570 return sd_bus_send(NULL, reply, NULL);
571 }
572
573 static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bus_error *error) {
574 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
575 Manager *m = userdata;
576 Inhibitor *inhibitor;
577 Iterator i;
578 int r;
579
580 assert(message);
581 assert(m);
582
583 r = sd_bus_message_new_method_return(message, &reply);
584 if (r < 0)
585 return r;
586
587 r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
588 if (r < 0)
589 return r;
590
591 HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
592
593 r = sd_bus_message_append(reply, "(ssssuu)",
594 strempty(inhibit_what_to_string(inhibitor->what)),
595 strempty(inhibitor->who),
596 strempty(inhibitor->why),
597 strempty(inhibit_mode_to_string(inhibitor->mode)),
598 (uint32_t) inhibitor->uid,
599 (uint32_t) inhibitor->pid);
600 if (r < 0)
601 return r;
602 }
603
604 r = sd_bus_message_close_container(reply);
605 if (r < 0)
606 return r;
607
608 return sd_bus_send(NULL, reply, NULL);
609 }
610
611 static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
612 const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
613 uint32_t audit_id = 0;
614 _cleanup_free_ char *id = NULL;
615 Session *session = NULL;
616 Manager *m = userdata;
617 User *user = NULL;
618 Seat *seat = NULL;
619 pid_t leader;
620 uid_t uid;
621 int remote;
622 uint32_t vtnr = 0;
623 SessionType t;
624 SessionClass c;
625 int r;
626
627 assert(message);
628 assert(m);
629
630 assert_cc(sizeof(pid_t) == sizeof(uint32_t));
631 assert_cc(sizeof(uid_t) == sizeof(uint32_t));
632
633 r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
634 if (r < 0)
635 return r;
636
637 if (!uid_is_valid(uid))
638 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
639 if (leader < 0 || leader == 1)
640 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
641
642 if (isempty(type))
643 t = _SESSION_TYPE_INVALID;
644 else {
645 t = session_type_from_string(type);
646 if (t < 0)
647 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
648 }
649
650 if (isempty(class))
651 c = _SESSION_CLASS_INVALID;
652 else {
653 c = session_class_from_string(class);
654 if (c < 0)
655 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
656 }
657
658 if (isempty(desktop))
659 desktop = NULL;
660 else {
661 if (!string_is_safe(desktop))
662 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
663 }
664
665 if (isempty(cseat))
666 seat = NULL;
667 else {
668 seat = hashmap_get(m->seats, cseat);
669 if (!seat)
670 return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
671 }
672
673 if (tty_is_vc(tty)) {
674 int v;
675
676 if (!seat)
677 seat = m->seat0;
678 else if (seat != m->seat0)
679 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
680
681 v = vtnr_from_tty(tty);
682 if (v <= 0)
683 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
684
685 if (!vtnr)
686 vtnr = (uint32_t) v;
687 else if (vtnr != (uint32_t) v)
688 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
689
690 } else if (tty_is_console(tty)) {
691
692 if (!seat)
693 seat = m->seat0;
694 else if (seat != m->seat0)
695 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
696
697 if (vtnr != 0)
698 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
699 }
700
701 if (seat) {
702 if (seat_has_vts(seat)) {
703 if (!vtnr || vtnr > 63)
704 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
705 } else {
706 if (vtnr != 0)
707 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
708 }
709 }
710
711 r = sd_bus_message_enter_container(message, 'a', "(sv)");
712 if (r < 0)
713 return r;
714
715 if (t == _SESSION_TYPE_INVALID) {
716 if (!isempty(display))
717 t = SESSION_X11;
718 else if (!isempty(tty))
719 t = SESSION_TTY;
720 else
721 t = SESSION_UNSPECIFIED;
722 }
723
724 if (c == _SESSION_CLASS_INVALID) {
725 if (t == SESSION_UNSPECIFIED)
726 c = SESSION_BACKGROUND;
727 else
728 c = SESSION_USER;
729 }
730
731 if (leader == 0) {
732 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
733
734 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
735 if (r < 0)
736 return r;
737
738 r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
739 if (r < 0)
740 return r;
741 }
742
743 r = manager_get_session_by_pid(m, leader, NULL);
744 if (r > 0)
745 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session");
746
747 /*
748 * Old gdm and lightdm start the user-session on the same VT as
749 * the greeter session. But they destroy the greeter session
750 * after the user-session and want the user-session to take
751 * over the VT. We need to support this for
752 * backwards-compatibility, so make sure we allow new sessions
753 * on a VT that a greeter is running on. Furthermore, to allow
754 * re-logins, we have to allow a greeter to take over a used VT for
755 * the exact same reasons.
756 */
757 if (c != SESSION_GREETER &&
758 vtnr > 0 &&
759 vtnr < m->seat0->position_count &&
760 m->seat0->positions[vtnr] &&
761 m->seat0->positions[vtnr]->class != SESSION_GREETER)
762 return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already occupied by a session");
763
764 if (hashmap_size(m->sessions) >= m->sessions_max)
765 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.", m->sessions_max);
766
767 audit_session_from_pid(leader, &audit_id);
768 if (audit_id > 0) {
769 /* Keep our session IDs and the audit session IDs in sync */
770
771 if (asprintf(&id, "%"PRIu32, audit_id) < 0)
772 return -ENOMEM;
773
774 /* Wut? There's already a session by this name and we
775 * didn't find it above? Weird, then let's not trust
776 * the audit data and let's better register a new
777 * ID */
778 if (hashmap_get(m->sessions, id)) {
779 log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
780 audit_id = 0;
781
782 id = mfree(id);
783 }
784 }
785
786 if (!id) {
787 do {
788 id = mfree(id);
789
790 if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
791 return -ENOMEM;
792
793 } while (hashmap_get(m->sessions, id));
794 }
795
796 r = manager_add_user_by_uid(m, uid, &user);
797 if (r < 0)
798 goto fail;
799
800 r = manager_add_session(m, id, &session);
801 if (r < 0)
802 goto fail;
803
804 session_set_user(session, user);
805
806 session->leader = leader;
807 session->audit_id = audit_id;
808 session->type = t;
809 session->class = c;
810 session->remote = remote;
811 session->vtnr = vtnr;
812
813 if (!isempty(tty)) {
814 session->tty = strdup(tty);
815 if (!session->tty) {
816 r = -ENOMEM;
817 goto fail;
818 }
819 }
820
821 if (!isempty(display)) {
822 session->display = strdup(display);
823 if (!session->display) {
824 r = -ENOMEM;
825 goto fail;
826 }
827 }
828
829 if (!isempty(remote_user)) {
830 session->remote_user = strdup(remote_user);
831 if (!session->remote_user) {
832 r = -ENOMEM;
833 goto fail;
834 }
835 }
836
837 if (!isempty(remote_host)) {
838 session->remote_host = strdup(remote_host);
839 if (!session->remote_host) {
840 r = -ENOMEM;
841 goto fail;
842 }
843 }
844
845 if (!isempty(service)) {
846 session->service = strdup(service);
847 if (!session->service) {
848 r = -ENOMEM;
849 goto fail;
850 }
851 }
852
853 if (!isempty(desktop)) {
854 session->desktop = strdup(desktop);
855 if (!session->desktop) {
856 r = -ENOMEM;
857 goto fail;
858 }
859 }
860
861 if (seat) {
862 r = seat_attach_session(seat, session);
863 if (r < 0)
864 goto fail;
865 }
866
867 r = session_start(session);
868 if (r < 0)
869 goto fail;
870
871 session->create_message = sd_bus_message_ref(message);
872
873 /* Now, let's wait until the slice unit and stuff got
874 * created. We send the reply back from
875 * session_send_create_reply(). */
876
877 return 1;
878
879 fail:
880 if (session)
881 session_add_to_gc_queue(session);
882
883 if (user)
884 user_add_to_gc_queue(user);
885
886 return r;
887 }
888
889 static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
890 Manager *m = userdata;
891 Session *session;
892 const char *name;
893 int r;
894
895 assert(message);
896 assert(m);
897
898 r = sd_bus_message_read(message, "s", &name);
899 if (r < 0)
900 return r;
901
902 r = manager_get_session_from_creds(m, message, name, error, &session);
903 if (r < 0)
904 return r;
905
906 r = session_release(session);
907 if (r < 0)
908 return r;
909
910 return sd_bus_reply_method_return(message, NULL);
911 }
912
913 static int method_activate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
914 Manager *m = userdata;
915 Session *session;
916 const char *name;
917 int r;
918
919 assert(message);
920 assert(m);
921
922 r = sd_bus_message_read(message, "s", &name);
923 if (r < 0)
924 return r;
925
926 r = manager_get_session_from_creds(m, message, name, error, &session);
927 if (r < 0)
928 return r;
929
930 return bus_session_method_activate(message, session, error);
931 }
932
933 static int method_activate_session_on_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
934 const char *session_name, *seat_name;
935 Manager *m = userdata;
936 Session *session;
937 Seat *seat;
938 int r;
939
940 assert(message);
941 assert(m);
942
943 /* Same as ActivateSession() but refuses to work if
944 * the seat doesn't match */
945
946 r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
947 if (r < 0)
948 return r;
949
950 r = manager_get_session_from_creds(m, message, session_name, error, &session);
951 if (r < 0)
952 return r;
953
954 r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
955 if (r < 0)
956 return r;
957
958 if (session->seat != seat)
959 return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
960
961 r = session_activate(session);
962 if (r < 0)
963 return r;
964
965 return sd_bus_reply_method_return(message, NULL);
966 }
967
968 static int method_lock_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
969 Manager *m = userdata;
970 Session *session;
971 const char *name;
972 int r;
973
974 assert(message);
975 assert(m);
976
977 r = sd_bus_message_read(message, "s", &name);
978 if (r < 0)
979 return r;
980
981 r = manager_get_session_from_creds(m, message, name, error, &session);
982 if (r < 0)
983 return r;
984
985 return bus_session_method_lock(message, session, error);
986 }
987
988 static int method_lock_sessions(sd_bus_message *message, void *userdata, sd_bus_error *error) {
989 Manager *m = userdata;
990 int r;
991
992 assert(message);
993 assert(m);
994
995 r = bus_verify_polkit_async(
996 message,
997 CAP_SYS_ADMIN,
998 "org.freedesktop.login1.lock-sessions",
999 NULL,
1000 false,
1001 UID_INVALID,
1002 &m->polkit_registry,
1003 error);
1004 if (r < 0)
1005 return r;
1006 if (r == 0)
1007 return 1; /* Will call us back */
1008
1009 r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
1010 if (r < 0)
1011 return r;
1012
1013 return sd_bus_reply_method_return(message, NULL);
1014 }
1015
1016 static int method_kill_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1017 const char *name;
1018 Manager *m = userdata;
1019 Session *session;
1020 int r;
1021
1022 assert(message);
1023 assert(m);
1024
1025 r = sd_bus_message_read(message, "s", &name);
1026 if (r < 0)
1027 return r;
1028
1029 r = manager_get_session_from_creds(m, message, name, error, &session);
1030 if (r < 0)
1031 return r;
1032
1033 return bus_session_method_kill(message, session, error);
1034 }
1035
1036 static int method_kill_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1037 Manager *m = userdata;
1038 uint32_t uid;
1039 User *user;
1040 int r;
1041
1042 assert(message);
1043 assert(m);
1044
1045 r = sd_bus_message_read(message, "u", &uid);
1046 if (r < 0)
1047 return r;
1048
1049 r = manager_get_user_from_creds(m, message, uid, error, &user);
1050 if (r < 0)
1051 return r;
1052
1053 return bus_user_method_kill(message, user, error);
1054 }
1055
1056 static int method_terminate_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1057 Manager *m = userdata;
1058 const char *name;
1059 Session *session;
1060 int r;
1061
1062 assert(message);
1063 assert(m);
1064
1065 r = sd_bus_message_read(message, "s", &name);
1066 if (r < 0)
1067 return r;
1068
1069 r = manager_get_session_from_creds(m, message, name, error, &session);
1070 if (r < 0)
1071 return r;
1072
1073 return bus_session_method_terminate(message, session, error);
1074 }
1075
1076 static int method_terminate_user(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1077 Manager *m = userdata;
1078 uint32_t uid;
1079 User *user;
1080 int r;
1081
1082 assert(message);
1083 assert(m);
1084
1085 r = sd_bus_message_read(message, "u", &uid);
1086 if (r < 0)
1087 return r;
1088
1089 r = manager_get_user_from_creds(m, message, uid, error, &user);
1090 if (r < 0)
1091 return r;
1092
1093 return bus_user_method_terminate(message, user, error);
1094 }
1095
1096 static int method_terminate_seat(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1097 Manager *m = userdata;
1098 const char *name;
1099 Seat *seat;
1100 int r;
1101
1102 assert(message);
1103 assert(m);
1104
1105 r = sd_bus_message_read(message, "s", &name);
1106 if (r < 0)
1107 return r;
1108
1109 r = manager_get_seat_from_creds(m, message, name, error, &seat);
1110 if (r < 0)
1111 return r;
1112
1113 return bus_seat_method_terminate(message, seat, error);
1114 }
1115
1116 static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1117 _cleanup_free_ char *cc = NULL;
1118 Manager *m = userdata;
1119 int r, b, interactive;
1120 struct passwd *pw;
1121 const char *path;
1122 uint32_t uid;
1123 bool self = false;
1124
1125 assert(message);
1126 assert(m);
1127
1128 r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
1129 if (r < 0)
1130 return r;
1131
1132 if (uid == UID_INVALID) {
1133 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1134
1135 /* Note that we get the owner UID of the session, not the actual client UID here! */
1136 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
1137 if (r < 0)
1138 return r;
1139
1140 r = sd_bus_creds_get_owner_uid(creds, &uid);
1141 if (r < 0)
1142 return r;
1143
1144 self = true;
1145
1146 } else if (!uid_is_valid(uid))
1147 return -EINVAL;
1148
1149 errno = 0;
1150 pw = getpwuid(uid);
1151 if (!pw)
1152 return errno > 0 ? -errno : -ENOENT;
1153
1154 r = bus_verify_polkit_async(
1155 message,
1156 CAP_SYS_ADMIN,
1157 self ? "org.freedesktop.login1.set-self-linger" : "org.freedesktop.login1.set-user-linger",
1158 NULL,
1159 interactive,
1160 UID_INVALID,
1161 &m->polkit_registry,
1162 error);
1163 if (r < 0)
1164 return r;
1165 if (r == 0)
1166 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1167
1168 mkdir_p_label("/var/lib/systemd", 0755);
1169
1170 r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
1171 if (r < 0)
1172 return r;
1173
1174 cc = cescape(pw->pw_name);
1175 if (!cc)
1176 return -ENOMEM;
1177
1178 path = strjoina("/var/lib/systemd/linger/", cc);
1179 if (b) {
1180 User *u;
1181
1182 r = touch(path);
1183 if (r < 0)
1184 return r;
1185
1186 if (manager_add_user_by_uid(m, uid, &u) >= 0)
1187 user_start(u);
1188
1189 } else {
1190 User *u;
1191
1192 r = unlink(path);
1193 if (r < 0 && errno != ENOENT)
1194 return -errno;
1195
1196 u = hashmap_get(m->users, UID_TO_PTR(uid));
1197 if (u)
1198 user_add_to_gc_queue(u);
1199 }
1200
1201 return sd_bus_reply_method_return(message, NULL);
1202 }
1203
1204 static int trigger_device(Manager *m, struct udev_device *d) {
1205 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
1206 struct udev_list_entry *first, *item;
1207 int r;
1208
1209 assert(m);
1210
1211 e = udev_enumerate_new(m->udev);
1212 if (!e)
1213 return -ENOMEM;
1214
1215 if (d) {
1216 r = udev_enumerate_add_match_parent(e, d);
1217 if (r < 0)
1218 return r;
1219 }
1220
1221 r = udev_enumerate_scan_devices(e);
1222 if (r < 0)
1223 return r;
1224
1225 first = udev_enumerate_get_list_entry(e);
1226 udev_list_entry_foreach(item, first) {
1227 _cleanup_free_ char *t = NULL;
1228 const char *p;
1229
1230 p = udev_list_entry_get_name(item);
1231
1232 t = strappend(p, "/uevent");
1233 if (!t)
1234 return -ENOMEM;
1235
1236 write_string_file(t, "change", WRITE_STRING_FILE_CREATE);
1237 }
1238
1239 return 0;
1240 }
1241
1242 static int attach_device(Manager *m, const char *seat, const char *sysfs) {
1243 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
1244 _cleanup_free_ char *rule = NULL, *file = NULL;
1245 const char *id_for_seat;
1246 int r;
1247
1248 assert(m);
1249 assert(seat);
1250 assert(sysfs);
1251
1252 d = udev_device_new_from_syspath(m->udev, sysfs);
1253 if (!d)
1254 return -ENODEV;
1255
1256 if (!udev_device_has_tag(d, "seat"))
1257 return -ENODEV;
1258
1259 id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
1260 if (!id_for_seat)
1261 return -ENODEV;
1262
1263 if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
1264 return -ENOMEM;
1265
1266 if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
1267 return -ENOMEM;
1268
1269 mkdir_p_label("/etc/udev/rules.d", 0755);
1270 r = write_string_file_atomic_label(file, rule);
1271 if (r < 0)
1272 return r;
1273
1274 return trigger_device(m, d);
1275 }
1276
1277 static int flush_devices(Manager *m) {
1278 _cleanup_closedir_ DIR *d;
1279
1280 assert(m);
1281
1282 d = opendir("/etc/udev/rules.d");
1283 if (!d) {
1284 if (errno != ENOENT)
1285 log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
1286 } else {
1287 struct dirent *de;
1288
1289 FOREACH_DIRENT_ALL(de, d, break) {
1290 if (!dirent_is_file(de))
1291 continue;
1292
1293 if (!startswith(de->d_name, "72-seat-"))
1294 continue;
1295
1296 if (!endswith(de->d_name, ".rules"))
1297 continue;
1298
1299 if (unlinkat(dirfd(d), de->d_name, 0) < 0)
1300 log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
1301 }
1302 }
1303
1304 return trigger_device(m, NULL);
1305 }
1306
1307 static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1308 const char *sysfs, *seat;
1309 Manager *m = userdata;
1310 int interactive, r;
1311
1312 assert(message);
1313 assert(m);
1314
1315 r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
1316 if (r < 0)
1317 return r;
1318
1319 if (!path_startswith(sysfs, "/sys"))
1320 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
1321
1322 if (!seat_name_is_valid(seat))
1323 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
1324
1325 r = bus_verify_polkit_async(
1326 message,
1327 CAP_SYS_ADMIN,
1328 "org.freedesktop.login1.attach-device",
1329 NULL,
1330 interactive,
1331 UID_INVALID,
1332 &m->polkit_registry,
1333 error);
1334 if (r < 0)
1335 return r;
1336 if (r == 0)
1337 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1338
1339 r = attach_device(m, seat, sysfs);
1340 if (r < 0)
1341 return r;
1342
1343 return sd_bus_reply_method_return(message, NULL);
1344 }
1345
1346 static int method_flush_devices(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1347 Manager *m = userdata;
1348 int interactive, r;
1349
1350 assert(message);
1351 assert(m);
1352
1353 r = sd_bus_message_read(message, "b", &interactive);
1354 if (r < 0)
1355 return r;
1356
1357 r = bus_verify_polkit_async(
1358 message,
1359 CAP_SYS_ADMIN,
1360 "org.freedesktop.login1.flush-devices",
1361 NULL,
1362 interactive,
1363 UID_INVALID,
1364 &m->polkit_registry,
1365 error);
1366 if (r < 0)
1367 return r;
1368 if (r == 0)
1369 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1370
1371 r = flush_devices(m);
1372 if (r < 0)
1373 return r;
1374
1375 return sd_bus_reply_method_return(message, NULL);
1376 }
1377
1378 static int have_multiple_sessions(
1379 Manager *m,
1380 uid_t uid) {
1381
1382 Session *session;
1383 Iterator i;
1384
1385 assert(m);
1386
1387 /* Check for other users' sessions. Greeter sessions do not
1388 * count, and non-login sessions do not count either. */
1389 HASHMAP_FOREACH(session, m->sessions, i)
1390 if (session->class == SESSION_USER &&
1391 session->user->uid != uid)
1392 return true;
1393
1394 return false;
1395 }
1396
1397 static int bus_manager_log_shutdown(
1398 Manager *m,
1399 InhibitWhat w,
1400 const char *unit_name) {
1401
1402 const char *p, *q;
1403
1404 assert(m);
1405 assert(unit_name);
1406
1407 if (w != INHIBIT_SHUTDOWN)
1408 return 0;
1409
1410 if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
1411 p = "MESSAGE=System is powering down";
1412 q = "SHUTDOWN=power-off";
1413 } else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
1414 p = "MESSAGE=System is halting";
1415 q = "SHUTDOWN=halt";
1416 } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
1417 p = "MESSAGE=System is rebooting";
1418 q = "SHUTDOWN=reboot";
1419 } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
1420 p = "MESSAGE=System is rebooting with kexec";
1421 q = "SHUTDOWN=kexec";
1422 } else {
1423 p = "MESSAGE=System is shutting down";
1424 q = NULL;
1425 }
1426
1427 if (isempty(m->wall_message))
1428 p = strjoina(p, ".");
1429 else
1430 p = strjoina(p, " (", m->wall_message, ").");
1431
1432 return log_struct(LOG_NOTICE,
1433 LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
1434 p,
1435 q,
1436 NULL);
1437 }
1438
1439 static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
1440 Manager *m = userdata;
1441
1442 assert(e);
1443 assert(m);
1444
1445 m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
1446 return 0;
1447 }
1448
1449 int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
1450 int r;
1451
1452 assert(m);
1453
1454 if (until <= now(CLOCK_MONOTONIC))
1455 return 0;
1456
1457 /* We want to ignore the lid switch for a while after each
1458 * suspend, and after boot-up. Hence let's install a timer for
1459 * this. As long as the event source exists we ignore the lid
1460 * switch. */
1461
1462 if (m->lid_switch_ignore_event_source) {
1463 usec_t u;
1464
1465 r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
1466 if (r < 0)
1467 return r;
1468
1469 if (until <= u)
1470 return 0;
1471
1472 r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
1473 } else
1474 r = sd_event_add_time(
1475 m->event,
1476 &m->lid_switch_ignore_event_source,
1477 CLOCK_MONOTONIC,
1478 until, 0,
1479 lid_switch_ignore_handler, m);
1480
1481 return r;
1482 }
1483
1484 static void reset_scheduled_shutdown(Manager *m) {
1485 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
1486 m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
1487 m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
1488 m->scheduled_shutdown_type = mfree(m->scheduled_shutdown_type);
1489 m->scheduled_shutdown_timeout = 0;
1490 m->shutdown_dry_run = false;
1491
1492 if (m->unlink_nologin) {
1493 (void) unlink("/run/nologin");
1494 m->unlink_nologin = false;
1495 }
1496 }
1497
1498 static int execute_shutdown_or_sleep(
1499 Manager *m,
1500 InhibitWhat w,
1501 const char *unit_name,
1502 sd_bus_error *error) {
1503
1504 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1505 char *c = NULL;
1506 const char *p;
1507 int r;
1508
1509 assert(m);
1510 assert(w >= 0);
1511 assert(w < _INHIBIT_WHAT_MAX);
1512 assert(unit_name);
1513
1514 bus_manager_log_shutdown(m, w, unit_name);
1515
1516 if (m->shutdown_dry_run) {
1517 log_info("Running in dry run, suppressing action.");
1518 reset_scheduled_shutdown(m);
1519 } else {
1520 r = sd_bus_call_method(
1521 m->bus,
1522 "org.freedesktop.systemd1",
1523 "/org/freedesktop/systemd1",
1524 "org.freedesktop.systemd1.Manager",
1525 "StartUnit",
1526 error,
1527 &reply,
1528 "ss", unit_name, "replace-irreversibly");
1529 if (r < 0)
1530 return r;
1531
1532 r = sd_bus_message_read(reply, "o", &p);
1533 if (r < 0)
1534 return r;
1535
1536 c = strdup(p);
1537 if (!c)
1538 return -ENOMEM;
1539 }
1540
1541 m->action_unit = unit_name;
1542 free(m->action_job);
1543 m->action_job = c;
1544 m->action_what = w;
1545
1546 /* Make sure the lid switch is ignored for a while */
1547 manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
1548
1549 return 0;
1550 }
1551
1552 int manager_dispatch_delayed(Manager *manager, bool timeout) {
1553
1554 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1555 Inhibitor *offending = NULL;
1556 int r;
1557
1558 assert(manager);
1559
1560 if (manager->action_what == 0 || manager->action_job)
1561 return 0;
1562
1563 if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
1564 _cleanup_free_ char *comm = NULL, *u = NULL;
1565
1566 if (!timeout)
1567 return 0;
1568
1569 (void) get_process_comm(offending->pid, &comm);
1570 u = uid_to_name(offending->uid);
1571
1572 log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
1573 offending->uid, strna(u),
1574 offending->pid, strna(comm));
1575 }
1576
1577 /* Actually do the operation */
1578 r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
1579 if (r < 0) {
1580 log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
1581
1582 manager->action_unit = NULL;
1583 manager->action_what = 0;
1584 return r;
1585 }
1586
1587 return 1;
1588 }
1589
1590 static int manager_inhibit_timeout_handler(
1591 sd_event_source *s,
1592 uint64_t usec,
1593 void *userdata) {
1594
1595 Manager *manager = userdata;
1596 int r;
1597
1598 assert(manager);
1599 assert(manager->inhibit_timeout_source == s);
1600
1601 r = manager_dispatch_delayed(manager, true);
1602 return (r < 0) ? r : 0;
1603 }
1604
1605 static int delay_shutdown_or_sleep(
1606 Manager *m,
1607 InhibitWhat w,
1608 const char *unit_name) {
1609
1610 int r;
1611 usec_t timeout_val;
1612
1613 assert(m);
1614 assert(w >= 0);
1615 assert(w < _INHIBIT_WHAT_MAX);
1616 assert(unit_name);
1617
1618 timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
1619
1620 if (m->inhibit_timeout_source) {
1621 r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
1622 if (r < 0)
1623 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1624
1625 r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
1626 if (r < 0)
1627 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
1628 } else {
1629 r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
1630 timeout_val, 0, manager_inhibit_timeout_handler, m);
1631 if (r < 0)
1632 return r;
1633 }
1634
1635 m->action_unit = unit_name;
1636 m->action_what = w;
1637
1638 return 0;
1639 }
1640
1641 static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
1642
1643 static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
1644 [INHIBIT_SHUTDOWN] = "PrepareForShutdown",
1645 [INHIBIT_SLEEP] = "PrepareForSleep"
1646 };
1647
1648 int active = _active;
1649
1650 assert(m);
1651 assert(w >= 0);
1652 assert(w < _INHIBIT_WHAT_MAX);
1653 assert(signal_name[w]);
1654
1655 return sd_bus_emit_signal(m->bus,
1656 "/org/freedesktop/login1",
1657 "org.freedesktop.login1.Manager",
1658 signal_name[w],
1659 "b",
1660 active);
1661 }
1662
1663 int bus_manager_shutdown_or_sleep_now_or_later(
1664 Manager *m,
1665 const char *unit_name,
1666 InhibitWhat w,
1667 sd_bus_error *error) {
1668
1669 bool delayed;
1670 int r;
1671
1672 assert(m);
1673 assert(unit_name);
1674 assert(w >= 0);
1675 assert(w <= _INHIBIT_WHAT_MAX);
1676 assert(!m->action_job);
1677
1678 /* Tell everybody to prepare for shutdown/sleep */
1679 send_prepare_for(m, w, true);
1680
1681 delayed =
1682 m->inhibit_delay_max > 0 &&
1683 manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
1684
1685 if (delayed)
1686 /* Shutdown is delayed, keep in mind what we
1687 * want to do, and start a timeout */
1688 r = delay_shutdown_or_sleep(m, w, unit_name);
1689 else
1690 /* Shutdown is not delayed, execute it
1691 * immediately */
1692 r = execute_shutdown_or_sleep(m, w, unit_name, error);
1693
1694 return r;
1695 }
1696
1697 static int verify_shutdown_creds(
1698 Manager *m,
1699 sd_bus_message *message,
1700 InhibitWhat w,
1701 bool interactive,
1702 const char *action,
1703 const char *action_multiple_sessions,
1704 const char *action_ignore_inhibit,
1705 sd_bus_error *error) {
1706
1707 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1708 bool multiple_sessions, blocked;
1709 uid_t uid;
1710 int r;
1711
1712 assert(m);
1713 assert(message);
1714 assert(w >= 0);
1715 assert(w <= _INHIBIT_WHAT_MAX);
1716
1717 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
1718 if (r < 0)
1719 return r;
1720
1721 r = sd_bus_creds_get_euid(creds, &uid);
1722 if (r < 0)
1723 return r;
1724
1725 r = have_multiple_sessions(m, uid);
1726 if (r < 0)
1727 return r;
1728
1729 multiple_sessions = r > 0;
1730 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
1731
1732 if (multiple_sessions && action_multiple_sessions) {
1733 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1734 if (r < 0)
1735 return r;
1736 if (r == 0)
1737 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1738 }
1739
1740 if (blocked && action_ignore_inhibit) {
1741 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1742 if (r < 0)
1743 return r;
1744 if (r == 0)
1745 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1746 }
1747
1748 if (!multiple_sessions && !blocked && action) {
1749 r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, NULL, interactive, UID_INVALID, &m->polkit_registry, error);
1750 if (r < 0)
1751 return r;
1752 if (r == 0)
1753 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
1754 }
1755
1756 return 0;
1757 }
1758
1759 static int method_do_shutdown_or_sleep(
1760 Manager *m,
1761 sd_bus_message *message,
1762 const char *unit_name,
1763 InhibitWhat w,
1764 const char *action,
1765 const char *action_multiple_sessions,
1766 const char *action_ignore_inhibit,
1767 const char *sleep_verb,
1768 sd_bus_error *error) {
1769
1770 int interactive, r;
1771
1772 assert(m);
1773 assert(message);
1774 assert(unit_name);
1775 assert(w >= 0);
1776 assert(w <= _INHIBIT_WHAT_MAX);
1777
1778 r = sd_bus_message_read(message, "b", &interactive);
1779 if (r < 0)
1780 return r;
1781
1782 /* Don't allow multiple jobs being executed at the same time */
1783 if (m->action_what)
1784 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
1785
1786 if (sleep_verb) {
1787 r = can_sleep(sleep_verb);
1788 if (r < 0)
1789 return r;
1790
1791 if (r == 0)
1792 return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
1793 }
1794
1795 r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
1796 action_ignore_inhibit, error);
1797 if (r != 0)
1798 return r;
1799
1800 r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
1801 if (r < 0)
1802 return r;
1803
1804 return sd_bus_reply_method_return(message, NULL);
1805 }
1806
1807 static int method_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1808 Manager *m = userdata;
1809
1810 return method_do_shutdown_or_sleep(
1811 m, message,
1812 SPECIAL_POWEROFF_TARGET,
1813 INHIBIT_SHUTDOWN,
1814 "org.freedesktop.login1.power-off",
1815 "org.freedesktop.login1.power-off-multiple-sessions",
1816 "org.freedesktop.login1.power-off-ignore-inhibit",
1817 NULL,
1818 error);
1819 }
1820
1821 static int method_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1822 Manager *m = userdata;
1823
1824 return method_do_shutdown_or_sleep(
1825 m, message,
1826 SPECIAL_REBOOT_TARGET,
1827 INHIBIT_SHUTDOWN,
1828 "org.freedesktop.login1.reboot",
1829 "org.freedesktop.login1.reboot-multiple-sessions",
1830 "org.freedesktop.login1.reboot-ignore-inhibit",
1831 NULL,
1832 error);
1833 }
1834
1835 static int method_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1836 Manager *m = userdata;
1837
1838 return method_do_shutdown_or_sleep(
1839 m, message,
1840 SPECIAL_SUSPEND_TARGET,
1841 INHIBIT_SLEEP,
1842 "org.freedesktop.login1.suspend",
1843 "org.freedesktop.login1.suspend-multiple-sessions",
1844 "org.freedesktop.login1.suspend-ignore-inhibit",
1845 "suspend",
1846 error);
1847 }
1848
1849 static int nologin_timeout_handler(
1850 sd_event_source *s,
1851 uint64_t usec,
1852 void *userdata) {
1853
1854 Manager *m = userdata;
1855 int r;
1856
1857 log_info("Creating /run/nologin, blocking further logins...");
1858
1859 r = write_string_file_atomic_label("/run/nologin", "System is going down.");
1860 if (r < 0)
1861 log_error_errno(r, "Failed to create /run/nologin: %m");
1862 else
1863 m->unlink_nologin = true;
1864
1865 return 0;
1866 }
1867
1868 static int update_schedule_file(Manager *m) {
1869 _cleanup_free_ char *temp_path = NULL;
1870 _cleanup_fclose_ FILE *f = NULL;
1871 int r;
1872
1873 assert(m);
1874
1875 r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
1876 if (r < 0)
1877 return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
1878
1879 r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
1880 if (r < 0)
1881 return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
1882
1883 (void) fchmod(fileno(f), 0644);
1884
1885 fprintf(f,
1886 "USEC="USEC_FMT"\n"
1887 "WARN_WALL=%i\n"
1888 "MODE=%s\n",
1889 m->scheduled_shutdown_timeout,
1890 m->enable_wall_messages,
1891 m->scheduled_shutdown_type);
1892
1893 if (!isempty(m->wall_message)) {
1894 _cleanup_free_ char *t;
1895
1896 t = cescape(m->wall_message);
1897 if (!t) {
1898 r = -ENOMEM;
1899 goto fail;
1900 }
1901
1902 fprintf(f, "WALL_MESSAGE=%s\n", t);
1903 }
1904
1905 r = fflush_and_check(f);
1906 if (r < 0)
1907 goto fail;
1908
1909 if (rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
1910 r = -errno;
1911 goto fail;
1912 }
1913
1914 return 0;
1915
1916 fail:
1917 (void) unlink(temp_path);
1918 (void) unlink("/run/systemd/shutdown/scheduled");
1919
1920 return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m");
1921 }
1922
1923 static int manager_scheduled_shutdown_handler(
1924 sd_event_source *s,
1925 uint64_t usec,
1926 void *userdata) {
1927
1928 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1929 Manager *m = userdata;
1930 const char *target;
1931 int r;
1932
1933 assert(m);
1934
1935 if (isempty(m->scheduled_shutdown_type))
1936 return 0;
1937
1938 if (streq(m->scheduled_shutdown_type, "halt"))
1939 target = SPECIAL_HALT_TARGET;
1940 else if (streq(m->scheduled_shutdown_type, "poweroff"))
1941 target = SPECIAL_POWEROFF_TARGET;
1942 else
1943 target = SPECIAL_REBOOT_TARGET;
1944
1945 r = execute_shutdown_or_sleep(m, 0, target, &error);
1946 if (r < 0)
1947 return log_error_errno(r, "Unable to execute transition to %s: %m", target);
1948
1949 return 0;
1950 }
1951
1952 static int method_schedule_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1953 Manager *m = userdata;
1954 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1955 const char *action_multiple_sessions = NULL;
1956 const char *action_ignore_inhibit = NULL;
1957 const char *action = NULL;
1958 uint64_t elapse;
1959 char *type;
1960 int r;
1961
1962 assert(m);
1963 assert(message);
1964
1965 r = sd_bus_message_read(message, "st", &type, &elapse);
1966 if (r < 0)
1967 return r;
1968
1969 if (startswith(type, "dry-")) {
1970 type += 4;
1971 m->shutdown_dry_run = true;
1972 }
1973
1974 if (streq(type, "reboot")) {
1975 action = "org.freedesktop.login1.reboot";
1976 action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
1977 action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
1978 } else if (streq(type, "halt")) {
1979 action = "org.freedesktop.login1.halt";
1980 action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
1981 action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
1982 } else if (streq(type, "poweroff")) {
1983 action = "org.freedesktop.login1.power-off";
1984 action_multiple_sessions = "org.freedesktop.login1.power-off-multiple-sessions";
1985 action_ignore_inhibit = "org.freedesktop.login1.power-off-ignore-inhibit";
1986 } else
1987 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
1988
1989 r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
1990 action, action_multiple_sessions, action_ignore_inhibit, error);
1991 if (r != 0)
1992 return r;
1993
1994 if (m->scheduled_shutdown_timeout_source) {
1995 r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
1996 if (r < 0)
1997 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
1998
1999 r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
2000 if (r < 0)
2001 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2002 } else {
2003 r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
2004 CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
2005 if (r < 0)
2006 return log_error_errno(r, "sd_event_add_time() failed: %m");
2007 }
2008
2009 r = free_and_strdup(&m->scheduled_shutdown_type, type);
2010 if (r < 0) {
2011 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2012 return log_oom();
2013 }
2014
2015 if (m->nologin_timeout_source) {
2016 r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
2017 if (r < 0)
2018 return log_error_errno(r, "sd_event_source_set_time() failed: %m");
2019
2020 r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
2021 if (r < 0)
2022 return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
2023 } else {
2024 r = sd_event_add_time(m->event, &m->nologin_timeout_source,
2025 CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
2026 if (r < 0)
2027 return log_error_errno(r, "sd_event_add_time() failed: %m");
2028 }
2029
2030 m->scheduled_shutdown_timeout = elapse;
2031
2032 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2033 if (r >= 0) {
2034 const char *tty = NULL;
2035
2036 (void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
2037 (void) sd_bus_creds_get_tty(creds, &tty);
2038
2039 r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
2040 if (r < 0) {
2041 m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
2042 return log_oom();
2043 }
2044 }
2045
2046 r = manager_setup_wall_message_timer(m);
2047 if (r < 0)
2048 return r;
2049
2050 if (!isempty(type)) {
2051 r = update_schedule_file(m);
2052 if (r < 0)
2053 return r;
2054 } else
2055 (void) unlink("/run/systemd/shutdown/scheduled");
2056
2057 return sd_bus_reply_method_return(message, NULL);
2058 }
2059
2060 static int method_cancel_scheduled_shutdown(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2061 Manager *m = userdata;
2062 bool cancelled;
2063
2064 assert(m);
2065 assert(message);
2066
2067 cancelled = m->scheduled_shutdown_type != NULL;
2068 reset_scheduled_shutdown(m);
2069
2070 if (cancelled) {
2071 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2072 const char *tty = NULL;
2073 uid_t uid = 0;
2074 int r;
2075
2076 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
2077 if (r >= 0) {
2078 (void) sd_bus_creds_get_uid(creds, &uid);
2079 (void) sd_bus_creds_get_tty(creds, &tty);
2080 }
2081
2082 utmp_wall("The system shutdown has been cancelled",
2083 uid_to_name(uid), tty, logind_wall_tty_filter, m);
2084 }
2085
2086 return sd_bus_reply_method_return(message, "b", cancelled);
2087 }
2088
2089 static int method_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2090 Manager *m = userdata;
2091
2092 return method_do_shutdown_or_sleep(
2093 m, message,
2094 SPECIAL_HIBERNATE_TARGET,
2095 INHIBIT_SLEEP,
2096 "org.freedesktop.login1.hibernate",
2097 "org.freedesktop.login1.hibernate-multiple-sessions",
2098 "org.freedesktop.login1.hibernate-ignore-inhibit",
2099 "hibernate",
2100 error);
2101 }
2102
2103 static int method_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2104 Manager *m = userdata;
2105
2106 return method_do_shutdown_or_sleep(
2107 m, message,
2108 SPECIAL_HYBRID_SLEEP_TARGET,
2109 INHIBIT_SLEEP,
2110 "org.freedesktop.login1.hibernate",
2111 "org.freedesktop.login1.hibernate-multiple-sessions",
2112 "org.freedesktop.login1.hibernate-ignore-inhibit",
2113 "hybrid-sleep",
2114 error);
2115 }
2116
2117 static int method_can_shutdown_or_sleep(
2118 Manager *m,
2119 sd_bus_message *message,
2120 InhibitWhat w,
2121 const char *action,
2122 const char *action_multiple_sessions,
2123 const char *action_ignore_inhibit,
2124 const char *sleep_verb,
2125 sd_bus_error *error) {
2126
2127 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2128 bool multiple_sessions, challenge, blocked;
2129 const char *result = NULL;
2130 uid_t uid;
2131 int r;
2132
2133 assert(m);
2134 assert(message);
2135 assert(w >= 0);
2136 assert(w <= _INHIBIT_WHAT_MAX);
2137 assert(action);
2138 assert(action_multiple_sessions);
2139 assert(action_ignore_inhibit);
2140
2141 if (sleep_verb) {
2142 r = can_sleep(sleep_verb);
2143 if (r < 0)
2144 return r;
2145 if (r == 0)
2146 return sd_bus_reply_method_return(message, "s", "na");
2147 }
2148
2149 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
2150 if (r < 0)
2151 return r;
2152
2153 r = sd_bus_creds_get_euid(creds, &uid);
2154 if (r < 0)
2155 return r;
2156
2157 r = have_multiple_sessions(m, uid);
2158 if (r < 0)
2159 return r;
2160
2161 multiple_sessions = r > 0;
2162 blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
2163
2164 if (multiple_sessions) {
2165 r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, NULL, UID_INVALID, &challenge, error);
2166 if (r < 0)
2167 return r;
2168
2169 if (r > 0)
2170 result = "yes";
2171 else if (challenge)
2172 result = "challenge";
2173 else
2174 result = "no";
2175 }
2176
2177 if (blocked) {
2178 r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, NULL, UID_INVALID, &challenge, error);
2179 if (r < 0)
2180 return r;
2181
2182 if (r > 0 && !result)
2183 result = "yes";
2184 else if (challenge && (!result || streq(result, "yes")))
2185 result = "challenge";
2186 else
2187 result = "no";
2188 }
2189
2190 if (!multiple_sessions && !blocked) {
2191 /* If neither inhibit nor multiple sessions
2192 * apply then just check the normal policy */
2193
2194 r = bus_test_polkit(message, CAP_SYS_BOOT, action, NULL, UID_INVALID, &challenge, error);
2195 if (r < 0)
2196 return r;
2197
2198 if (r > 0)
2199 result = "yes";
2200 else if (challenge)
2201 result = "challenge";
2202 else
2203 result = "no";
2204 }
2205
2206 return sd_bus_reply_method_return(message, "s", result);
2207 }
2208
2209 static int method_can_poweroff(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2210 Manager *m = userdata;
2211
2212 return method_can_shutdown_or_sleep(
2213 m, message,
2214 INHIBIT_SHUTDOWN,
2215 "org.freedesktop.login1.power-off",
2216 "org.freedesktop.login1.power-off-multiple-sessions",
2217 "org.freedesktop.login1.power-off-ignore-inhibit",
2218 NULL,
2219 error);
2220 }
2221
2222 static int method_can_reboot(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2223 Manager *m = userdata;
2224
2225 return method_can_shutdown_or_sleep(
2226 m, message,
2227 INHIBIT_SHUTDOWN,
2228 "org.freedesktop.login1.reboot",
2229 "org.freedesktop.login1.reboot-multiple-sessions",
2230 "org.freedesktop.login1.reboot-ignore-inhibit",
2231 NULL,
2232 error);
2233 }
2234
2235 static int method_can_suspend(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2236 Manager *m = userdata;
2237
2238 return method_can_shutdown_or_sleep(
2239 m, message,
2240 INHIBIT_SLEEP,
2241 "org.freedesktop.login1.suspend",
2242 "org.freedesktop.login1.suspend-multiple-sessions",
2243 "org.freedesktop.login1.suspend-ignore-inhibit",
2244 "suspend",
2245 error);
2246 }
2247
2248 static int method_can_hibernate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2249 Manager *m = userdata;
2250
2251 return method_can_shutdown_or_sleep(
2252 m, message,
2253 INHIBIT_SLEEP,
2254 "org.freedesktop.login1.hibernate",
2255 "org.freedesktop.login1.hibernate-multiple-sessions",
2256 "org.freedesktop.login1.hibernate-ignore-inhibit",
2257 "hibernate",
2258 error);
2259 }
2260
2261 static int method_can_hybrid_sleep(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2262 Manager *m = userdata;
2263
2264 return method_can_shutdown_or_sleep(
2265 m, message,
2266 INHIBIT_SLEEP,
2267 "org.freedesktop.login1.hibernate",
2268 "org.freedesktop.login1.hibernate-multiple-sessions",
2269 "org.freedesktop.login1.hibernate-ignore-inhibit",
2270 "hybrid-sleep",
2271 error);
2272 }
2273
2274 static int property_get_reboot_to_firmware_setup(
2275 sd_bus *bus,
2276 const char *path,
2277 const char *interface,
2278 const char *property,
2279 sd_bus_message *reply,
2280 void *userdata,
2281 sd_bus_error *error) {
2282 int r;
2283
2284 assert(bus);
2285 assert(reply);
2286 assert(userdata);
2287
2288 r = efi_get_reboot_to_firmware();
2289 if (r < 0 && r != -EOPNOTSUPP)
2290 return r;
2291
2292 return sd_bus_message_append(reply, "b", r > 0);
2293 }
2294
2295 static int method_set_reboot_to_firmware_setup(
2296 sd_bus_message *message,
2297 void *userdata,
2298 sd_bus_error *error) {
2299
2300 int b, r;
2301 Manager *m = userdata;
2302
2303 assert(message);
2304 assert(m);
2305
2306 r = sd_bus_message_read(message, "b", &b);
2307 if (r < 0)
2308 return r;
2309
2310 r = bus_verify_polkit_async(message,
2311 CAP_SYS_ADMIN,
2312 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2313 NULL,
2314 false,
2315 UID_INVALID,
2316 &m->polkit_registry,
2317 error);
2318 if (r < 0)
2319 return r;
2320 if (r == 0)
2321 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2322
2323 r = efi_set_reboot_to_firmware(b);
2324 if (r < 0)
2325 return r;
2326
2327 return sd_bus_reply_method_return(message, NULL);
2328 }
2329
2330 static int method_can_reboot_to_firmware_setup(
2331 sd_bus_message *message,
2332 void *userdata,
2333 sd_bus_error *error) {
2334
2335 int r;
2336 bool challenge;
2337 const char *result;
2338 Manager *m = userdata;
2339
2340 assert(message);
2341 assert(m);
2342
2343 r = efi_reboot_to_firmware_supported();
2344 if (r == -EOPNOTSUPP)
2345 return sd_bus_reply_method_return(message, "s", "na");
2346 else if (r < 0)
2347 return r;
2348
2349 r = bus_test_polkit(message,
2350 CAP_SYS_ADMIN,
2351 "org.freedesktop.login1.set-reboot-to-firmware-setup",
2352 NULL,
2353 UID_INVALID,
2354 &challenge,
2355 error);
2356 if (r < 0)
2357 return r;
2358
2359 if (r > 0)
2360 result = "yes";
2361 else if (challenge)
2362 result = "challenge";
2363 else
2364 result = "no";
2365
2366 return sd_bus_reply_method_return(message, "s", result);
2367 }
2368
2369 static int method_set_wall_message(
2370 sd_bus_message *message,
2371 void *userdata,
2372 sd_bus_error *error) {
2373
2374 int r;
2375 Manager *m = userdata;
2376 char *wall_message;
2377 int enable_wall_messages;
2378
2379 assert(message);
2380 assert(m);
2381
2382 r = sd_bus_message_read(message, "sb", &wall_message, &enable_wall_messages);
2383 if (r < 0)
2384 return r;
2385
2386 r = bus_verify_polkit_async(message,
2387 CAP_SYS_ADMIN,
2388 "org.freedesktop.login1.set-wall-message",
2389 NULL,
2390 false,
2391 UID_INVALID,
2392 &m->polkit_registry,
2393 error);
2394 if (r < 0)
2395 return r;
2396 if (r == 0)
2397 return 1; /* Will call us back */
2398
2399 r = free_and_strdup(&m->wall_message, empty_to_null(wall_message));
2400 if (r < 0)
2401 return log_oom();
2402
2403 m->enable_wall_messages = enable_wall_messages;
2404
2405 return sd_bus_reply_method_return(message, NULL);
2406 }
2407
2408 static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2409 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
2410 const char *who, *why, *what, *mode;
2411 _cleanup_free_ char *id = NULL;
2412 _cleanup_close_ int fifo_fd = -1;
2413 Manager *m = userdata;
2414 Inhibitor *i = NULL;
2415 InhibitMode mm;
2416 InhibitWhat w;
2417 pid_t pid;
2418 uid_t uid;
2419 int r;
2420
2421 assert(message);
2422 assert(m);
2423
2424 r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
2425 if (r < 0)
2426 return r;
2427
2428 w = inhibit_what_from_string(what);
2429 if (w <= 0)
2430 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
2431
2432 mm = inhibit_mode_from_string(mode);
2433 if (mm < 0)
2434 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
2435
2436 /* Delay is only supported for shutdown/sleep */
2437 if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
2438 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
2439
2440 /* Don't allow taking delay locks while we are already
2441 * executing the operation. We shouldn't create the impression
2442 * that the lock was successful if the machine is about to go
2443 * down/suspend any moment. */
2444 if (m->action_what & w)
2445 return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
2446
2447 r = bus_verify_polkit_async(
2448 message,
2449 CAP_SYS_BOOT,
2450 w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
2451 w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
2452 w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
2453 w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
2454 w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
2455 w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
2456 "org.freedesktop.login1.inhibit-handle-lid-switch",
2457 NULL,
2458 false,
2459 UID_INVALID,
2460 &m->polkit_registry,
2461 error);
2462 if (r < 0)
2463 return r;
2464 if (r == 0)
2465 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
2466
2467 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
2468 if (r < 0)
2469 return r;
2470
2471 r = sd_bus_creds_get_euid(creds, &uid);
2472 if (r < 0)
2473 return r;
2474
2475 r = sd_bus_creds_get_pid(creds, &pid);
2476 if (r < 0)
2477 return r;
2478
2479 if (hashmap_size(m->inhibitors) >= m->inhibitors_max)
2480 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Maximum number of inhibitors (%" PRIu64 ") reached, refusing further inhibitors.", m->inhibitors_max);
2481
2482 do {
2483 id = mfree(id);
2484
2485 if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
2486 return -ENOMEM;
2487
2488 } while (hashmap_get(m->inhibitors, id));
2489
2490 r = manager_add_inhibitor(m, id, &i);
2491 if (r < 0)
2492 return r;
2493
2494 i->what = w;
2495 i->mode = mm;
2496 i->pid = pid;
2497 i->uid = uid;
2498 i->why = strdup(why);
2499 i->who = strdup(who);
2500
2501 if (!i->why || !i->who) {
2502 r = -ENOMEM;
2503 goto fail;
2504 }
2505
2506 fifo_fd = inhibitor_create_fifo(i);
2507 if (fifo_fd < 0) {
2508 r = fifo_fd;
2509 goto fail;
2510 }
2511
2512 inhibitor_start(i);
2513
2514 return sd_bus_reply_method_return(message, "h", fifo_fd);
2515
2516 fail:
2517 if (i)
2518 inhibitor_free(i);
2519
2520 return r;
2521 }
2522
2523 const sd_bus_vtable manager_vtable[] = {
2524 SD_BUS_VTABLE_START(0),
2525
2526 SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
2527 SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
2528
2529 SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
2530 SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
2531 SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
2532 SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
2533 SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2534 SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2535 SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2536 SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2537 SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2538 SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2539 SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
2540 SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
2541 SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
2542 SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
2543 SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
2544 SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
2545 SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2546 SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
2547 SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
2548 SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
2549 SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
2550 SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
2551 SD_BUS_PROPERTY("Docked", "b", property_get_docked, 0, 0),
2552 SD_BUS_PROPERTY("RemoveIPC", "b", bus_property_get_bool, offsetof(Manager, remove_ipc), SD_BUS_VTABLE_PROPERTY_CONST),
2553 SD_BUS_PROPERTY("RuntimeDirectorySize", "t", bus_property_get_size, offsetof(Manager, runtime_dir_size), SD_BUS_VTABLE_PROPERTY_CONST),
2554 SD_BUS_PROPERTY("InhibitorsMax", "t", NULL, offsetof(Manager, inhibitors_max), SD_BUS_VTABLE_PROPERTY_CONST),
2555 SD_BUS_PROPERTY("NCurrentInhibitors", "t", property_get_current_inhibitors, 0, 0),
2556 SD_BUS_PROPERTY("SessionsMax", "t", NULL, offsetof(Manager, sessions_max), SD_BUS_VTABLE_PROPERTY_CONST),
2557 SD_BUS_PROPERTY("NCurrentSessions", "t", property_get_current_sessions, 0, 0),
2558 SD_BUS_PROPERTY("UserTasksMax", "t", NULL, offsetof(Manager, user_tasks_max), SD_BUS_VTABLE_PROPERTY_CONST),
2559
2560 SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
2561 SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2562 SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
2563 SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
2564 SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2565 SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2566 SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
2567 SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
2568 SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
2569 SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
2570 SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
2571 SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2572 SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2573 SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2574 SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
2575 SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2576 SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
2577 SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
2578 SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
2579 SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
2580 SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
2581 SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
2582 SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
2583 SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
2584 SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
2585 SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2586 SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2587 SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2588 SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2589 SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2590 SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
2591 SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
2592 SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
2593 SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
2594 SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
2595 SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2596 SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
2597 SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
2598 SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2599 SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
2600 SD_BUS_METHOD("SetWallMessage", "sb", NULL, method_set_wall_message, SD_BUS_VTABLE_UNPRIVILEGED),
2601
2602 SD_BUS_SIGNAL("SessionNew", "so", 0),
2603 SD_BUS_SIGNAL("SessionRemoved", "so", 0),
2604 SD_BUS_SIGNAL("UserNew", "uo", 0),
2605 SD_BUS_SIGNAL("UserRemoved", "uo", 0),
2606 SD_BUS_SIGNAL("SeatNew", "so", 0),
2607 SD_BUS_SIGNAL("SeatRemoved", "so", 0),
2608 SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
2609 SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
2610
2611 SD_BUS_VTABLE_END
2612 };
2613
2614 static int session_jobs_reply(Session *s, const char *unit, const char *result) {
2615 int r = 0;
2616
2617 assert(s);
2618 assert(unit);
2619
2620 if (!s->started)
2621 return r;
2622
2623 if (streq(result, "done"))
2624 r = session_send_create_reply(s, NULL);
2625 else {
2626 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
2627
2628 sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
2629 r = session_send_create_reply(s, &e);
2630 }
2631
2632 return r;
2633 }
2634
2635 int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2636 const char *path, *result, *unit;
2637 Manager *m = userdata;
2638 Session *session;
2639 uint32_t id;
2640 User *user;
2641 int r;
2642
2643 assert(message);
2644 assert(m);
2645
2646 r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
2647 if (r < 0) {
2648 bus_log_parse_error(r);
2649 return 0;
2650 }
2651
2652 if (m->action_job && streq(m->action_job, path)) {
2653 log_info("Operation '%s' finished.", inhibit_what_to_string(m->action_what));
2654
2655 /* Tell people that they now may take a lock again */
2656 send_prepare_for(m, m->action_what, false);
2657
2658 m->action_job = mfree(m->action_job);
2659 m->action_unit = NULL;
2660 m->action_what = 0;
2661 return 0;
2662 }
2663
2664 session = hashmap_get(m->session_units, unit);
2665 if (session && streq_ptr(path, session->scope_job)) {
2666 session->scope_job = mfree(session->scope_job);
2667 session_jobs_reply(session, unit, result);
2668
2669 session_save(session);
2670 user_save(session->user);
2671 session_add_to_gc_queue(session);
2672 }
2673
2674 user = hashmap_get(m->user_units, unit);
2675 if (user &&
2676 (streq_ptr(path, user->service_job) ||
2677 streq_ptr(path, user->slice_job))) {
2678
2679 if (streq_ptr(path, user->service_job))
2680 user->service_job = mfree(user->service_job);
2681
2682 if (streq_ptr(path, user->slice_job))
2683 user->slice_job = mfree(user->slice_job);
2684
2685 LIST_FOREACH(sessions_by_user, session, user->sessions)
2686 session_jobs_reply(session, unit, result);
2687
2688 user_save(user);
2689 user_add_to_gc_queue(user);
2690 }
2691
2692 return 0;
2693 }
2694
2695 int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2696 const char *path, *unit;
2697 Manager *m = userdata;
2698 Session *session;
2699 User *user;
2700 int r;
2701
2702 assert(message);
2703 assert(m);
2704
2705 r = sd_bus_message_read(message, "so", &unit, &path);
2706 if (r < 0) {
2707 bus_log_parse_error(r);
2708 return 0;
2709 }
2710
2711 session = hashmap_get(m->session_units, unit);
2712 if (session)
2713 session_add_to_gc_queue(session);
2714
2715 user = hashmap_get(m->user_units, unit);
2716 if (user)
2717 user_add_to_gc_queue(user);
2718
2719 return 0;
2720 }
2721
2722 int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2723 _cleanup_free_ char *unit = NULL;
2724 Manager *m = userdata;
2725 const char *path;
2726 Session *session;
2727 User *user;
2728 int r;
2729
2730 assert(message);
2731 assert(m);
2732
2733 path = sd_bus_message_get_path(message);
2734 if (!path)
2735 return 0;
2736
2737 r = unit_name_from_dbus_path(path, &unit);
2738 if (r == -EINVAL) /* not a unit */
2739 return 0;
2740 if (r < 0) {
2741 log_oom();
2742 return 0;
2743 }
2744
2745 session = hashmap_get(m->session_units, unit);
2746 if (session)
2747 session_add_to_gc_queue(session);
2748
2749 user = hashmap_get(m->user_units, unit);
2750 if (user)
2751 user_add_to_gc_queue(user);
2752
2753 return 0;
2754 }
2755
2756 int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error) {
2757 Manager *m = userdata;
2758 Session *session;
2759 Iterator i;
2760 int b, r;
2761
2762 assert(message);
2763 assert(m);
2764
2765 r = sd_bus_message_read(message, "b", &b);
2766 if (r < 0) {
2767 bus_log_parse_error(r);
2768 return 0;
2769 }
2770
2771 if (b)
2772 return 0;
2773
2774 /* systemd finished reloading, let's recheck all our sessions */
2775 log_debug("System manager has been reloaded, rechecking sessions...");
2776
2777 HASHMAP_FOREACH(session, m->sessions, i)
2778 session_add_to_gc_queue(session);
2779
2780 return 0;
2781 }
2782
2783 int manager_send_changed(Manager *manager, const char *property, ...) {
2784 char **l;
2785
2786 assert(manager);
2787
2788 l = strv_from_stdarg_alloca(property);
2789
2790 return sd_bus_emit_properties_changed_strv(
2791 manager->bus,
2792 "/org/freedesktop/login1",
2793 "org.freedesktop.login1.Manager",
2794 l);
2795 }
2796
2797 static int strdup_job(sd_bus_message *reply, char **job) {
2798 const char *j;
2799 char *copy;
2800 int r;
2801
2802 r = sd_bus_message_read(reply, "o", &j);
2803 if (r < 0)
2804 return r;
2805
2806 copy = strdup(j);
2807 if (!copy)
2808 return -ENOMEM;
2809
2810 *job = copy;
2811 return 1;
2812 }
2813
2814 int manager_start_slice(
2815 Manager *manager,
2816 const char *slice,
2817 const char *description,
2818 const char *after,
2819 const char *after2,
2820 uint64_t tasks_max,
2821 sd_bus_error *error,
2822 char **job) {
2823
2824 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
2825 int r;
2826
2827 assert(manager);
2828 assert(slice);
2829 assert(job);
2830
2831 r = sd_bus_message_new_method_call(
2832 manager->bus,
2833 &m,
2834 "org.freedesktop.systemd1",
2835 "/org/freedesktop/systemd1",
2836 "org.freedesktop.systemd1.Manager",
2837 "StartTransientUnit");
2838 if (r < 0)
2839 return r;
2840
2841 r = sd_bus_message_append(m, "ss", strempty(slice), "fail");
2842 if (r < 0)
2843 return r;
2844
2845 r = sd_bus_message_open_container(m, 'a', "(sv)");
2846 if (r < 0)
2847 return r;
2848
2849 if (!isempty(description)) {
2850 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2851 if (r < 0)
2852 return r;
2853 }
2854
2855 if (!isempty(after)) {
2856 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2857 if (r < 0)
2858 return r;
2859 }
2860
2861 if (!isempty(after2)) {
2862 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2863 if (r < 0)
2864 return r;
2865 }
2866
2867 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
2868 if (r < 0)
2869 return r;
2870
2871 r = sd_bus_message_close_container(m);
2872 if (r < 0)
2873 return r;
2874
2875 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2876 if (r < 0)
2877 return r;
2878
2879 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2880 if (r < 0)
2881 return r;
2882
2883 return strdup_job(reply, job);
2884 }
2885
2886 int manager_start_scope(
2887 Manager *manager,
2888 const char *scope,
2889 pid_t pid,
2890 const char *slice,
2891 const char *description,
2892 const char *after,
2893 const char *after2,
2894 uint64_t tasks_max,
2895 sd_bus_error *error,
2896 char **job) {
2897
2898 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
2899 int r;
2900
2901 assert(manager);
2902 assert(scope);
2903 assert(pid > 1);
2904 assert(job);
2905
2906 r = sd_bus_message_new_method_call(
2907 manager->bus,
2908 &m,
2909 "org.freedesktop.systemd1",
2910 "/org/freedesktop/systemd1",
2911 "org.freedesktop.systemd1.Manager",
2912 "StartTransientUnit");
2913 if (r < 0)
2914 return r;
2915
2916 r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
2917 if (r < 0)
2918 return r;
2919
2920 r = sd_bus_message_open_container(m, 'a', "(sv)");
2921 if (r < 0)
2922 return r;
2923
2924 if (!isempty(slice)) {
2925 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
2926 if (r < 0)
2927 return r;
2928 }
2929
2930 if (!isempty(description)) {
2931 r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
2932 if (r < 0)
2933 return r;
2934 }
2935
2936 if (!isempty(after)) {
2937 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
2938 if (r < 0)
2939 return r;
2940 }
2941
2942 if (!isempty(after2)) {
2943 r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
2944 if (r < 0)
2945 return r;
2946 }
2947
2948 /* cgroup empty notification is not available in containers
2949 * currently. To make this less problematic, let's shorten the
2950 * stop timeout for sessions, so that we don't wait
2951 * forever. */
2952
2953 /* Make sure that the session shells are terminated with
2954 * SIGHUP since bash and friends tend to ignore SIGTERM */
2955 r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
2956 if (r < 0)
2957 return r;
2958
2959 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
2960 if (r < 0)
2961 return r;
2962
2963 r = sd_bus_message_append(m, "(sv)", "TasksMax", "t", tasks_max);
2964 if (r < 0)
2965 return r;
2966
2967 r = sd_bus_message_close_container(m);
2968 if (r < 0)
2969 return r;
2970
2971 r = sd_bus_message_append(m, "a(sa(sv))", 0);
2972 if (r < 0)
2973 return r;
2974
2975 r = sd_bus_call(manager->bus, m, 0, error, &reply);
2976 if (r < 0)
2977 return r;
2978
2979 return strdup_job(reply, job);
2980 }
2981
2982 int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
2983 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
2984 int r;
2985
2986 assert(manager);
2987 assert(unit);
2988 assert(job);
2989
2990 r = sd_bus_call_method(
2991 manager->bus,
2992 "org.freedesktop.systemd1",
2993 "/org/freedesktop/systemd1",
2994 "org.freedesktop.systemd1.Manager",
2995 "StartUnit",
2996 error,
2997 &reply,
2998 "ss", unit, "replace");
2999 if (r < 0)
3000 return r;
3001
3002 return strdup_job(reply, job);
3003 }
3004
3005 int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
3006 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3007 int r;
3008
3009 assert(manager);
3010 assert(unit);
3011 assert(job);
3012
3013 r = sd_bus_call_method(
3014 manager->bus,
3015 "org.freedesktop.systemd1",
3016 "/org/freedesktop/systemd1",
3017 "org.freedesktop.systemd1.Manager",
3018 "StopUnit",
3019 error,
3020 &reply,
3021 "ss", unit, "fail");
3022 if (r < 0) {
3023 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3024 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
3025
3026 *job = NULL;
3027 sd_bus_error_free(error);
3028 return 0;
3029 }
3030
3031 return r;
3032 }
3033
3034 return strdup_job(reply, job);
3035 }
3036
3037 int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
3038 _cleanup_free_ char *path = NULL;
3039 int r;
3040
3041 assert(manager);
3042 assert(scope);
3043
3044 path = unit_dbus_path_from_name(scope);
3045 if (!path)
3046 return -ENOMEM;
3047
3048 r = sd_bus_call_method(
3049 manager->bus,
3050 "org.freedesktop.systemd1",
3051 path,
3052 "org.freedesktop.systemd1.Scope",
3053 "Abandon",
3054 error,
3055 NULL,
3056 NULL);
3057 if (r < 0) {
3058 if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
3059 sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
3060 sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
3061 sd_bus_error_free(error);
3062 return 0;
3063 }
3064
3065 return r;
3066 }
3067
3068 return 1;
3069 }
3070
3071 int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
3072 assert(manager);
3073 assert(unit);
3074
3075 return sd_bus_call_method(
3076 manager->bus,
3077 "org.freedesktop.systemd1",
3078 "/org/freedesktop/systemd1",
3079 "org.freedesktop.systemd1.Manager",
3080 "KillUnit",
3081 error,
3082 NULL,
3083 "ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
3084 }
3085
3086 int manager_unit_is_active(Manager *manager, const char *unit) {
3087 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3088 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3089 _cleanup_free_ char *path = NULL;
3090 const char *state;
3091 int r;
3092
3093 assert(manager);
3094 assert(unit);
3095
3096 path = unit_dbus_path_from_name(unit);
3097 if (!path)
3098 return -ENOMEM;
3099
3100 r = sd_bus_get_property(
3101 manager->bus,
3102 "org.freedesktop.systemd1",
3103 path,
3104 "org.freedesktop.systemd1.Unit",
3105 "ActiveState",
3106 &error,
3107 &reply,
3108 "s");
3109 if (r < 0) {
3110 /* systemd might have droppped off momentarily, let's
3111 * not make this an error */
3112 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3113 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3114 return true;
3115
3116 /* If the unit is already unloaded then it's not
3117 * active */
3118 if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
3119 sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
3120 return false;
3121
3122 return r;
3123 }
3124
3125 r = sd_bus_message_read(reply, "s", &state);
3126 if (r < 0)
3127 return -EINVAL;
3128
3129 return !streq(state, "inactive") && !streq(state, "failed");
3130 }
3131
3132 int manager_job_is_active(Manager *manager, const char *path) {
3133 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
3134 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
3135 int r;
3136
3137 assert(manager);
3138 assert(path);
3139
3140 r = sd_bus_get_property(
3141 manager->bus,
3142 "org.freedesktop.systemd1",
3143 path,
3144 "org.freedesktop.systemd1.Job",
3145 "State",
3146 &error,
3147 &reply,
3148 "s");
3149 if (r < 0) {
3150 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
3151 sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
3152 return true;
3153
3154 if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
3155 return false;
3156
3157 return r;
3158 }
3159
3160 /* We don't actually care about the state really. The fact
3161 * that we could read the job state is enough for us */
3162
3163 return true;
3164 }