~noskcaj/ubuntu/vivid/gdm/3.14.1

« back to all changes in this revision

Viewing changes to .pc/ubuntu_ensure_dirs.patch/daemon/main.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha, Tim Lunn, Jeremy Bicha, Robert Ancell
  • Date: 2013-05-31 22:36:08 UTC
  • mfrom: (1.4.55)
  • Revision ID: package-import@ubuntu.com-20130531223608-33uo85niksee5460
Tags: 3.8.1.1-0ubuntu1
[ Tim Lunn ]
* New upstream release
* debian/patches/ubuntu_dont_catch_sigsegv.patch:
  - Dropped, obsolete
* debian/rules:
  - Don't rename gdm binary since that's already been
    done in the new version

[ Jeremy Bicha ]
* debian/control.in: Bump minimum glib
* debian/watch: Watch for unstable releases
* debian/patches/00git_logind_check.patch:
  - Dropped, applied in new release
* debian/patches/08_frequent-users_greeter.patch: Refreshed

[ Robert Ancell ]
* New upstream release
* debian/patches/ubuntu_daemon_autologin_tracking.patch:
* debian/patches/ubuntu_ensure_dirs.patch:
* debian/patches/ubuntu_slave-only-set-up-autologin.patch:
  - Applied upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2
 
 *
3
 
 * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4
 
 *
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.
9
 
 *
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.
14
 
 *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 
 *
19
 
 */
20
 
 
21
 
#include "config.h"
22
 
 
23
 
#include <stdlib.h>
24
 
#include <stdio.h>
25
 
#include <unistd.h>
26
 
#include <errno.h>
27
 
#include <string.h>
28
 
#include <sys/types.h>
29
 
#include <sys/stat.h>
30
 
#include <fcntl.h>
31
 
#include <pwd.h>
32
 
#include <grp.h>
33
 
#include <sys/wait.h>
34
 
#include <locale.h>
35
 
#include <signal.h>
36
 
 
37
 
#include <glib.h>
38
 
#include <glib/gi18n.h>
39
 
#include <glib/gstdio.h>
40
 
#include <glib-object.h>
41
 
#include <gio/gio.h>
42
 
 
43
 
#include "gdm-manager.h"
44
 
#include "gdm-log.h"
45
 
#include "gdm-common.h"
46
 
#include "gdm-signal-handler.h"
47
 
 
48
 
#include "gdm-settings.h"
49
 
#include "gdm-settings-direct.h"
50
 
#include "gdm-settings-keys.h"
51
 
 
52
 
#define GDM_DBUS_NAME "org.gnome.DisplayManager"
53
 
 
54
 
static GDBusConnection *get_system_bus (void);
55
 
static gboolean         bus_reconnect (void);
56
 
 
57
 
extern char **environ;
58
 
 
59
 
static GdmManager      *manager       = NULL;
60
 
static int              name_id       = -1;
61
 
static GdmSettings     *settings      = NULL;
62
 
static uid_t            gdm_uid       = -1;
63
 
static gid_t            gdm_gid       = -1;
64
 
 
65
 
static gboolean
66
 
timed_exit_cb (GMainLoop *loop)
67
 
{
68
 
        g_main_loop_quit (loop);
69
 
        return FALSE;
70
 
}
71
 
 
72
 
static void
73
 
bus_connection_closed (void)
74
 
{
75
 
        g_debug ("Disconnected from D-Bus");
76
 
 
77
 
        if (manager == NULL) {
78
 
                /* probably shutting down or something */
79
 
                return;
80
 
        }
81
 
 
82
 
        g_clear_object (&manager);
83
 
 
84
 
        g_timeout_add_seconds (3, (GSourceFunc)bus_reconnect, NULL);
85
 
}
86
 
 
87
 
static GDBusConnection *
88
 
get_system_bus (void)
89
 
{
90
 
        GError          *error;
91
 
        GDBusConnection *bus;
92
 
 
93
 
        error = NULL;
94
 
        bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
95
 
        if (bus == NULL) {
96
 
                g_warning ("Couldn't connect to system bus: %s",
97
 
                           error->message);
98
 
                g_error_free (error);
99
 
                goto out;
100
 
        }
101
 
 
102
 
        g_signal_connect (bus, "closed",
103
 
                          G_CALLBACK (bus_connection_closed), NULL);
104
 
        g_dbus_connection_set_exit_on_close (bus, FALSE);
105
 
 
106
 
 out:
107
 
        return bus;
108
 
}
109
 
 
110
 
