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