2 * Copyright (C) 2008-2010 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Author: David Zeuthen <davidz@redhat.com>
26 #include <glib-unix.h>
31 #include <polkit/polkit.h>
32 #include <polkitbackend/polkitbackend.h>
34 /* ---------------------------------------------------------------------------------------------------- */
36 static PolkitBackendAuthority *authority = NULL;
37 static gpointer registration_id = NULL;
38 static GMainLoop *loop = NULL;
39 static gboolean opt_replace = FALSE;
40 static gboolean opt_no_debug = FALSE;
41 static GOptionEntry opt_entries[] = {
42 {"replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, "Replace existing daemon", NULL},
43 {"no-debug", 'n', 0, G_OPTION_ARG_NONE, &opt_no_debug, "Don't print debug information", NULL},
48 on_bus_acquired (GDBusConnection *connection,
54 g_print ("Connected to the system bus\n");
56 g_assert (authority == NULL);
57 g_assert (registration_id == NULL);
59 authority = polkit_backend_authority_get ();
60 g_print ("Using authority class %s\n", g_type_name (G_TYPE_FROM_INSTANCE (authority)));
63 registration_id = polkit_backend_authority_register (authority,
65 "/org/freedesktop/PolicyKit1/Authority",
67 if (registration_id == NULL)
69 g_printerr ("Error registering authority: %s\n", error->message);
71 g_main_loop_quit (loop); /* exit */
76 on_name_lost (GDBusConnection *connection,
80 g_print ("Lost the name org.freedesktop.PolicyKit1 - exiting\n");
81 g_main_loop_quit (loop);
85 on_name_acquired (GDBusConnection *connection,
89 g_print ("Acquired the name org.freedesktop.PolicyKit1\n");
93 on_sigint (gpointer user_data)
95 g_print ("Handling SIGINT\n");
96 g_main_loop_quit (loop);
101 become_user (const gchar *user,
104 gboolean ret = FALSE;
107 g_return_val_if_fail (user != NULL, FALSE);
108 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
110 pw = getpwnam (user);
113 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
114 "Error calling getpwnam(): %m");
118 if (setgroups (0, NULL) != 0)
120 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
121 "Error clearing groups: %m");
124 if (initgroups (pw->pw_name, pw->pw_gid) != 0)
126 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
127 "Error initializing groups: %m");
131 setregid (pw->pw_gid, pw->pw_gid);
132 setreuid (pw->pw_uid, pw->pw_uid);
133 if ((geteuid () != pw->pw_uid) || (getuid () != pw->pw_uid) ||
134 (getegid () != pw->pw_gid) || (getgid () != pw->pw_gid))
136 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
137 "Error becoming real+effective uid %d and gid %d: %m",
138 (int) pw->pw_uid, (int) pw->pw_gid);
142 if (chdir (pw->pw_dir) != 0)
144 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
145 "Error changing to home directory %s: %m",
162 GOptionContext *opt_context;
172 registration_id = NULL;
176 opt_context = g_option_context_new ("polkit system daemon");
177 g_option_context_add_main_entries (opt_context, opt_entries, NULL);
179 if (!g_option_context_parse (opt_context, &argc, &argv, &error))
181 g_printerr ("Error parsing options: %s", error->message);
182 g_error_free (error);
186 /* If --no-debug is requested don't clutter stdout/stderr etc.
191 dev_null_fd = open ("/dev/null", O_RDWR);
192 if (dev_null_fd >= 0)
194 dup2 (dev_null_fd, STDIN_FILENO);
195 dup2 (dev_null_fd, STDOUT_FILENO);
196 dup2 (dev_null_fd, STDERR_FILENO);
201 g_warning ("Error opening /dev/null: %m");
206 if (!become_user (POLKITD_USER, &error))
208 g_printerr ("Error switcing to user %s: %s\n",
209 POLKITD_USER, error->message);
210 g_clear_error (&error);
214 g_print ("Successfully changed to user %s\n", POLKITD_USER);
216 if (g_getenv ("PATH") == NULL)
217 g_setenv ("PATH", "/usr/bin:/bin:/usr/sbin:/sbin", TRUE);
219 loop = g_main_loop_new (NULL, FALSE);
221 sigint_id = g_unix_signal_add (SIGINT,
225 name_owner_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
226 "org.freedesktop.PolicyKit1",
227 G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
228 (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
235 g_print ("Entering main event loop\n");
236 g_main_loop_run (loop);
240 g_print ("Shutting down\n");
243 g_source_remove (sigint_id);
244 if (name_owner_id != 0)
245 g_bus_unown_name (name_owner_id);
246 if (registration_id != NULL)
247 polkit_backend_authority_unregister (registration_id);
248 if (authority != NULL)
249 g_object_unref (authority);
251 g_main_loop_unref (loop);
252 if (opt_context != NULL)
253 g_option_context_free (opt_context);
255 g_print ("Exiting with code %d\n", ret);