static void
111
 
delete_pid (void)
112
 
{
113
 
        g_unlink (GDM_PID_FILE);
114
 
}
115
 
 
116
 
static void
117
 
write_pid (void)
118
 
{
119
 
        int     pf;
120
 
        ssize_t written;
121
 
        char    pid[9];
122
 
 
123
 
        errno = 0;
124
 
        pf = open (GDM_PID_FILE, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
125
 
        if (pf < 0) {
126
 
                g_warning (_("Cannot write PID file %s: possibly out of disk space: %s"),
127
 
                           GDM_PID_FILE,
128
 
                           g_strerror (errno));
129
 
 
130
 
                return;
131
 
        }
132
 
 
133
 
        snprintf (pid, sizeof (pid), "%lu\n", (long unsigned) getpid ());
134
 
        errno = 0;
135
 
        written = write (pf, pid, strlen (pid));
136
 
        close (pf);
137
 
 
138
 
        if (written < 0) {
139
 
                g_warning (_("Cannot write PID file %s: possibly out of disk space: %s"),
140
 
                           GDM_PID_FILE,
141
 
                           g_strerror (errno));
142
 
                return;
143
 
        }
144
 
 
145
 
        atexit (delete_pid);
146
 
}
147
 
 
148
 
static void
149
 
check_logdir (void)
150
 
{
151
 
        struct stat     statbuf;
152
 
        int             r;
153
 
        const char     *log_path;
154
 
 
155
 
        log_path = LOGDIR;
156
 
 
157
 
        r = g_stat (log_path, &statbuf);
158
 
        if (r < 0 || ! S_ISDIR (statbuf.st_mode))  {
159
 
                if (g_mkdir (log_path, 0755) < 0) {
160
 
                        gdm_fail (_("Logdir %s does not exist or isn't a directory."),
161
 
                                  log_path);
162
 
                }
163
 
                g_chmod (log_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
164
 
        }
165
 
}
166
 
 
167
 
static void
168
 
check_servauthdir (const char  *auth_path,
169
 
                   struct stat *statbuf)
170
 
{
171
 
        int r;
172
 
 
173
 
        /* Enter paranoia mode */
174
 
        r = g_stat (auth_path, statbuf);
175
 
        if (r < 0) {
176
 
                gdm_fail (_("Authdir %s does not exist. Aborting."), auth_path);
177
 
        }
178
 
 
179
 
        if (! S_ISDIR (statbuf->st_mode)) {
180
 
                gdm_fail (_("Authdir %s is not a directory. Aborting."), auth_path);
181
 
        }
182
 
}
183
 
 
184
 
static void
185
 
set_effective_user (uid_t uid)
186
 
{
187
 
        int res;
188
 
 
189
 
        res = 0;
190
 
 
191
 
        if (geteuid () != uid) {
192
 
                res = seteuid (uid);
193
 
        }
194
 
 
195
 
        if (res != 0) {
196
 
                g_error ("Cannot set uid to %d: %s",
197
 
                         (int)uid,
198
 
                         g_strerror (errno));
199
 
        }
200
 
}
201
 
 
202
 
static void
203
 
set_effective_group (gid_t gid)
204
 
{
205
 
        int res;
206
 
 
207
 
        res = 0;
208
 
        if (getegid () != gid) {
209
 
                res = setegid (gid);
210
 
        }
211
 
 
212
 
        if (res != 0) {
213
 
                g_error ("Cannot set gid to %d: %s",
214
 
                         (int)gid,
215
 
                         g_strerror (errno));
216
 
        }
217
 
}
218
 
 
219
 
static void
220
 
set_effective_user_group (uid_t uid,
221
 
                          gid_t gid)
222
 
{
223
 
        set_effective_user (0);
224
 
        set_effective_group (gid);
225
 
        if (uid != 0) {
226
 
                set_effective_user (0);
227
 
        }
228
 
}
229
 
 
230
 
static void
231
 
gdm_daemon_check_permissions (uid_t uid,
232
 
                              gid_t gid)
233
 
{
234
 
        struct stat statbuf;
235
 
        const char *auth_path;
236
 
 
237
 
        auth_path = LOGDIR;
238
 
 
239
 
        /* Enter paranoia mode */
240
 
        check_servauthdir (auth_path, &statbuf);
241
 
 
242
 
        set_effective_user_group (0, 0);
243
 
 
244
 
        /* Now set things up for us as  */
245
 
        chown (auth_path, 0, gid);
246
 
        g_chmod (auth_path, (S_IRWXU|S_IRWXG|S_ISVTX));
247
 
 
248
 
        set_effective_user_group (uid, gid);
249
 
 
250
 
        /* Again paranoid */
251
 
        check_servauthdir (auth_path, &statbuf);
252
 
 
253
 
        if G_UNLIKELY (statbuf.st_uid != 0 || statbuf.st_gid != gid)  {
254
 
                gdm_fail (_("Authdir %s is not owned by user %d, group %d. Aborting."),
255
 
                          auth_path,
256
 
                          (int)uid,
257
 
                          (int)gid);
258
 
        }
259
 
 
260
 
        if G_UNLIKELY (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX))  {
261
 
                gdm_fail (_("Authdir %s has wrong permissions %o. Should be %o. Aborting."),
262
 
                          auth_path,
263
 
                          statbuf.st_mode,
264
 
                          (S_IRWXU|S_IRWXG|S_ISVTX));
265
 
        }
266
 
}
267
 
 
268
 
static void
269
 
gdm_daemon_change_user (uid_t *uidp,
270
 
                        gid_t *gidp)
271
 
{
272
 
        char          *username;
273
 
        char          *groupname;
274
 
        uid_t          uid;
275
 
        gid_t          gid;
276
 
        struct passwd *pwent;
277
 
        struct group  *grent;
278
 
 
279
 
        username = NULL;
280
 
        groupname = NULL;
281
 
        uid = 0;
282
 
        gid = 0;
283
 
 
284
 
        gdm_settings_direct_get_string (GDM_KEY_USER, &username);
285
 
        gdm_settings_direct_get_string (GDM_KEY_GROUP, &groupname);
286
 
 
287
 
        if (username == NULL || groupname == NULL) {
288
 
                return;
289
 
        }
290
 
 
291
 
        g_debug ("Changing user:group to %s:%s", username, groupname);
292
 
 
293
 
        /* Lookup user and groupid for the GDM user */
294
 
        gdm_get_pwent_for_name (username, &pwent);
295
 
 
296
 
        /* Set uid and gid */
297
 
        if G_UNLIKELY (pwent == NULL) {
298
 
                gdm_fail (_("Can't find the GDM user '%s'. Aborting!"), username);
299
 
        } else {
300
 
                uid = pwent->pw_uid;
301
 
        }
302
 
 
303
 
        if G_UNLIKELY (uid == 0) {
304
 
                gdm_fail (_("The GDM user should not be root. Aborting!"));
305
 
        }
306
 
 
307
 
        grent = getgrnam (groupname);
308
 
 
309
 
        if G_UNLIKELY (grent == NULL) {
310
 
                gdm_fail (_("Can't find the GDM group '%s'. Aborting!"), groupname);
311
 
        } else  {
312
 
                gid = grent->gr_gid;
313
 
        }
314
 
 
315
 
        if G_UNLIKELY (gid == 0) {
316
 
                gdm_fail (_("The GDM group should not be root. Aborting!"));
317
 
        }
318
 
 
319
 
        /* gid remains 'gdm' */
320
 
        set_effective_user_group (uid, gid);
321
 
 
322
 
        if (uidp != NULL) {
323
 
                *uidp = uid;
324
 
        }
325
 
 
326
 
        if (gidp != NULL) {
327
 
                *gidp = gid;
328
 
        }
329
 
 
330
 
        g_free (username);
331
 
        g_free (groupname);
332
 
}
333
 
 
334
 
static gboolean
335
 
signal_cb (int      signo,
336
 
           gpointer data)
337
 
{
338
 
        int ret;
339
 
 
340
 
        g_debug ("Got callback for signal %d", signo);
341
 
 
342
 
        ret = TRUE;
343
 
 
344
 
        switch (signo) {
345
 
        case SIGFPE:
346
 
        case SIGPIPE:
347
 
                /* let the fatal signals interrupt us */
348
 
                g_debug ("Caught signal %d, shutting down abnormally.", signo);
349
 
                ret = FALSE;
350
 
 
351
 
                break;
352
 
 
353
 
        case SIGINT:
354
 
        case SIGTERM:
355
 
                /* let the fatal signals interrupt us */
356
 
                g_debug ("Caught signal %d, shutting down normally.", signo);
357
 
                ret = FALSE;
358
 
 
359
 
                break;
360
 
 
361
 
        case SIGHUP:
362
 
                g_debug ("Got HUP signal");
363
 
                /* Reread config stuff like system config files, VPN service
364
 
                 * files, etc
365
 
                 */
366
 
                g_object_unref (settings);
367
 
                settings = gdm_settings_new ();
368
 
                if (settings != NULL) {
369
 
                        if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) {
370
 
                                g_warning ("Unable to initialize settings");
371
 
                        }
372
 
                }
373
 
 
374
 
                ret = TRUE;
375
 
 
376
 
                break;
377
 
 
378
 
        case SIGUSR1:
379
 
                g_debug ("Got USR1 signal");
380
 
                /* FIXME:
381
 
                 * Play with log levels or something
382
 
                 */
383
 
                ret = TRUE;
384
 
 
385
 
                gdm_log_toggle_debug ();
386
 
 
387
 
                break;
388
 
 
389
 
        default:
390
 
                g_debug ("Caught unhandled signal %d", signo);
391
 
                ret = TRUE;
392
 
 
393
 
                break;
394
 
        }
395
 
 
396
 
        return ret;
397
 
}
398
 
 
399
 
