1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2009-2010 Red Hat, Inc.
4 * Copyright (c) 2013 Canonical Limited
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * Written by: Matthias Clasen <mclasen@redhat.com>
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <sys/wait.h>
31 #include <pwd.h>
32 #ifdef HAVE_SHADOW_H
33 #include <shadow.h>
34 #endif
35 #include <unistd.h>
36 #include <errno.h>
37 #include <sys/types.h>
38
39 #include <glib.h>
40 #include <glib/gi18n.h>
41 #include <glib-object.h>
42 #include <glib/gstdio.h>
43 #include <gio/gio.h>
44 #include <polkit/polkit.h>
45
46 #include "user-classify.h"
47 #include "wtmp-helper.h"
48 #include "daemon.h"
49 #include "util.h"
50
51 #define PATH_PASSWD "/etc/passwd"
52 #define PATH_SHADOW "/etc/shadow"
53 #define PATH_GROUP "/etc/group"
54
55 enum {
56 PROP_0,
57 PROP_DAEMON_VERSION
58 };
59
60 typedef struct {
61 GDBusConnection *bus_connection;
62
63 GHashTable *users;
64 gsize number_of_normal_users;
65 GList *explicitly_requested_users;
66
67 User *autologin;
68
69 GFileMonitor *passwd_monitor;
70 GFileMonitor *shadow_monitor;
71 GFileMonitor *group_monitor;
72 GFileMonitor *gdm_monitor;
73 GFileMonitor *wtmp_monitor;
74
75 GQueue *pending_list_cached_users;
76
77 guint reload_id;
78 guint autologin_id;
79
80 PolkitAuthority *authority;
81 GHashTable *extension_ifaces;
82 } DaemonPrivate;
83
84 #ifdef HAVE_SHADOW_H
85 typedef struct passwd * (* EntryGeneratorFunc) (Daemon *, GHashTable *, gpointer *, struct spwd **shadow_entry);
86 #else
87 typedef struct passwd * (* EntryGeneratorFunc) (Daemon *, GHashTable *, gpointer *);
88 #endif
89
90 typedef struct {
91 Daemon *daemon;
92 GDBusMethodInvocation *context;
93 } ListUserData;
94
95 static void finish_list_cached_users (ListUserData *data);
96
97 static void list_user_data_free (ListUserData *data);
98
99 static void daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface);
100
101 G_DEFINE_TYPE_WITH_CODE (Daemon, daemon, ACCOUNTS_TYPE_ACCOUNTS_SKELETON, G_ADD_PRIVATE (Daemon) G_IMPLEMENT_INTERFACE (ACCOUNTS_TYPE_ACCOUNTS, daemon_accounts_accounts_iface_init));
102
103 G_DEFINE_AUTOPTR_CLEANUP_FUNC (Daemon, g_object_unref)
104
105 static const GDBusErrorEntry accounts_error_entries[] =
106 {
107 { ERROR_FAILED, "org.freedesktop.Accounts.Error.Failed" },
108 { ERROR_USER_EXISTS, "org.freedesktop.Accounts.Error.UserExists" },
109 { ERROR_USER_DOES_NOT_EXIST, "org.freedesktop.Accounts.Error.UserDoesNotExist" },
110 { ERROR_PERMISSION_DENIED, "org.freedesktop.Accounts.Error.PermissionDenied" },
111 { ERROR_NOT_SUPPORTED, "org.freedesktop.Accounts.Error.NotSupported" }
112 };
113
114 GQuark
error_quark(void)115 error_quark (void)
116 {
117 static volatile gsize quark_volatile = 0;
118
119 g_dbus_error_register_error_domain ("accounts_error",
120 &quark_volatile,
121 accounts_error_entries,
122 G_N_ELEMENTS (accounts_error_entries));
123
124 return (GQuark) quark_volatile;
125 }
126 #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
127
128 GType
error_get_type(void)129 error_get_type (void)
130 {
131 static GType etype = 0;
132
133 if (etype == 0)
134 {
135 static const GEnumValue values[] =
136 {
137 ENUM_ENTRY (ERROR_FAILED, "Failed"),
138 ENUM_ENTRY (ERROR_USER_EXISTS, "UserExists"),
139 ENUM_ENTRY (ERROR_USER_DOES_NOT_EXIST, "UserDoesntExist"),
140 ENUM_ENTRY (ERROR_PERMISSION_DENIED, "PermissionDenied"),
141 ENUM_ENTRY (ERROR_NOT_SUPPORTED, "NotSupported"),
142 { 0, 0, 0 }
143 };
144 g_assert (NUM_ERRORS == G_N_ELEMENTS (values) - 1);
145 etype = g_enum_register_static ("Error", values);
146 }
147 return etype;
148 }
149
150 #ifndef HAVE_FGETPWENT
151 #include "fgetpwent.c"
152 #endif
153
154 #ifndef MAX_LOCAL_USERS
155 #define MAX_LOCAL_USERS 50
156 #endif
157
158 static void
remove_cache_files(const gchar * user_name)159 remove_cache_files (const gchar *user_name)
160 {
161 g_autofree gchar *user_filename = NULL;
162 g_autofree gchar *icon_filename = NULL;
163
164 user_filename = g_build_filename (USERDIR, user_name, NULL);
165 g_remove (user_filename);
166
167 icon_filename = g_build_filename (ICONDIR, user_name, NULL);
168 g_remove (icon_filename);
169 }
170
171 static struct passwd *
172 #ifdef HAVE_SHADOW_H
entry_generator_fgetpwent(Daemon * daemon,GHashTable * users,gpointer * state,struct spwd ** spent)173 entry_generator_fgetpwent (Daemon *daemon,
174 GHashTable *users,
175 gpointer *state,
176 struct spwd **spent)
177 #else
178 entry_generator_fgetpwent (Daemon *daemon,
179 GHashTable *users,
180 gpointer *state)
181 #endif
182 {
183 struct passwd *pwent;
184
185 #ifdef HAVE_SHADOW_H
186 struct {
187 struct spwd spbuf;
188 char buf[1024];
189 } *shadow_entry_buffers;
190 #endif
191
192 struct {
193 FILE *fp;
194 GHashTable *users;
195 } *generator_state;
196
197 /* First iteration */
198 if (*state == NULL) {
199 GHashTable *shadow_users = NULL;
200 FILE *fp;
201 #ifdef HAVE_SHADOW_H
202 struct spwd *shadow_entry;
203
204 fp = fopen (PATH_SHADOW, "r");
205 if (fp == NULL) {
206 g_warning ("Unable to open %s: %s", PATH_SHADOW, g_strerror (errno));
207 return NULL;
208 }
209
210 shadow_users = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
211
212 do {
213 int ret = 0;
214
215 shadow_entry_buffers = g_malloc0 (sizeof (*shadow_entry_buffers));
216
217 ret = fgetspent_r (fp, &shadow_entry_buffers->spbuf, shadow_entry_buffers->buf, sizeof (shadow_entry_buffers->buf), &shadow_entry);
218 if (ret == 0) {
219 g_hash_table_insert (shadow_users, g_strdup (shadow_entry->sp_namp), shadow_entry_buffers);
220 } else {
221 g_free (shadow_entry_buffers);
222
223 if (errno != EINTR) {
224 break;
225 }
226 }
227 } while (shadow_entry != NULL);
228
229 fclose (fp);
230
231 if (g_hash_table_size (shadow_users) == 0) {
232 g_clear_pointer (&shadow_users, g_hash_table_unref);
233 return NULL;
234 }
235 #endif
236
237 fp = fopen (PATH_PASSWD, "r");
238 if (fp == NULL) {
239 g_clear_pointer (&shadow_users, g_hash_table_unref);
240 g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno));
241 return NULL;
242 }
243
244 generator_state = g_malloc0 (sizeof (*generator_state));
245 generator_state->fp = fp;
246 generator_state->users = shadow_users;
247
248 *state = generator_state;
249 }
250
251 /* Every iteration */
252 generator_state = *state;
253
254 if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
255 pwent = fgetpwent (generator_state->fp);
256 if (pwent != NULL) {
257 #ifdef HAVE_SHADOW_H
258 shadow_entry_buffers = g_hash_table_lookup (generator_state->users, pwent->pw_name);
259
260 if (shadow_entry_buffers != NULL) {
261 *spent = &shadow_entry_buffers->spbuf;
262 }
263 return pwent;
264 #else
265 if (!generator_state->users || g_hash_table_lookup (generator_state->users, pwent->pw_name))
266 return pwent;
267 #endif
268 }
269 }
270
271 /* Last iteration */
272 fclose (generator_state->fp);
273 g_hash_table_unref (generator_state->users);
274 g_free (generator_state);
275 *state = NULL;
276
277 return NULL;
278 }
279
280 static struct passwd *
281 #ifdef HAVE_SHADOW_H
entry_generator_cachedir(Daemon * daemon,GHashTable * users,gpointer * state,struct spwd ** shadow_entry)282 entry_generator_cachedir (Daemon *daemon,
283 GHashTable *users,
284 gpointer *state,
285 struct spwd **shadow_entry)
286 #else
287 entry_generator_cachedir (Daemon *daemon,
288 GHashTable *users,
289 gpointer *state)
290 #endif
291 {
292 struct passwd *pwent;
293 g_autoptr(GError) error = NULL;
294 gboolean regular;
295 GHashTableIter iter;
296 gpointer key, value;
297 GDir *dir;
298
299 /* First iteration */
300 if (*state == NULL) {
301 *state = g_dir_open (USERDIR, 0, &error);
302 if (error != NULL) {
303 if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
304 g_warning ("couldn't list user cache directory: %s", USERDIR);
305 return NULL;
306 }
307 }
308
309 /* Every iteration */
310
311 /*
312 * Use names of files of regular type to lookup information
313 * about each user. Loop until we find something valid.
314 */
315 dir = *state;
316 while (TRUE) {
317 const gchar *name;
318 g_autofree gchar *filename = NULL;
319
320 name = g_dir_read_name (dir);
321 if (name == NULL)
322 break;
323
324 /* Only load files in this directory */
325 filename = g_build_filename (USERDIR, name, NULL);
326 regular = g_file_test (filename, G_FILE_TEST_IS_REGULAR);
327
328 if (regular) {
329 errno = 0;
330 pwent = getpwnam (name);
331 if (pwent != NULL) {
332 #ifdef HAVE_SHADOW_H
333 *shadow_entry = getspnam (pwent->pw_name);
334 #endif
335
336 return pwent;
337 } else if (errno == 0) {
338 g_debug ("user '%s' in cache dir but not present on system, removing", name);
339 remove_cache_files (name);
340 }
341 else {
342 g_warning ("failed to check if user '%s' in cache dir is present on system: %s",
343 name, g_strerror (errno));
344 }
345 }
346 }
347
348 /* Last iteration */
349 g_dir_close (dir);
350
351 /* Update all the users from the files in the cache dir */
352 g_hash_table_iter_init (&iter, users);
353 while (g_hash_table_iter_next (&iter, &key, &value)) {
354 const gchar *name = key;
355 User *user = value;
356 g_autofree gchar *filename = NULL;
357 g_autoptr(GKeyFile) key_file = NULL;
358
359 filename = g_build_filename (USERDIR, name, NULL);
360 key_file = g_key_file_new ();
361 if (g_key_file_load_from_file (key_file, filename, 0, NULL))
362 user_update_from_keyfile (user, key_file);
363 }
364
365 *state = NULL;
366 return NULL;
367 }
368
369 static struct passwd *
370 #ifdef HAVE_SHADOW_H
entry_generator_requested_users(Daemon * daemon,GHashTable * users,gpointer * state,struct spwd ** shadow_entry)371 entry_generator_requested_users (Daemon *daemon,
372 GHashTable *users,
373 gpointer *state,
374 struct spwd **shadow_entry)
375 #else
376 entry_generator_requested_users (Daemon *daemon,
377 GHashTable *users,
378 gpointer *state)
379 #endif
380 {
381 DaemonPrivate *priv = daemon_get_instance_private (daemon);
382 struct passwd *pwent;
383 GList *node;
384
385 /* First iteration */
386 if (*state == NULL) {
387 *state = priv->explicitly_requested_users;
388 }
389
390 /* Every iteration */
391
392 if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
393 node = *state;
394 while (node != NULL) {
395 const char *name;
396
397 name = node->data;
398 node = node->next;
399
400 *state = node;
401
402 if (!g_hash_table_lookup (users, name)) {
403 pwent = getpwnam (name);
404 if (pwent == NULL) {
405 g_debug ("user '%s' requested previously but not present on system", name);
406 } else {
407 #ifdef HAVE_SHADOW_H
408 *shadow_entry = getspnam (pwent->pw_name);
409 #endif
410
411 return pwent;
412 }
413 }
414 }
415 }
416
417 /* Last iteration */
418
419 *state = NULL;
420 return NULL;
421 }
422
423 static void
load_entries(Daemon * daemon,GHashTable * users,gboolean explicitly_requested,EntryGeneratorFunc entry_generator)424 load_entries (Daemon *daemon,
425 GHashTable *users,
426 gboolean explicitly_requested,
427 EntryGeneratorFunc entry_generator)
428 {
429 DaemonPrivate *priv = daemon_get_instance_private (daemon);
430 gpointer generator_state = NULL;
431 struct passwd *pwent;
432 #ifdef HAVE_SHADOW_H
433 struct spwd *spent = NULL;
434 #endif
435 User *user = NULL;
436
437 g_assert (entry_generator != NULL);
438
439 for (;;) {
440 #ifdef HAVE_SHADOW_H
441 spent = NULL;
442 pwent = entry_generator (daemon, users, &generator_state, &spent);
443 #else
444 pwent = entry_generator (daemon, users, &generator_state);
445 #endif
446 if (pwent == NULL)
447 break;
448
449 /* Skip system users... */
450 #ifdef HAVE_SHADOW_H
451 if (!explicitly_requested && !user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, spent? spent->sp_pwdp : NULL)) {
452 #else
453 if (!explicitly_requested && !user_classify_is_human (pwent->pw_uid, pwent->pw_name, pwent->pw_shell, NULL)) {
454 #endif
455 g_debug ("skipping user: %s", pwent->pw_name);
456 continue;
457 }
458
459 /* Only process users that haven't been processed yet.
460 * We do always make sure entries get promoted
461 * to "cached" status if they are supposed to be
462 */
463
464 user = g_hash_table_lookup (users, pwent->pw_name);
465
466 if (user == NULL) {
467 user = g_hash_table_lookup (priv->users, pwent->pw_name);
468 if (user == NULL) {
469 user = user_new (daemon, pwent->pw_uid);
470 } else {
471 g_object_ref (user);
472 }
473
474 /* freeze & update users not already in the new list */
475 g_object_freeze_notify (G_OBJECT (user));
476 #ifdef HAVE_SHADOW_H
477 user_update_from_pwent (user, pwent, spent);
478 #else
479 user_update_from_pwent (user, pwent);
480 #endif
481
482 g_hash_table_insert (users, g_strdup (user_get_user_name (user)), user);
483 g_debug ("loaded user: %s", user_get_user_name (user));
484 }
485
486 if (!explicitly_requested) {
487 user_set_cached (user, TRUE);
488 }
489 }
490
491 /* Generator should have cleaned up */
492 g_assert (generator_state == NULL);
493 }
494
495 static GHashTable *
496 create_users_hash_table (void)
497 {
498 return g_hash_table_new_full (g_str_hash,
499 g_str_equal,
500 g_free,
501 g_object_unref);
502 }
503
504 static void
505 reload_users (Daemon *daemon)
506 {
507 DaemonPrivate *priv = daemon_get_instance_private (daemon);
508 AccountsAccounts *accounts = ACCOUNTS_ACCOUNTS (daemon);
509 gboolean had_no_users, has_no_users, had_multiple_users, has_multiple_users;
510 GHashTable *users;
511 GHashTable *old_users;
512 GHashTable *local;
513 GHashTableIter iter;
514 gsize number_of_normal_users = 0;
515 gpointer name, value;
516
517 /* Track the users that we saw during our (re)load */
518 users = create_users_hash_table ();
519
520 /*
521 * NOTE: As we load data from all the sources, notifies are
522 * frozen in load_entries() and then thawed as we process
523 * them below.
524 */
525
526 /* Load the local users into our hash table */
527 load_entries (daemon, users, FALSE, entry_generator_fgetpwent);
528 local = g_hash_table_new (g_str_hash, g_str_equal);
529 g_hash_table_iter_init (&iter, users);
530 while (g_hash_table_iter_next (&iter, &name, NULL))
531 g_hash_table_add (local, name);
532
533 /* and add users to hash table that were explicitly requested */
534 load_entries (daemon, users, TRUE, entry_generator_requested_users);
535
536 /* Now add/update users from other sources, possibly non-local */
537 load_entries (daemon, users, FALSE, entry_generator_cachedir);
538
539 wtmp_helper_update_login_frequencies (users);
540
541 /* Count the non-system users. Mark which users are local, which are not. */
542 g_hash_table_iter_init (&iter, users);
543 while (g_hash_table_iter_next (&iter, &name, &value)) {
544 User *user = value;
545 if (!user_get_system_account (user))
546 number_of_normal_users++;
547 user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL);
548 }
549 g_hash_table_destroy (local);
550
551 had_no_users = accounts_accounts_get_has_no_users (accounts);
552 has_no_users = number_of_normal_users == 0;
553
554 if (had_no_users != has_no_users)
555 accounts_accounts_set_has_no_users (accounts, has_no_users);
556
557 had_multiple_users = accounts_accounts_get_has_multiple_users (accounts);
558 has_multiple_users = number_of_normal_users > 1;
559
560 if (had_multiple_users != has_multiple_users)
561 accounts_accounts_set_has_multiple_users (accounts, has_multiple_users);
562
563 /* Swap out the users */
564 old_users = priv->users;
565 priv->users = users;
566
567 /* Remove all the old users */
568 g_hash_table_iter_init (&iter, old_users);
569 while (g_hash_table_iter_next (&iter, &name, &value)) {
570 User *user = value;
571 User *refreshed_user;
572
573 refreshed_user = g_hash_table_lookup (users, name);
574
575 if (!refreshed_user || (user_get_cached (user) && !user_get_cached (refreshed_user))) {
576 accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon),
577 user_get_object_path (user));
578 user_unregister (user);
579 }
580 }
581
582 /* Register all the new users */
583 g_hash_table_iter_init (&iter, users);
584 while (g_hash_table_iter_next (&iter, &name, &value)) {
585 User *user = value;
586 User *stale_user;
587
588 stale_user = g_hash_table_lookup (old_users, name);
589
590 if (!stale_user || (!user_get_cached (stale_user) && user_get_cached (user))) {
591 user_register (user);
592 accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon),
593 user_get_object_path (user));
594 }
595 g_object_thaw_notify (G_OBJECT (user));
596 }
597
598 g_hash_table_destroy (old_users);
599 }
600
601 static gboolean
602 reload_users_timeout (Daemon *daemon)
603 {
604 DaemonPrivate *priv = daemon_get_instance_private (daemon);
605
606 reload_users (daemon);
607 priv->reload_id = 0;
608
609 g_queue_foreach (priv->pending_list_cached_users,
610 (GFunc) finish_list_cached_users, NULL);
611 g_queue_clear (priv->pending_list_cached_users);
612
613 return FALSE;
614 }
615
616 static gboolean load_autologin (Daemon *daemon,
617 gchar **name,
618 gboolean *enabled,
619 GError **error);
620
621 static gboolean
622 reload_autologin_timeout (Daemon *daemon)
623 {
624 DaemonPrivate *priv = daemon_get_instance_private (daemon);
625 AccountsAccounts *accounts = ACCOUNTS_ACCOUNTS (daemon);
626 gboolean enabled;
627 g_autofree gchar *name = NULL;
628 g_autoptr(GError) error = NULL;
629 User *user = NULL;
630
631 priv->autologin_id = 0;
632
633 if (!load_autologin (daemon, &name, &enabled, &error)) {
634 g_debug ("failed to load gdms custom.conf: %s", error->message);
635 return FALSE;
636 }
637
638 if (enabled && name)
639 user = daemon_local_find_user_by_name (daemon, name);
640
641 if (priv->autologin != NULL && priv->autologin != user) {
642 g_object_set (priv->autologin, "automatic-login", FALSE, NULL);
643 g_signal_emit_by_name (priv->autologin, "changed", 0);
644 g_clear_object (&priv->autologin);
645 }
646
647 if (enabled) {
648 const gchar *users[2];
649
650 g_debug ("automatic login is enabled for '%s'", name);
651 users[0] = user_get_object_path (user);
652 users[1] = NULL;
653 accounts_accounts_set_automatic_login_users (accounts, users);
654 if (priv->autologin != user) {
655 g_object_set (user, "automatic-login", TRUE, NULL);
656 priv->autologin = g_object_ref (user);
657 g_signal_emit_by_name (priv->autologin, "changed", 0);
658 }
659 }
660 else {
661 g_debug ("automatic login is disabled");
662 accounts_accounts_set_automatic_login_users (accounts, NULL);
663 }
664
665 return FALSE;
666 }
667
668 static void
669 queue_reload_users_soon (Daemon *daemon)
670 {
671 DaemonPrivate *priv = daemon_get_instance_private (daemon);
672
673 if (priv->reload_id > 0) {
674 return;
675 }
676
677 /* we wait half a second or so in case /etc/passwd and
678 * /etc/shadow are changed at the same time, or repeatedly.
679 */
680 priv->reload_id = g_timeout_add (500, (GSourceFunc)reload_users_timeout, daemon);
681 }
682
683 static void
684 queue_reload_users (Daemon *daemon)
685 {
686 DaemonPrivate *priv = daemon_get_instance_private (daemon);
687
688 if (priv->reload_id > 0) {
689 return;
690 }
691
692 priv->reload_id = g_idle_add ((GSourceFunc)reload_users_timeout, daemon);
693 }
694
695 static void
696 queue_reload_autologin (Daemon *daemon)
697 {
698 DaemonPrivate *priv = daemon_get_instance_private (daemon);
699
700 if (priv->autologin_id > 0) {
701 return;
702 }
703
704 priv->autologin_id = g_idle_add ((GSourceFunc)reload_autologin_timeout, daemon);
705 }
706
707 static void
708 on_users_monitor_changed (GFileMonitor *monitor,
709 GFile *file,
710 GFile *other_file,
711 GFileMonitorEvent event_type,
712 Daemon *daemon)
713 {
714 if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
715 event_type != G_FILE_MONITOR_EVENT_CREATED) {
716 return;
717 }
718
719 queue_reload_users_soon (daemon);
720 }
721
722 static void
723 on_gdm_monitor_changed (GFileMonitor *monitor,
724 GFile *file,
725 GFile *other_file,
726 GFileMonitorEvent event_type,
727 Daemon *daemon)
728 {
729 if (event_type != G_FILE_MONITOR_EVENT_CHANGED &&
730 event_type != G_FILE_MONITOR_EVENT_CREATED) {
731 return;
732 }
733
734 queue_reload_autologin (daemon);
735 }
736
737 typedef void FileChangeCallback (GFileMonitor *monitor,
738 GFile *file,
739 GFile *other_file,
740 GFileMonitorEvent event_type,
741 Daemon *daemon);
742
743 static GFileMonitor *
744 setup_monitor (Daemon *daemon,
745 const gchar *path,
746 FileChangeCallback *callback)
747 {
748 g_autoptr(GFile) file = NULL;
749 GFileMonitor *monitor;
750 g_autoptr(GError) error = NULL;
751
752 if (!path) {
753 return NULL;
754 }
755
756 file = g_file_new_for_path (path);
757 monitor = g_file_monitor_file (file,
758 G_FILE_MONITOR_NONE,
759 NULL,
760 &error);
761 if (monitor == NULL) {
762 g_warning ("Unable to monitor %s: %s", path, error->message);
763 return NULL;
764 }
765
766 g_signal_connect (monitor,
767 "changed",
768 G_CALLBACK (callback),
769 daemon);
770
771 return monitor;
772 }
773
774 static void
775 daemon_init (Daemon *daemon)
776 {
777 DaemonPrivate *priv = daemon_get_instance_private (daemon);
778
779 priv->extension_ifaces = daemon_read_extension_ifaces ();
780
781 priv->users = create_users_hash_table ();
782
783 priv->pending_list_cached_users = g_queue_new ();
784
785 priv->passwd_monitor = setup_monitor (daemon,
786 PATH_PASSWD,
787 on_users_monitor_changed);
788 priv->shadow_monitor = setup_monitor (daemon,
789 PATH_SHADOW,
790 on_users_monitor_changed);
791 priv->group_monitor = setup_monitor (daemon,
792 PATH_GROUP,
793 on_users_monitor_changed);
794
795 priv->wtmp_monitor = setup_monitor (daemon,
796 wtmp_helper_get_path_for_monitor (),
797 on_users_monitor_changed);
798
799 priv->gdm_monitor = setup_monitor (daemon,
800 PATH_GDM_CUSTOM,
801 on_gdm_monitor_changed);
802 reload_users_timeout (daemon);
803 queue_reload_autologin (daemon);
804 }
805
806 static void
807 daemon_finalize (GObject *object)
808 {
809 DaemonPrivate *priv;
810 Daemon *daemon;
811
812 g_return_if_fail (IS_DAEMON (object));
813
814 daemon = DAEMON (object);
815 priv = daemon_get_instance_private (daemon);
816
817 if (priv->bus_connection != NULL)
818 g_object_unref (priv->bus_connection);
819
820 g_queue_free_full (priv->pending_list_cached_users,
821 (GDestroyNotify) list_user_data_free);
822
823 g_list_free_full (priv->explicitly_requested_users, g_free);
824
825 g_hash_table_destroy (priv->users);
826
827 g_hash_table_unref (priv->extension_ifaces);
828
829 G_OBJECT_CLASS (daemon_parent_class)->finalize (object);
830 }
831
832 static gboolean
833 register_accounts_daemon (Daemon *daemon)
834 {
835 DaemonPrivate *priv = daemon_get_instance_private (daemon);
836 g_autoptr(GError) error = NULL;
837
838 priv->authority = polkit_authority_get_sync (NULL, &error);
839 if (priv->authority == NULL) {
840 if (error != NULL)
841 g_critical ("error getting polkit authority: %s", error->message);
842 return FALSE;
843 }
844
845 priv->bus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
846 if (priv->bus_connection == NULL) {
847 if (error != NULL)
848 g_critical ("error getting system bus: %s", error->message);
849 return FALSE;
850 }
851
852 if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon),
853 priv->bus_connection,
854 "/org/freedesktop/Accounts",
855 &error)) {
856 if (error != NULL)
857 g_critical ("error exporting interface: %s", error->message);
858 return FALSE;
859 }
860
861 return TRUE;
862 }
863
864 Daemon *
865 daemon_new (void)
866 {
867 g_autoptr(Daemon) daemon = NULL;
868
869 daemon = DAEMON (g_object_new (TYPE_DAEMON, NULL));
870
871 if (!register_accounts_daemon (DAEMON (daemon))) {
872 return NULL;
873 }
874
875 return g_steal_pointer (&daemon);
876 }
877
878 static void
879 throw_error (GDBusMethodInvocation *context,
880 gint error_code,
881 const gchar *format,
882 ...)
883 {
884 va_list args;
885 g_autofree gchar *message = NULL;
886
887 va_start (args, format);
888 message = g_strdup_vprintf (format, args);
889 va_end (args);
890
891 g_dbus_method_invocation_return_error (context, ERROR, error_code, "%s", message);
892 }
893
894 static User *
895 #ifdef HAVE_SHADOW_H
896 add_new_user_for_pwent (Daemon *daemon,
897 struct passwd *pwent,
898 struct spwd *spent)
899 #else
900 add_new_user_for_pwent (Daemon *daemon,
901 struct passwd *pwent)
902 #endif
903 {
904 DaemonPrivate *priv = daemon_get_instance_private (daemon);
905 User *user;
906
907 user = user_new (daemon, pwent->pw_uid);
908 #ifdef HAVE_SHADOW_H
909 user_update_from_pwent (user, pwent, spent);
910 #else
911 user_update_from_pwent (user, pwent);
912 #endif
913 user_register (user);
914
915 g_hash_table_insert (priv->users,
916 g_strdup (user_get_user_name (user)),
917 user);
918
919 accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon), user_get_object_path (user));
920
921 return user;
922 }
923
924 User *
925 daemon_local_find_user_by_id (Daemon *daemon,
926 uid_t uid)
927 {
928 DaemonPrivate *priv = daemon_get_instance_private (daemon);
929 User *user;
930 struct passwd *pwent;
931
932 pwent = getpwuid (uid);
933 if (pwent == NULL) {
934 g_debug ("unable to lookup uid %d", (int)uid);
935 return NULL;
936 }
937
938 user = g_hash_table_lookup (priv->users, pwent->pw_name);
939
940 if (user == NULL) {
941 #ifdef HAVE_SHADOW_H
942 struct spwd *spent;
943 spent = getspnam (pwent->pw_name);
944 user = add_new_user_for_pwent (daemon, pwent, spent);
945 #else
946 user = add_new_user_for_pwent (daemon, pwent);
947 #endif
948
949 priv->explicitly_requested_users = g_list_append (priv->explicitly_requested_users,
950 g_strdup (pwent->pw_name));
951 }
952
953 return user;
954 }
955
956 User *
957 daemon_local_find_user_by_name (Daemon *daemon,
958 const gchar *name)
959 {
960 DaemonPrivate *priv = daemon_get_instance_private (daemon);
961 User *user;
962 struct passwd *pwent;
963
964 pwent = getpwnam (name);
965 if (pwent == NULL) {
966 g_debug ("unable to lookup name %s: %s", name, g_strerror (errno));
967 return NULL;
968 }
969
970 user = g_hash_table_lookup (priv->users, pwent->pw_name);
971
972 if (user == NULL) {
973 #ifdef HAVE_SHADOW_H
974 struct spwd *spent;
975 spent = getspnam (pwent->pw_name);
976 user = add_new_user_for_pwent (daemon, pwent, spent);
977 #else
978 user = add_new_user_for_pwent (daemon, pwent);
979 #endif
980
981 priv->explicitly_requested_users = g_list_append (priv->explicitly_requested_users,
982 g_strdup (pwent->pw_name));
983 }
984
985 return user;
986 }
987
988 User *
989 daemon_local_get_automatic_login_user (Daemon *daemon)
990 {
991 DaemonPrivate *priv = daemon_get_instance_private (daemon);
992 return priv->autologin;
993 }
994
995 static gboolean
996 daemon_find_user_by_id (AccountsAccounts *accounts,
997 GDBusMethodInvocation *context,
998 gint64 uid)
999 {
1000 Daemon *daemon = (Daemon*)accounts;
1001 User *user;
1002
1003 user = daemon_local_find_user_by_id (daemon, uid);
1004
1005 if (user) {
1006 accounts_accounts_complete_find_user_by_id (NULL, context, user_get_object_path (user));
1007 }
1008 else {
1009 throw_error (context, ERROR_FAILED, "Failed to look up user with uid %d.", (int)uid);
1010 }
1011
1012 return TRUE;
1013 }
1014
1015 static gboolean
1016 daemon_find_user_by_name (AccountsAccounts *accounts,
1017 GDBusMethodInvocation *context,
1018 const gchar *name)
1019 {
1020 Daemon *daemon = (Daemon*)accounts;
1021 User *user;
1022
1023 user = daemon_local_find_user_by_name (daemon, name);
1024
1025 if (user) {
1026 accounts_accounts_complete_find_user_by_name (NULL, context, user_get_object_path (user));
1027 }
1028 else {
1029 throw_error (context, ERROR_FAILED, "Failed to look up user with name %s.", name);
1030 }
1031
1032 return TRUE;
1033 }
1034
1035 static ListUserData *
1036 list_user_data_new (Daemon *daemon,
1037 GDBusMethodInvocation *context)
1038 {
1039 ListUserData *data;
1040
1041 data = g_new0 (ListUserData, 1);
1042
1043 data->daemon = g_object_ref (daemon);
1044 data->context = context;
1045
1046 return data;
1047 }
1048
1049 static void
1050 list_user_data_free (ListUserData *data)
1051 {
1052 g_object_unref (data->daemon);
1053 g_free (data);
1054 }
1055
1056 static void
1057 finish_list_cached_users (ListUserData *data)
1058 {
1059 DaemonPrivate *priv = daemon_get_instance_private (data->daemon);
1060 g_autoptr(GPtrArray) object_paths = NULL;
1061 GHashTableIter iter;
1062 gpointer key, value;
1063 uid_t uid;
1064 const gchar *shell;
1065
1066 object_paths = g_ptr_array_new ();
1067
1068 g_hash_table_iter_init (&iter, priv->users);
1069 while (g_hash_table_iter_next (&iter, &key, &value)) {
1070 const gchar *name = key;
1071 User *user = value;
1072
1073 uid = user_get_uid (user);
1074 shell = user_get_shell (user);
1075
1076 if (!user_classify_is_human (uid, name, shell, NULL)) {
1077 g_debug ("user %s %ld excluded", name, (long) uid);
1078 continue;
1079 }
1080
1081 if (!user_get_cached (user)) {
1082 g_debug ("user %s %ld not cached", name, (long) uid);
1083 continue;
1084 }
1085
1086 g_debug ("user %s %ld not excluded", name, (long) uid);
1087 g_ptr_array_add (object_paths, (gpointer) user_get_object_path (user));
1088 }
1089 g_ptr_array_add (object_paths, NULL);
1090
1091 accounts_accounts_complete_list_cached_users (NULL, data->context, (const gchar * const *) object_paths->pdata);
1092
1093 list_user_data_free (data);
1094 }
1095
1096 static gboolean
1097 daemon_list_cached_users (AccountsAccounts *accounts,
1098 GDBusMethodInvocation *context)
1099 {
1100 Daemon *daemon = (Daemon*)accounts;
1101 DaemonPrivate *priv = daemon_get_instance_private (daemon);
1102 ListUserData *data;
1103
1104 data = list_user_data_new (daemon, context);
1105
1106 if (priv->reload_id > 0) {
1107 /* reload pending -- finish call in reload_users_timeout */
1108 g_queue_push_tail (priv->pending_list_cached_users, data);
1109 }
1110 else {
1111 finish_list_cached_users (data);
1112 }
1113
1114 return TRUE;
1115 }
1116
1117 static const gchar *
1118 daemon_get_daemon_version (AccountsAccounts *object)
1119 {
1120 return VERSION;
1121 }
1122
1123 static void
1124 cache_user (Daemon *daemon,
1125 User *user)
1126 {
1127 g_autofree gchar *filename = NULL;
1128 const gchar *user_name;
1129
1130 /* Always use the canonical user name looked up */
1131 user_name = user_get_user_name (user);
1132
1133 filename = g_build_filename (USERDIR, user_name, NULL);
1134 if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
1135 user_save (user);
1136 }
1137 }
1138
1139 typedef struct {
1140 gchar *user_name;
1141 gchar *real_name;
1142 gint account_type;
1143 } CreateUserData;
1144
1145 static void
1146 create_data_free (gpointer data)
1147 {
1148 CreateUserData *cd = data;
1149
1150 g_free (cd->user_name);
1151 g_free (cd->real_name);
1152 g_free (cd);
1153 }
1154
1155 static void
1156 daemon_create_user_authorized_cb (Daemon *daemon,
1157 User *dummy,
1158 GDBusMethodInvocation *context,
1159 gpointer data)
1160
1161 {
1162 CreateUserData *cd = data;
1163 User *user;
1164 g_autoptr(GError) error = NULL;
1165 const gchar *argv[9];
1166 g_autofree gchar *admin_groups = NULL;
1167
1168 if (getpwnam (cd->user_name) != NULL) {
1169 throw_error (context, ERROR_USER_EXISTS, "A user with name '%s' already exists", cd->user_name);
1170 return;
1171 }
1172
1173 sys_log (context, "create user '%s'", cd->user_name);
1174
1175 argv[0] = "/usr/sbin/pw";
1176 argv[1] = "useradd";
1177 argv[2] = cd->user_name;
1178 argv[3] = "-m";
1179 argv[4] = "-c";
1180 argv[5] = cd->real_name;
1181 if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) {
1182 if (EXTRA_ADMIN_GROUPS != NULL && EXTRA_ADMIN_GROUPS[0] != '\0')
1183 admin_groups = g_strconcat (ADMIN_GROUP, ",",
1184 EXTRA_ADMIN_GROUPS, NULL);
1185 else
1186 admin_groups = g_strdup (ADMIN_GROUP);
1187
1188 argv[6] = "-G";
1189 argv[7] = admin_groups;
1190 argv[8] = NULL;
1191 }
1192 else if (cd->account_type == ACCOUNT_TYPE_STANDARD) {
1193 argv[6] = NULL;
1194 }
1195 else {
1196 throw_error (context, ERROR_FAILED, "Don't know how to add user of type %d", cd->account_type);
1197 return;
1198 }
1199
1200 if (!spawn_with_login_uid (context, argv, &error)) {
1201 throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
1202 return;
1203 }
1204
1205 user = daemon_local_find_user_by_name (daemon, cd->user_name);
1206 user_update_local_account_property (user, TRUE);
1207 user_update_system_account_property (user, FALSE);
1208
1209 cache_user (daemon, user);
1210
1211 accounts_accounts_complete_create_user (NULL, context, user_get_object_path (user));
1212 }
1213
1214 static gboolean
1215 daemon_create_user (AccountsAccounts *accounts,
1216 GDBusMethodInvocation *context,
1217 const gchar *user_name,
1218 const gchar *real_name,
1219 gint account_type)
1220 {
1221 Daemon *daemon = (Daemon*)accounts;
1222 CreateUserData *data;
1223
1224 data = g_new0 (CreateUserData, 1);
1225 data->user_name = g_strdup (user_name);
1226 data->real_name = g_strdup (real_name);
1227 data->account_type = account_type;
1228
1229 daemon_local_check_auth (daemon,
1230 NULL,
1231 "org.freedesktop.accounts.user-administration",
1232 TRUE,
1233 daemon_create_user_authorized_cb,
1234 context,
1235 data,
1236 (GDestroyNotify)create_data_free);
1237
1238 return TRUE;
1239 }
1240
1241 static void
1242 daemon_cache_user_authorized_cb (Daemon *daemon,
1243 User *dummy,
1244 GDBusMethodInvocation *context,
1245 gpointer data)
1246 {
1247 const gchar *user_name = data;
1248 User *user;
1249
1250 sys_log (context, "cache user '%s'", user_name);
1251
1252 user = daemon_local_find_user_by_name (daemon, user_name);
1253 if (user == NULL) {
1254 throw_error (context, ERROR_USER_DOES_NOT_EXIST,
1255 "No user with the name %s found", user_name);
1256 return;
1257 }
1258
1259 user_update_system_account_property (user, FALSE);
1260
1261 cache_user (daemon, user);
1262
1263 accounts_accounts_complete_cache_user (NULL, context, user_get_object_path (user));
1264 }
1265
1266 static gboolean
1267 daemon_cache_user (AccountsAccounts *accounts,
1268 GDBusMethodInvocation *context,
1269 const gchar *user_name)
1270 {
1271 Daemon *daemon = (Daemon*)accounts;
1272
1273 /* Can't have a slash in the user name */
1274 if (strchr (user_name, '/') != NULL) {
1275 g_dbus_method_invocation_return_error (context, G_DBUS_ERROR,
1276 G_DBUS_ERROR_INVALID_ARGS,
1277 "Invalid user name: %s", user_name);
1278 return TRUE;
1279 }
1280
1281 daemon_local_check_auth (daemon,
1282 NULL,
1283 "org.freedesktop.accounts.user-administration",
1284 TRUE,
1285 daemon_cache_user_authorized_cb,
1286 context,
1287 g_strdup (user_name),
1288 g_free);
1289
1290 return TRUE;
1291 }
1292
1293 static void
1294 daemon_uncache_user_authorized_cb (Daemon *daemon,
1295 User *dummy,
1296 GDBusMethodInvocation *context,
1297 gpointer data)
1298 {
1299 const gchar *user_name = data;
1300 User *user;
1301
1302 sys_log (context, "uncache user '%s'", user_name);
1303
1304 user = daemon_local_find_user_by_name (daemon, user_name);
1305 if (user == NULL) {
1306 throw_error (context, ERROR_USER_DOES_NOT_EXIST,
1307 "No user with the name %s found", user_name);
1308 return;
1309 }
1310
1311 /* Always use the canonical user name looked up */
1312 user_name = user_get_user_name (user);
1313
1314 remove_cache_files (user_name);
1315
1316 user_set_saved (user, FALSE);
1317 user_set_cached (user, FALSE);
1318
1319 accounts_accounts_complete_uncache_user (NULL, context);
1320
1321 queue_reload_users (daemon);
1322 }
1323
1324 static gboolean
1325 daemon_uncache_user (AccountsAccounts *accounts,
1326 GDBusMethodInvocation *context,
1327 const gchar *user_name)
1328 {
1329 Daemon *daemon = (Daemon*)accounts;
1330
1331 daemon_local_check_auth (daemon,
1332 NULL,
1333 "org.freedesktop.accounts.user-administration",
1334 TRUE,
1335 daemon_uncache_user_authorized_cb,
1336 context,
1337 g_strdup (user_name),
1338 g_free);
1339
1340 return TRUE;
1341 }
1342
1343 typedef struct {
1344 uid_t uid;
1345 gboolean remove_files;
1346 } DeleteUserData;
1347
1348 static void
1349 daemon_delete_user_authorized_cb (Daemon *daemon,
1350 User *dummy,
1351 GDBusMethodInvocation *context,
1352 gpointer data)
1353
1354 {
1355 DaemonPrivate *priv = daemon_get_instance_private (daemon);
1356 DeleteUserData *ud = data;
1357 g_autoptr(GError) error = NULL;
1358 struct passwd *pwent;
1359 const gchar *argv[5];
1360 User *user;
1361
1362 pwent = getpwuid (ud->uid);
1363
1364 if (pwent == NULL) {
1365 throw_error (context, ERROR_USER_DOES_NOT_EXIST, "No user with uid %d found", ud->uid);
1366 return;
1367 }
1368
1369 sys_log (context, "delete user '%s' (%d)", pwent->pw_name, ud->uid);
1370
1371 user = daemon_local_find_user_by_id (daemon, ud->uid);
1372
1373 if (user != NULL) {
1374 user_set_cached (user, FALSE);
1375
1376 if (priv->autologin == user) {
1377 daemon_local_set_automatic_login (daemon, user, FALSE, NULL);
1378 }
1379 }
1380
1381 remove_cache_files (pwent->pw_name);
1382
1383 user_set_saved (user, FALSE);
1384
1385 argv[0] = "/usr/sbin/pw";
1386 argv[1] = "userdel";
1387 if (ud->remove_files) {
1388 argv[2] = pwent->pw_name;
1389 argv[3] = "-r";
1390 argv[4] = NULL;
1391 }
1392 else {
1393 argv[2] = pwent->pw_name;
1394 argv[3] = NULL;
1395 }
1396
1397 if (!spawn_with_login_uid (context, argv, &error)) {
1398 throw_error (context, ERROR_FAILED, "running '%s' failed: %s", argv[0], error->message);
1399 return;
1400 }
1401
1402 accounts_accounts_complete_delete_user (NULL, context);
1403 }
1404
1405
1406 static gboolean
1407 daemon_delete_user (AccountsAccounts *accounts,
1408 GDBusMethodInvocation *context,
1409 gint64 uid,
1410 gboolean remove_files)
1411 {
1412 Daemon *daemon = (Daemon*)accounts;
1413 DeleteUserData *data;
1414
1415 if ((uid_t)uid == 0) {
1416 throw_error (context, ERROR_FAILED, "Refuse to delete root user");
1417 return TRUE;
1418 }
1419
1420 data = g_new0 (DeleteUserData, 1);
1421 data->uid = (uid_t)uid;
1422 data->remove_files = remove_files;
1423
1424 daemon_local_check_auth (daemon,
1425 NULL,
1426 "org.freedesktop.accounts.user-administration",
1427 TRUE,
1428 daemon_delete_user_authorized_cb,
1429 context,
1430 data,
1431 (GDestroyNotify)g_free);
1432
1433 return TRUE;
1434 }
1435
1436 typedef struct {
1437 Daemon *daemon;
1438 User *user;
1439 AuthorizedCallback authorized_cb;
1440 GDBusMethodInvocation *context;
1441 gpointer data;
1442 GDestroyNotify destroy_notify;
1443 } CheckAuthData;
1444
1445 static void
1446 check_auth_data_free (CheckAuthData *data)
1447 {
1448 g_object_unref (data->daemon);
1449
1450 if (data->user)
1451 g_object_unref (data->user);
1452
1453 if (data->destroy_notify)
1454 (*data->destroy_notify) (data->data);
1455
1456 g_free (data);
1457 }
1458
1459 static void
1460 check_auth_cb (PolkitAuthority *authority,
1461 GAsyncResult *res,
1462 gpointer data)
1463 {
1464 CheckAuthData *cad = data;
1465 PolkitAuthorizationResult *result;
1466 g_autoptr(GError) error = NULL;
1467 gboolean is_authorized = FALSE;
1468
1469 result = polkit_authority_check_authorization_finish (authority, res, &error);
1470 if (error) {
1471 throw_error (cad->context, ERROR_PERMISSION_DENIED, "Not authorized: %s", error->message);
1472 }
1473 else {
1474 if (polkit_authorization_result_get_is_authorized (result)) {
1475 is_authorized = TRUE;
1476 }
1477 else if (polkit_authorization_result_get_is_challenge (result)) {
1478 throw_error (cad->context, ERROR_PERMISSION_DENIED, "Authentication is required");
1479 }
1480 else {
1481 throw_error (cad->context, ERROR_PERMISSION_DENIED, "Not authorized");
1482 }
1483
1484 g_object_unref (result);
1485 }
1486
1487 if (is_authorized) {
1488 (* cad->authorized_cb) (cad->daemon,
1489 cad->user,
1490 cad->context,
1491 cad->data);
1492 }
1493
1494 check_auth_data_free (data);
1495 }
1496
1497 void
1498 daemon_local_check_auth (Daemon *daemon,
1499 User *user,
1500 const gchar *action_id,
1501 gboolean allow_interaction,
1502 AuthorizedCallback authorized_cb,
1503 GDBusMethodInvocation *context,
1504 gpointer authorized_cb_data,
1505 GDestroyNotify destroy_notify)
1506 {
1507 DaemonPrivate *priv = daemon_get_instance_private (daemon);
1508 CheckAuthData *data;
1509 PolkitSubject *subject;
1510 PolkitCheckAuthorizationFlags flags;
1511
1512 data = g_new0 (CheckAuthData, 1);
1513 data->daemon = g_object_ref (daemon);
1514 if (user)
1515 data->user = g_object_ref (user);
1516 data->context = context;
1517 data->authorized_cb = authorized_cb;
1518 data->data = authorized_cb_data;
1519 data->destroy_notify = destroy_notify;
1520
1521 subject = polkit_system_bus_name_new (g_dbus_method_invocation_get_sender (context));
1522
1523 flags = POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE;
1524 if (allow_interaction)
1525 flags |= POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION;
1526 polkit_authority_check_authorization (priv->authority,
1527 subject,
1528 action_id,
1529 NULL,
1530 flags,
1531 NULL,
1532 (GAsyncReadyCallback) check_auth_cb,
1533 data);
1534
1535 g_object_unref (subject);
1536 }
1537
1538 gboolean
1539 load_autologin (Daemon *daemon,
1540 gchar **name,
1541 gboolean *enabled,
1542 GError **error)
1543 {
1544 g_autoptr(GKeyFile) keyfile = NULL;
1545 GError *local_error = NULL;
1546 g_autofree gchar *string = NULL;
1547
1548 keyfile = g_key_file_new ();
1549 if (!g_key_file_load_from_file (keyfile,
1550 PATH_GDM_CUSTOM,
1551 G_KEY_FILE_KEEP_COMMENTS,
1552 error)) {
1553 return FALSE;
1554 }
1555
1556 string = g_key_file_get_string (keyfile, "daemon", "AutomaticLoginEnable", &local_error);
1557 if (local_error) {
1558 g_propagate_error (error, local_error);
1559 return FALSE;
1560 }
1561 if (string != NULL && (g_ascii_strcasecmp (string, "true") == 0 || strcmp (string, "1") == 0)) {
1562 *enabled = TRUE;
1563 }
1564 else {
1565 *enabled = FALSE;
1566 }
1567
1568 *name = g_key_file_get_string (keyfile, "daemon", "AutomaticLogin", &local_error);
1569 if (local_error) {
1570 g_propagate_error (error, local_error);
1571 return FALSE;
1572 }
1573
1574 return TRUE;
1575 }
1576
1577 static gboolean
1578 save_autologin (Daemon *daemon,
1579 const gchar *name,
1580 gboolean enabled,
1581 GError **error)
1582 {
1583 g_autoptr(GKeyFile) keyfile = NULL;
1584 g_autofree gchar *data = NULL;
1585 gboolean result;
1586
1587 keyfile = g_key_file_new ();
1588 if (!g_key_file_load_from_file (keyfile,
1589 PATH_GDM_CUSTOM,
1590 G_KEY_FILE_KEEP_COMMENTS,
1591 error)) {
1592 return FALSE;
1593 }
1594
1595 g_key_file_set_string (keyfile, "daemon", "AutomaticLoginEnable", enabled ? "True" : "False");
1596 g_key_file_set_string (keyfile, "daemon", "AutomaticLogin", name);
1597
1598 data = g_key_file_to_data (keyfile, NULL, NULL);
1599 result = g_file_set_contents (PATH_GDM_CUSTOM, data, -1, error);
1600
1601 return result;
1602 }
1603
1604 gboolean
1605 daemon_local_set_automatic_login (Daemon *daemon,
1606 User *user,
1607 gboolean enabled,
1608 GError **error)
1609 {
1610 DaemonPrivate *priv = daemon_get_instance_private (daemon);
1611
1612 if (priv->autologin == user && enabled) {
1613 return TRUE;
1614 }
1615
1616 if (priv->autologin != user && !enabled) {
1617 return TRUE;
1618 }
1619
1620 if (!save_autologin (daemon, user_get_user_name (user), enabled, error)) {
1621 return FALSE;
1622 }
1623
1624 if (priv->autologin != NULL) {
1625 g_object_set (priv->autologin, "automatic-login", FALSE, NULL);
1626 g_signal_emit_by_name (priv->autologin, "changed", 0);
1627 g_clear_object (&priv->autologin);
1628 }
1629
1630 if (enabled) {
1631 g_object_set (user, "automatic-login", TRUE, NULL);
1632 g_signal_emit_by_name (user, "changed", 0);
1633 g_object_ref (user);
1634 priv->autologin = user;
1635 }
1636
1637 return TRUE;
1638 }
1639
1640 GHashTable *
1641 daemon_get_extension_ifaces (Daemon *daemon)
1642 {
1643 DaemonPrivate *priv = daemon_get_instance_private (daemon);
1644 return priv->extension_ifaces;
1645 }
1646
1647 static void
1648 get_property (GObject *object,
1649 guint prop_id,
1650 GValue *value,
1651 GParamSpec *pspec)
1652 {
1653 switch (prop_id) {
1654 case PROP_DAEMON_VERSION:
1655 g_value_set_string (value, VERSION);
1656 break;
1657
1658 default:
1659 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1660 break;
1661 }
1662 }
1663
1664 static void
1665 set_property (GObject *object,
1666 guint prop_id,
1667 const GValue *value,
1668 GParamSpec *pspec)
1669 {
1670 switch (prop_id) {
1671 case PROP_DAEMON_VERSION:
1672 g_assert_not_reached ();
1673 break;
1674
1675 default:
1676 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1677 break;
1678 }
1679 }
1680
1681 static void
1682 daemon_class_init (DaemonClass *klass)
1683 {
1684 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1685
1686 object_class->finalize = daemon_finalize;
1687 object_class->get_property = get_property;
1688 object_class->set_property = set_property;
1689
1690 g_object_class_override_property (object_class,
1691 PROP_DAEMON_VERSION,
1692 "daemon-version");
1693 }
1694
1695 static void
1696 daemon_accounts_accounts_iface_init (AccountsAccountsIface *iface)
1697 {
1698 iface->handle_create_user = daemon_create_user;
1699 iface->handle_delete_user = daemon_delete_user;
1700 iface->handle_find_user_by_id = daemon_find_user_by_id;
1701 iface->handle_find_user_by_name = daemon_find_user_by_name;
1702 iface->handle_list_cached_users = daemon_list_cached_users;
1703 iface->get_daemon_version = daemon_get_daemon_version;
1704 iface->handle_cache_user = daemon_cache_user;
1705 iface->handle_uncache_user = daemon_uncache_user;
1706 }
1707