1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28
#include <sys/types.h>
38
#include <glib/gi18n.h>
39
#include <glib/gstdio.h>
40
#include <glib-object.h>
42
#define DBUS_API_SUBJECT_TO_CHANGE
43
#include <dbus/dbus-glib.h>
44
#include <dbus/dbus-glib-lowlevel.h>
46
#include "gdm-manager.h"
48
#include "gdm-common.h"
49
#include "gdm-signal-handler.h"
51
#include "gdm-settings.h"
52
#include "gdm-settings-direct.h"
53
#include "gdm-settings-keys.h"
55
#define GDM_DBUS_NAME "org.gnome.DisplayManager"
57
static void bus_proxy_destroyed_cb (DBusGProxy *bus_proxy,
58
GdmManager **managerp);
60
extern char **environ;
62
static GdmManager *manager = NULL;
63
static GdmSettings *settings = NULL;
64
static uid_t gdm_uid = -1;
65
static gid_t gdm_gid = -1;
68
timed_exit_cb (GMainLoop *loop)
70
g_main_loop_quit (loop);
75
get_bus_proxy (DBusGConnection *connection)
77
DBusGProxy *bus_proxy;
79
bus_proxy = dbus_g_proxy_new_for_name (connection,
87
acquire_name_on_proxy (DBusGProxy *bus_proxy)
96
if (bus_proxy == NULL) {
101
res = dbus_g_proxy_call (bus_proxy,
104
G_TYPE_STRING, GDM_DBUS_NAME,
107
G_TYPE_UINT, &result,
111
g_warning ("Failed to acquire %s: %s", GDM_DBUS_NAME, error->message);
112
g_error_free (error);
114
g_warning ("Failed to acquire %s", GDM_DBUS_NAME);
119
if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
121
g_warning ("Failed to acquire %s: %s", GDM_DBUS_NAME, error->message);
122
g_error_free (error);
124
g_warning ("Failed to acquire %s", GDM_DBUS_NAME);
135
static DBusGConnection *
136
get_system_bus (void)
139
DBusGConnection *bus;
140
DBusConnection *connection;
143
bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
145
g_warning ("Couldn't connect to system bus: %s",
147
g_error_free (error);
151
connection = dbus_g_connection_get_connection (bus);
152
dbus_connection_set_exit_on_disconnect (connection, FALSE);
159
bus_reconnect (GdmManager *manager)
161
DBusGConnection *bus;
162
DBusGProxy *bus_proxy;
167
bus = get_system_bus ();
172
bus_proxy = get_bus_proxy (bus);
173
if (bus_proxy == NULL) {
174
g_warning ("Could not construct bus_proxy object; will retry");
178
if (! acquire_name_on_proxy (bus_proxy) ) {
179
g_warning ("Could not acquire name; will retry");
183
manager = gdm_manager_new ();
184
if (manager == NULL) {
185
g_warning ("Could not construct manager object");
189
g_signal_connect (bus_proxy,
191
G_CALLBACK (bus_proxy_destroyed_cb),
194
g_debug ("Successfully reconnected to D-Bus");
196
gdm_manager_start (manager);
205
bus_proxy_destroyed_cb (DBusGProxy *bus_proxy,
206
GdmManager **managerp)
208
g_debug ("Disconnected from D-Bus");
210
if (managerp == NULL || *managerp == NULL) {
211
/* probably shutting down or something */
215
g_object_unref (*managerp);
218
g_timeout_add_seconds (3, (GSourceFunc)bus_reconnect, managerp);
224
g_unlink (GDM_PID_FILE);
235
pf = open (GDM_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
237
g_warning (_("Cannot write PID file %s: possibly out of diskspace: %s"),
244
snprintf (pid, sizeof (pid), "%lu\n", (long unsigned) getpid ());
246
written = write (pf, pid, strlen (pid));
250
g_warning (_("Cannot write PID file %s: possibly out of diskspace: %s"),
256
g_atexit (delete_pid);
264
const char *log_path;
268
r = g_stat (log_path, &statbuf);
269
if (r < 0 || ! S_ISDIR (statbuf.st_mode)) {
270
if (g_mkdir (log_path, 0755) < 0) {
271
gdm_fail (_("Logdir %s does not exist or isn't a directory."),
274
g_chmod (log_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
279
check_servauthdir (const char *auth_path,
280
struct stat *statbuf)
284
/* Enter paranoia mode */
285
r = g_stat (auth_path, statbuf);
287
gdm_fail (_("Authdir %s does not exist. Aborting."), auth_path);
290
if (! S_ISDIR (statbuf->st_mode)) {
291
gdm_fail (_("Authdir %s is not a directory. Aborting."), auth_path);
296
set_effective_user (uid_t uid)
302
if (geteuid () != uid) {
307
g_error ("Cannot set uid to %d: %s",
314
set_effective_group (gid_t gid)
319
if (getegid () != gid) {
324
g_error ("Cannot set gid to %d: %s",
331
set_effective_user_group (uid_t uid,
334
set_effective_user (0);
335
set_effective_group (gid);
337
set_effective_user (0);
342
gdm_daemon_check_permissions (uid_t uid,
346
const char *auth_path;
350
/* Enter paranoia mode */
351
check_servauthdir (auth_path, &statbuf);
353
set_effective_user_group (0, 0);
355
/* Now set things up for us as */
356
chown (auth_path, 0, gid);
357
g_chmod (auth_path, (S_IRWXU|S_IRWXG|S_ISVTX));
359
set_effective_user_group (uid, gid);
362
check_servauthdir (auth_path, &statbuf);
364
if G_UNLIKELY (statbuf.st_uid != 0 || statbuf.st_gid != gid) {
365
gdm_fail (_("Authdir %s is not owned by user %d, group %d. Aborting."),
371
if G_UNLIKELY (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX)) {
372
gdm_fail (_("Authdir %s has wrong permissions %o. Should be %o. Aborting."),
375
(S_IRWXU|S_IRWXG|S_ISVTX));
380
gdm_daemon_change_user (uid_t *uidp,
387
struct passwd *pwent;
395
gdm_settings_direct_get_string (GDM_KEY_USER, &username);
396
gdm_settings_direct_get_string (GDM_KEY_GROUP, &groupname);
398
if (username == NULL || groupname == NULL) {
402
g_debug ("Changing user:group to %s:%s", username, groupname);
404
/* Lookup user and groupid for the GDM user */
405
pwent = getpwnam (username);
407
/* Set uid and gid */
408
if G_UNLIKELY (pwent == NULL) {
409
gdm_fail (_("Can't find the GDM user '%s'. Aborting!"), username);
414
if G_UNLIKELY (uid == 0) {
415
gdm_fail (_("The GDM user should not be root. Aborting!"));
418
grent = getgrnam (groupname);
420
if G_UNLIKELY (grent == NULL) {
421
gdm_fail (_("Can't find the GDM group '%s'. Aborting!"), groupname);
426
if G_UNLIKELY (gid == 0) {
427
gdm_fail (_("The GDM group should not be root. Aborting!"));
430
/* gid remains 'gdm' */
431
set_effective_user_group (uid, gid);
446
signal_cb (int signo,
451
g_debug ("Got callback for signal %d", signo);
458
/* let the fatal signals interrupt us */
459
g_debug ("Caught signal %d, shutting down abnormally.", signo);
466
/* let the fatal signals interrupt us */
467
g_debug ("Caught signal %d, shutting down normally.", signo);
473
g_debug ("Got HUP signal");
475
* Reread config stuff like system config files, VPN service files, etc
482
g_debug ("Got USR1 signal");
484
* Play with log levels or something
488
gdm_log_toggle_debug ();
493
g_debug ("Caught unhandled signal %d", signo);
505
gboolean debug = FALSE;
507
/* enable debugging for unstable builds */
508
if (gdm_is_version_unstable ()) {
512
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
520
GMainLoop *main_loop;
521
GOptionContext *context;
522
DBusGProxy *bus_proxy;
523
DBusGConnection *connection;
527
gboolean xdmcp_enabled;
528
GdmSignalHandler *signal_handler;
529
static gboolean do_timed_exit = FALSE;
530
static gboolean print_version = FALSE;
531
static gboolean fatal_warnings = FALSE;
532
static GOptionEntry entries [] = {
533
{ "fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &fatal_warnings, N_("Make all warnings fatal"), NULL },
534
{ "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time - for debugging"), NULL },
535
{ "version", 0, 0, G_OPTION_ARG_NONE, &print_version, N_("Print GDM version"), NULL },
540
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
541
textdomain (GETTEXT_PACKAGE);
542
setlocale (LC_ALL, "");
546
gdm_set_fatal_warnings_if_unstable ();
550
context = g_option_context_new (_("GNOME Display Manager"));
551
g_option_context_add_main_entries (context, entries, NULL);
552
g_option_context_set_ignore_unknown_options (context, TRUE);
555
res = g_option_context_parse (context, &argc, &argv, &error);
556
g_option_context_free (context);
558
g_warning ("%s", error->message);
559
g_error_free (error);
563
if (fatal_warnings) {
564
GLogLevelFlags fatal_mask;
566
fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
567
fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
568
g_log_set_always_fatal (fatal_mask);
571
connection = get_system_bus ();
572
if (connection == NULL) {
576
bus_proxy = get_bus_proxy (connection);
577
if (bus_proxy == NULL) {
578
g_warning ("Could not construct bus_proxy object; bailing out");
582
if (! acquire_name_on_proxy (bus_proxy) ) {
583
g_warning ("Could not acquire name; bailing out");
589
settings = gdm_settings_new ();
590
if (settings == NULL) {
591
g_warning ("Unable to initialize settings");
595
if (! gdm_settings_direct_init (settings, GDMCONFDIR "/gdm.schemas", "/")) {
596
g_warning ("Unable to initialize settings");
600
gdm_log_set_debug (is_debug_set ());
602
gdm_daemon_change_user (&gdm_uid, &gdm_gid);
603
gdm_daemon_check_permissions (gdm_uid, gdm_gid);
605
set_effective_user_group (0, 0);
608
/* XDM compliant error message */
609
if (getuid () != 0) {
610
/* make sure the pid file doesn't get wiped */
611
g_warning (_("Only the root user can run GDM"));
621
manager = gdm_manager_new ();
623
if (manager == NULL) {
627
xdmcp_enabled = FALSE;
628
gdm_settings_direct_get_boolean (GDM_KEY_XDMCP_ENABLE, &xdmcp_enabled);
629
gdm_manager_set_xdmcp_enabled (manager, xdmcp_enabled);
631
g_signal_connect (bus_proxy,
633
G_CALLBACK (bus_proxy_destroyed_cb),
636
main_loop = g_main_loop_new (NULL, FALSE);
638
signal_handler = gdm_signal_handler_new ();
639
gdm_signal_handler_set_fatal_func (signal_handler,
640
(GDestroyNotify)g_main_loop_quit,
642
gdm_signal_handler_add_fatal (signal_handler);
643
gdm_signal_handler_add (signal_handler, SIGTERM, signal_cb, NULL);
644
gdm_signal_handler_add (signal_handler, SIGINT, signal_cb, NULL);
645
gdm_signal_handler_add (signal_handler, SIGFPE, signal_cb, NULL);
646
gdm_signal_handler_add (signal_handler, SIGHUP, signal_cb, NULL);
647
gdm_signal_handler_add (signal_handler, SIGUSR1, signal_cb, NULL);
650
g_timeout_add_seconds (30, (GSourceFunc) timed_exit_cb, main_loop);
653
gdm_manager_start (manager);
655
g_main_loop_run (main_loop);
657
g_debug ("GDM finished, cleaning up...");
659
if (manager != NULL) {
660
g_object_unref (manager);
663
if (settings != NULL) {
664
g_object_unref (settings);
667
if (signal_handler != NULL) {
668
g_object_unref (signal_handler);
671
gdm_settings_direct_shutdown ();
674
g_main_loop_unref (main_loop);