static gboolean
400
 
is_debug_set (void)
401
 
{
402
 
        gboolean debug = FALSE;
403
 
 
404
 
        /* enable debugging for unstable builds */
405
 
        if (gdm_is_version_unstable ()) {
406
 
                return TRUE;
407
 
        }
408
 
 
409
 
        gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
410
 
        return debug;
411
 
}
412
 
 
413
 
int
414
 
main (int    argc,
415
 
      char **argv)
416
 
{
417
 
        GMainLoop          *main_loop;
418
 
        GOptionContext     *context;
419
 
        GError             *error;
420
 
        int                 ret;
421
 
        gboolean            res;
422
 
        GdmSignalHandler   *signal_handler;
423
 
        static gboolean     do_timed_exit    = FALSE;
424
 
        static gboolean     print_version    = FALSE;
425
 
        static gboolean     fatal_warnings   = FALSE;
426
 
        static GOptionEntry entries []   = {
427
 
                { "fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &fatal_warnings, N_("Make all warnings fatal"), NULL },
428
 
                { "timed-exit", 0, 0, G_OPTION_ARG_NONE, &do_timed_exit, N_("Exit after a time (for debugging)"), NULL },
429
 
                { "version", 0, 0, G_OPTION_ARG_NONE, &print_version, N_("Print GDM version"), NULL },
430
 
 
431
 
                { NULL }
432
 
        };
433
 
 
434
 
        bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
435
 
        textdomain (GETTEXT_PACKAGE);
436
 
        setlocale (LC_ALL, "");
437
 
 
438
 
        ret = 1;
439
 
 
440
 
        g_type_init ();
441
 
 
442
 
        context = g_option_context_new (_("GNOME Display Manager"));
443
 
        g_option_context_add_main_entries (context, entries, NULL);
444
 
        g_option_context_set_ignore_unknown_options (context, TRUE);
445
 
 
446
 
        error = NULL;
447
 
        res = g_option_context_parse (context, &argc, &argv, &error);
448
 
        g_option_context_free (context);
449
 
        if (! res) {
450
 
                g_warning ("%s", error->message);
451
 
                g_error_free (error);
452
 
                goto out;
453
 
        }
454
 
 
455
 
        if (print_version) {
456
 
                g_print ("GDM %s\n", VERSION);
457
 
                exit (1);
458
 
        }
459
 
 
460
 
        if (fatal_warnings) {
461
 
                GLogLevelFlags fatal_mask;
462
 
 
463
 
                fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
464
 
                fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
465
 
                g_log_set_always_fatal (fatal_mask);
466
 
        }
467
 
 
468
 
        gdm_log_init ();
469
 
 
470
 
        settings = gdm_settings_new ();
471
 
        if (settings == NULL) {
472
 
                g_warning ("Unable to initialize settings");
473
 
                goto out;
474
 
        }
475
 
 
476
 
        if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) {
477
 
                g_warning ("Unable to initialize settings");
478
 
                goto out;
479
 
        }
480
 
 
481
 
        gdm_log_set_debug (is_debug_set ());
482
 
 
483
 
        gdm_daemon_change_user (&gdm_uid, &gdm_gid);
484
 
        gdm_daemon_check_permissions (gdm_uid, gdm_gid);
485
 
 
486
 
        set_effective_user_group (0, 0);
487
 
        check_logdir ();
488
 
 
489
 
        /* XDM compliant error message */
490
 
        if (getuid () != 0) {
491
 
                /* make sure the pid file doesn't get wiped */
492
 
                g_warning (_("Only the root user can run GDM"));
493
 
                exit (-1);
494
 
        }
495
 
 
496
 
        /* Connect to the bus, own the name and start the manager */
497
 
        bus_reconnect ();
498
 
 
499
 
        /* pid file */
500
 
        delete_pid ();
501
 
        write_pid ();
502
 
 
503
 
        g_chdir (AUTHDIR);
504
 
 
505
 
        main_loop = g_main_loop_new (NULL, FALSE);
506
 
 
507
 
        signal_handler = gdm_signal_handler_new ();
508
 
        gdm_signal_handler_set_fatal_func (signal_handler,
509
 
                                           (GDestroyNotify)g_main_loop_quit,
510
 
                                           main_loop);
511
 
        gdm_signal_handler_add_fatal (signal_handler);
512
 
        gdm_signal_handler_add (signal_handler, SIGTERM, signal_cb, NULL);
513
 
        gdm_signal_handler_add (signal_handler, SIGINT, signal_cb, NULL);
514
 
        gdm_signal_handler_add (signal_handler, SIGFPE, signal_cb, NULL);
515
 
        gdm_signal_handler_add (signal_handler, SIGHUP, signal_cb, NULL);
516
 
        gdm_signal_handler_add (signal_handler, SIGUSR1, signal_cb, NULL);
517
 
 
518
 
        if (do_timed_exit) {
519
 
                g_timeout_add_seconds (30, (GSourceFunc) timed_exit_cb, main_loop);
520
 
        }
521
 
 
522
 
        g_main_loop_run (main_loop);
523
 
 
524
 
        g_debug ("GDM finished, cleaning up...");
525
 
 
526
 
        g_clear_object (&manager);
527
 
        g_clear_object (&settings);
528
 
        g_clear_object (&signal_handler);
529
 
 
530
 
        gdm_settings_direct_shutdown ();
531
 
        gdm_log_shutdown ();
532
 
 
533
 
        g_main_loop_unref (main_loop);
534
 
 
535
 
        ret = 0;
536
 
 
537
 
 out:
538
 
 
539
 
        return ret;
540
 
}
541
 
 
542
 
static void
543
 
on_name_acquired (GDBusConnection *bus,
544
 
                  const char      *name,
545
 
                  gpointer         user_data)
546
 
{
547
 
        gboolean xdmcp_enabled;
548
 
        gboolean show_local_greeter;
549
 
 
550
 
        manager = gdm_manager_new ();
551
 
        if (manager == NULL) {
552
 
                g_warning ("Could not construct manager object");
553
 
                exit (1);
554
 
        }
555
 
 
556
 
        g_debug ("Successfully connected to D-Bus");
557
 
 
558
 
        gdm_manager_start (manager);
559
 
 
560
 
        show_local_greeter = TRUE;
561
 
        gdm_settings_direct_get_boolean (GDM_KEY_SHOW_LOCAL_GREETER, &show_local_greeter);
562
 
        gdm_manager_set_show_local_greeter (manager, show_local_greeter);
563
 
 
564
 
        xdmcp_enabled = FALSE;
565
 
        gdm_settings_direct_get_boolean (GDM_KEY_XDMCP_ENABLE, &xdmcp_enabled);
566
 
        gdm_manager_set_xdmcp_enabled (manager, xdmcp_enabled);
567
 
}
568
 
 
569
 
static void
570
 
on_name_lost (GDBusConnection *bus,
571
 
              const char      *name,
572
 
              gpointer         user_data)
573
 
{
574
 
        g_debug ("Lost GDM name on bus");
575
 
 
576
 
        bus_connection_closed ();
577
 
}
578
 
 
579
 
static gboolean
580
 
bus_reconnect ()
581
 
{
582
 
        GDBusConnection *bus;
583
 
        gboolean         ret;
584
 
 
585
 
        ret = TRUE;
586
 
 
587
 
        bus = get_system_bus ();
588
 
        if (bus == NULL) {
589
 
                goto out;
590
 
        }
591
 
 
592
 
        name_id = g_bus_own_name_on_connection (bus,
593
 
                                                GDM_DBUS_NAME,
594
 
                                                G_BUS_NAME_OWNER_FLAGS_NONE,
595
 
                                                on_name_acquired,
596
 
                                                on_name_lost,
597
 
                                                NULL,
598
 
                                                NULL);
599
 
 
600
 
        ret = FALSE;
601
 
 out:
602
 
        return ret;
603
 
}