~darkxst/ubuntu/saucy/gdm/lp1212408

« back to all changes in this revision

Viewing changes to daemon/auth.c

  • Committer: Bazaar Package Importer
  • Author(s): Josselin Mouette
  • Date: 2008-09-02 10:37:20 UTC
  • mfrom: (1.4.27 upstream)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: james.westby@ubuntu.com-20080902103720-p810vv530hqj45wg
Tags: 2.20.7-3
* Install the debian-moreblue-orbit theme, thanks Andre Luiz Rodrigues 
  Ferreira. Closes: #497440.
* 35_gdm.conf.patch: make it the default.
* copyright: fix encoding.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* GDM - The GNOME Display Manager
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 
2
 *
 
3
 * GDM - The GNOME Display Manager
2
4
 * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
3
5
 *
4
6
 * This program is free software; you can redistribute it and/or modify
24
26
#include <stdlib.h>
25
27
#include <unistd.h>
26
28
#include <fcntl.h>
27
 
#include <netdb.h> 
 
29
#include <netdb.h>
28
30
#include <sys/types.h>
29
31
#include <sys/socket.h>
30
32
#include <sys/stat.h>
31
33
#include <netinet/in.h>
 
34
#include <errno.h>
 
35
 
32
36
#include <X11/Xauth.h>
33
37
#include <glib/gi18n.h>
34
38
 
37
41
#include "misc.h"
38
42
#include "filecheck.h"
39
43
#include "auth.h"
40
 
#include "gdmconfig.h"
 
44
 
 
45
#include "gdm-common.h"
 
46
#include "gdm-log.h"
 
47
#include "gdm-daemon-config.h"
41
48
 
42
49
/* Ensure we know about FamilyInternetV6 even if what we're compiling
43
50
   against doesn't */
72
79
}
73
80
 
74
81
static gboolean
75
 
add_auth_entry (GdmDisplay *d, 
 
82
add_auth_entry (GdmDisplay *d,
76
83
                GSList **authlist,
77
 
                FILE *af, FILE *af2,
78
 
                unsigned short family, const char *addr, int addrlen)
 
84
                FILE *af,
 
85
                FILE *af2,
 
86
                unsigned short family,
 
87
                const char *addr,
 
88
                int addrlen)
79
89
{
80
90
        Xauth *xa;
81
91
        gchar *dispnum;
164
174
gboolean
165
175
gdm_auth_secure_display (GdmDisplay *d)
166
176
{
167
 
    FILE *af, *af_gdm;
168
 
    int closeret;
169
 
 
170
 
    if G_UNLIKELY (!d)
171
 
        return FALSE;
172
 
 
173
 
    umask (022);
174
 
 
175
 
    gdm_debug ("gdm_auth_secure_display: Setting up access for %s", d->name);
176
 
 
177
 
    g_free (d->authfile);
178
 
    d->authfile = NULL;
179
 
    g_free (d->authfile_gdm);
180
 
    d->authfile_gdm = NULL;
181
 
 
182
 
    if (d->server_uid != 0) {
183
 
            int authfd;
184
 
 
185
 
            /* Note, Xnest can't use the GDM_KEY_SERV_AUTHDIR unless running as
186
 
             * root, which is rare anyway. */
187
 
 
188
 
            d->authfile = g_build_filename (gdm_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL);
189
 
 
190
 
            umask (077);
191
 
            authfd = g_mkstemp (d->authfile);
192
 
            umask (022);
193
 
 
194
 
            if G_UNLIKELY (authfd == -1) {
195
 
                    gdm_error (_("%s: Could not make new cookie file in %s"),
196
 
                               "gdm_auth_secure_display", gdm_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK));
197
 
                    g_free (d->authfile);
198
 
                    d->authfile = NULL;
199
 
                    return FALSE;
200
 
            }
201
 
 
202
 
            /* Make it owned by the user that Xnest is started as */
203
 
            fchown (authfd, d->server_uid, -1);
204
 
 
205
 
            VE_IGNORE_EINTR (af = fdopen (authfd, "w"));
206
 
 
207
 
            if G_UNLIKELY (af == NULL) {
208
 
                    g_free (d->authfile);
209
 
                    d->authfile = NULL;
210
 
                    return FALSE;
211
 
            }
212
 
 
213
 
            /* Make another authfile since the greeter can't read the server/user
214
 
             * readable file */
215
 
            d->authfile_gdm = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth");
216
 
            af_gdm = gdm_safe_fopen_w (d->authfile_gdm);
217
 
 
218
 
            if G_UNLIKELY (af_gdm == NULL) {
219
 
                    gdm_error (_("%s: Cannot safely open %s"),
220
 
                               "gdm_auth_secure_display",
221
 
                               d->authfile_gdm);
222
 
 
223
 
                    g_free (d->authfile_gdm);
224
 
                    d->authfile_gdm = NULL;
225
 
                    g_free (d->authfile);
226
 
                    d->authfile = NULL;
227
 
                    VE_IGNORE_EINTR (fclose (af));
228
 
                    return FALSE;
229
 
            }
230
 
    } else {
231
 
            /* gdm and xserver authfile can be the same, server will run as root */
232
 
            d->authfile = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth");
233
 
            af = gdm_safe_fopen_w (d->authfile);
234
 
 
235
 
            if G_UNLIKELY (af == NULL) {
236
 
                    gdm_error (_("%s: Cannot safely open %s"),
237
 
                               "gdm_auth_secure_display",
238
 
                               d->authfile);
239
 
 
240
 
                    g_free (d->authfile);
241
 
                    d->authfile = NULL;
242
 
                    return FALSE;
243
 
            }
244
 
 
245
 
            af_gdm = NULL;
246
 
    }
247
 
 
248
 
    /* If this is a local display the struct hasn't changed and we
249
 
     * have to eat up old authentication cookies before baking new
250
 
     * ones... */
251
 
    if (SERVER_IS_LOCAL (d) && d->auths) {
252
 
            gdm_auth_free_auth_list (d->auths);
253
 
            d->auths = NULL;
254
 
 
255
 
            g_free (d->cookie);
256
 
            d->cookie = NULL;
257
 
            g_free (d->bcookie);
258
 
            d->bcookie = NULL;
259
 
    }
260
 
 
261
 
    /* Create new random cookie */
262
 
    gdm_cookie_generate (d);
263
 
 
264
 
    /* reget local host if local as it may have changed */
265
 
    if (SERVER_IS_LOCAL (d)) {
266
 
            char hostname[1024];
267
 
 
268
 
            hostname[1023] = '\0';
269
 
            if G_LIKELY (gethostname (hostname, 1023) == 0) {
270
 
                    g_free (d->hostname);
271
 
                    d->hostname = g_strdup (hostname);
272
 
            }
273
 
    }
274
 
 
275
 
    if ( ! add_auth_entry (d, &(d->auths), af, af_gdm, FamilyWild, NULL, 0))
276
 
            return FALSE;
277
 
 
278
 
    gdm_debug ("gdm_auth_secure_display: Setting up access");
279
 
 
280
 
    VE_IGNORE_EINTR (closeret = fclose (af));
281
 
    if G_UNLIKELY (closeret < 0) {
282
 
            display_add_error (d);
283
 
            return FALSE;
284
 
    }
285
 
    if (af_gdm != NULL) {
286
 
            VE_IGNORE_EINTR (closeret = fclose (af_gdm));
287
 
            if G_UNLIKELY (closeret < 0) {
288
 
                    display_add_error (d);
289
 
                    return FALSE;
290
 
            }
291
 
    }
292
 
    g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE);
293
 
 
294
 
    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG))
295
 
            gdm_debug ("gdm_auth_secure_display: Setting up access for %s - %d entries", 
296
 
                       d->name, g_slist_length (d->auths));
297
 
 
298
 
    return TRUE;
 
177
        FILE *af, *af_gdm;
 
178
        int closeret;
 
179
 
 
180
        if G_UNLIKELY (!d)
 
181
                return FALSE;
 
182
 
 
183
        umask (022);
 
184
 
 
185
        gdm_debug ("gdm_auth_secure_display: Setting up access for %s", d->name);
 
186
 
 
187
        g_free (d->authfile);
 
188
        d->authfile = NULL;
 
189
        g_free (d->authfile_gdm);
 
190
        d->authfile_gdm = NULL;
 
191
 
 
192
        if (d->server_uid != 0) {
 
193
                int authfd;
 
194
 
 
195
                /* Note, nested display can't use the GDM_KEY_SERV_AUTHDIR unless 
 
196
                 * running as root, which is rare anyway. */
 
197
 
 
198
                d->authfile = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL);
 
199
 
 
200
                umask (077);
 
201
                authfd = g_mkstemp (d->authfile);
 
202
                umask (022);
 
203
 
 
204
                if G_UNLIKELY (authfd == -1) {
 
205
                        gdm_error (_("%s: Could not make new cookie file in %s"),
 
206
                                   "gdm_auth_secure_display", gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK));
 
207
                        g_free (d->authfile);
 
208
                        d->authfile = NULL;
 
209
                        return FALSE;
 
210
                }
 
211
 
 
212
                /* Make it owned by the user that nested display is started as */
 
213
                fchown (authfd, d->server_uid, -1);
 
214
 
 
215
                VE_IGNORE_EINTR (af = fdopen (authfd, "w"));
 
216
 
 
217
                if G_UNLIKELY (af == NULL) {
 
218
                        g_free (d->authfile);
 
219
                        d->authfile = NULL;
 
220
                        return FALSE;
 
221
                }
 
222
 
 
223
                /* Make another authfile since the greeter can't read the server/user
 
224
                 * readable file */
 
225
                d->authfile_gdm = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth");
 
226
                af_gdm = gdm_safe_fopen_w (d->authfile_gdm, 0644);
 
227
 
 
228
                if G_UNLIKELY (af_gdm == NULL) {
 
229
                        gdm_error (_("%s: Cannot safely open %s"),
 
230
                                   "gdm_auth_secure_display",
 
231
                                   d->authfile_gdm);
 
232
 
 
233
                        g_free (d->authfile_gdm);
 
234
                        d->authfile_gdm = NULL;
 
235
                        g_free (d->authfile);
 
236
                        d->authfile = NULL;
 
237
                        VE_IGNORE_EINTR (fclose (af));
 
238
                        return FALSE;
 
239
                }
 
240
        } else {
 
241
                /* gdm and xserver authfile can be the same, server will run as root */
 
242
                d->authfile = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth");
 
243
                af = gdm_safe_fopen_w (d->authfile, 0644);
 
244
 
 
245
                if G_UNLIKELY (af == NULL) {
 
246
                        gdm_error (_("%s: Cannot safely open %s"),
 
247
                                   "gdm_auth_secure_display",
 
248
                                   d->authfile);
 
249
 
 
250
                        g_free (d->authfile);
 
251
                        d->authfile = NULL;
 
252
                        return FALSE;
 
253
                }
 
254
 
 
255
                af_gdm = NULL;
 
256
        }
 
257
 
 
258
        /* If this is a local display the struct hasn't changed and we
 
259
         * have to eat up old authentication cookies before baking new
 
260
         * ones... */
 
261
        if (SERVER_IS_LOCAL (d) && d->auths) {
 
262
                gdm_auth_free_auth_list (d->auths);
 
263
                d->auths = NULL;
 
264
 
 
265
                g_free (d->cookie);
 
266
                d->cookie = NULL;
 
267
                g_free (d->bcookie);
 
268
                d->bcookie = NULL;
 
269
        }
 
270
 
 
271
        /* Create new random cookie */
 
272
        gdm_cookie_generate (&d->cookie, &d->bcookie);
 
273
 
 
274
        /* reget local host if local as it may have changed */
 
275
        if (SERVER_IS_LOCAL (d)) {
 
276
                char hostname[1024];
 
277
 
 
278
                hostname[1023] = '\0';
 
279
                if G_LIKELY (gethostname (hostname, 1023) == 0) {
 
280
                        g_free (d->hostname);
 
281
                        d->hostname = g_strdup (hostname);
 
282
                }
 
283
        }
 
284
 
 
285
        if ( ! add_auth_entry (d, &(d->auths), af, af_gdm, FamilyWild, NULL, 0))
 
286
                return FALSE;
 
287
 
 
288
        gdm_debug ("gdm_auth_secure_display: Setting up access");
 
289
 
 
290
        VE_IGNORE_EINTR (closeret = fclose (af));
 
291
        if G_UNLIKELY (closeret < 0) {
 
292
                display_add_error (d);
 
293
                return FALSE;
 
294
        }
 
295
        if (af_gdm != NULL) {
 
296
                VE_IGNORE_EINTR (closeret = fclose (af_gdm));
 
297
                if G_UNLIKELY (closeret < 0) {
 
298
                        display_add_error (d);
 
299
                        return FALSE;
 
300
                }
 
301
        }
 
302
        g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE);
 
303
 
 
304
        if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG))
 
305
                gdm_debug ("gdm_auth_secure_display: Setting up access for %s - %d entries", 
 
306
                           d->name, g_slist_length (d->auths));
 
307
 
 
308
        return TRUE;
 
309
}
 
310
 
 
311
#define SA(__s)    ((struct sockaddr *) __s)
 
312
#define SIN(__s)   ((struct sockaddr_in *) __s)
 
313
#define SIN6(__s)  ((struct sockaddr_in6 *) __s)
 
314
 
 
315
static gboolean
 
316
add_auth_entry_for_addr (GdmDisplay              *d,
 
317
                         GSList                 **authlist,
 
318
                         struct sockaddr_storage *ss)
 
319
{
 
320
        const char    *addr;
 
321
        int            len;
 
322
        unsigned short family;
 
323
 
 
324
        switch (ss->ss_family) {
 
325
#ifdef ENABLE_IPV6
 
326
        case AF_INET6:
 
327
                family = FamilyInternetV6;
 
328
                addr = (const char *) &SIN6 (ss)->sin6_addr;
 
329
                len = sizeof (struct in6_addr);
 
330
                break;
 
331
#endif
 
332
        case AF_INET:
 
333
        default:
 
334
                family = FamilyInternet;
 
335
                addr = (const char *) &SIN (ss)->sin_addr;
 
336
                len = sizeof (struct in_addr);
 
337
                break;
 
338
        }
 
339
 
 
340
        return add_auth_entry (d, authlist, NULL, NULL, family, addr, len);
299
341
}
300
342
 
301
343
static GSList *
302
344
get_local_auths (GdmDisplay *d)
303
345
{
304
 
    gboolean is_local = FALSE;
305
 
    const char lo[] = {127,0,0,1};
306
 
#ifdef ENABLE_IPV6
307
 
    const char lo6[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
308
 
#endif
309
 
    guint i;
310
 
    const GList *local_addys = NULL;
311
 
    gboolean added_lo = FALSE;
312
 
    GSList *auths = NULL;
313
 
 
314
 
    if G_UNLIKELY (!d)
 
346
        gboolean is_local = FALSE;
 
347
        const char lo[] = {127,0,0,1};
 
348
        guint i;
 
349
        const GList *local_addys = NULL;
 
350
        gboolean added_lo = FALSE;
 
351
        GSList *auths = NULL;
 
352
 
 
353
        if G_UNLIKELY (!d)
 
354
                return NULL;
 
355
 
 
356
        if (SERVER_IS_LOCAL (d)) {
 
357
                char hostname[1024];
 
358
 
 
359
                /* reget local host if local as it may have changed */
 
360
                hostname[1023] = '\0';
 
361
                if G_LIKELY (gethostname (hostname, 1023) == 0) {
 
362
                        g_free (d->hostname);
 
363
                        d->hostname = g_strdup (hostname);
 
364
                }
 
365
                if ( ! d->tcp_disallowed)
 
366
                        local_addys = gdm_address_peek_local_list ();
 
367
 
 
368
                is_local = TRUE;
 
369
        } else  {
 
370
                is_local = FALSE;
 
371
 
 
372
                if (gdm_address_is_local (&(d->addr))) {
 
373
                        is_local = TRUE;
 
374
                }
 
375
 
 
376
                for (i = 0; ! is_local && i < d->addr_count; i++) {
 
377
                        if (gdm_address_is_local (&d->addrs[i])) {
 
378
                                is_local = TRUE;
 
379
                                break;
 
380
                        }
 
381
                }
 
382
        }
 
383
 
 
384
        /* Local access also in case the host is very local */
 
385
        if (is_local) {
 
386
                gdm_debug ("get_local_auths: Setting up socket access");
 
387
 
 
388
                if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal,
 
389
                                       d->hostname, strlen (d->hostname)))
 
390
                        goto get_local_auth_error;
 
391
 
 
392
                /* local machine but not local if you get my meaning, add
 
393
                 * the host gotten by gethostname as well if it's different
 
394
                 * since the above is probably localhost */
 
395
                if ( ! SERVER_IS_LOCAL (d)) {
 
396
                        char hostname[1024];
 
397
 
 
398
                        hostname[1023] = '\0';
 
399
                        if (gethostname (hostname, 1023) == 0 &&
 
400
                            strcmp (hostname, d->hostname) != 0) {
 
401
                                if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal,
 
402
                                                       hostname,
 
403
                                                       strlen (hostname)))
 
404
                                        goto get_local_auth_error;
 
405
                        }
 
406
                } else {
 
407
                        /* local machine, perhaps we haven't added
 
408
                         * localhost.localdomain to socket access */
 
409
                        const char *localhost = "localhost.localdomain";
 
410
                        if (strcmp (localhost, d->hostname) != 0) {
 
411
                                if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal,
 
412
                                                       localhost,
 
413
                                                       strlen (localhost))) {
 
414
                                        goto get_local_auth_error;
 
415
                                }
 
416
                        }
 
417
                }
 
418
        }
 
419
 
 
420
        gdm_debug ("get_local_auths: Setting up network access");
 
421
 
 
422
        if ( ! SERVER_IS_LOCAL (d)) {
 
423
                /* we should write out an entry for d->addr since
 
424
                   possibly it is not in d->addrs */
 
425
 
 
426
                if (! add_auth_entry_for_addr (d, &auths, &d->addr)) {
 
427
                        goto get_local_auth_error;
 
428
                }
 
429
 
 
430
                if (gdm_address_is_loopback (&(d->addr))) {
 
431
                        added_lo = TRUE;
 
432
                }
 
433
        }
 
434
 
 
435
        /* Network access: Write out an authentication entry for each of
 
436
         * this host's official addresses */
 
437
        for (i = 0; i < d->addr_count; i++) {
 
438
                struct sockaddr_storage *sa;
 
439
 
 
440
                sa = &d->addrs[i];
 
441
                if (gdm_address_equal (sa, &d->addr)) {
 
442
                        continue;
 
443
                }
 
444
 
 
445
                if (! add_auth_entry_for_addr (d, &auths, sa)) {
 
446
                        goto get_local_auth_error;
 
447
                }
 
448
 
 
449
                if (gdm_address_is_loopback (sa)) {
 
450
                        added_lo = TRUE;
 
451
                }
 
452
        }
 
453
 
 
454
        /* Network access: Write out an authentication entry for each of
 
455
         * this host's local addresses if any */
 
456
        for (; local_addys != NULL; local_addys = local_addys->next) {
 
457
                struct sockaddr_storage *ia = local_addys->data;
 
458
 
 
459
                if (ia == NULL)
 
460
                        break;
 
461
 
 
462
                if (! add_auth_entry_for_addr (d, &auths, ia)) {
 
463
                        goto get_local_auth_error;
 
464
                }
 
465
 
 
466
                if (gdm_address_is_loopback (ia)) {
 
467
                        added_lo = TRUE;
 
468
                }
 
469
        }
 
470
 
 
471
        /* If local server, then add loopback */
 
472
        if (SERVER_IS_LOCAL (d) && ! added_lo && ! d->tcp_disallowed) {
 
473
                if (! add_auth_entry (d, &auths, NULL, NULL, FamilyInternet,
 
474
                      lo, sizeof (struct in_addr))) {
 
475
                        goto get_local_auth_error;
 
476
                }
 
477
        }
 
478
 
 
479
        if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG))
 
480
                gdm_debug ("get_local_auths: Setting up access for %s - %d entries",
 
481
                           d->name, g_slist_length (auths));
 
482
 
 
483
        return auths;
 
484
 
 
485
 get_local_auth_error:
 
486
 
 
487
        gdm_auth_free_auth_list (auths);
 
488
 
315
489
        return NULL;
316
 
 
317
 
    if (SERVER_IS_LOCAL (d)) {
318
 
            char hostname[1024];
319
 
 
320
 
            /* reget local host if local as it may have changed */
321
 
            hostname[1023] = '\0';
322
 
            if G_LIKELY (gethostname (hostname, 1023) == 0) {
323
 
                    g_free (d->hostname);
324
 
                    d->hostname = g_strdup (hostname);
325
 
            }
326
 
            if ( ! d->tcp_disallowed)
327
 
                    local_addys = gdm_peek_local_address_list ();
328
 
 
329
 
            is_local = TRUE;
330
 
    } else  {
331
 
            is_local = FALSE;
332
 
#ifdef ENABLE_IPV6
333
 
            if (d->addrtype == AF_INET6) {
334
 
                    if (gdm_is_local_addr6 (&(d->addr6)))
335
 
                            is_local = TRUE;
336
 
            }
337
 
            else
338
 
#endif
339
 
            {
340
 
                    if (gdm_is_local_addr (&(d->addr)))
341
 
                            is_local = TRUE;
342
 
            }
343
 
 
344
 
            for (i = 0; ! is_local && i < d->addr_count; i++) {
345
 
#ifdef ENABLE_IPV6
346
 
                    if (d->addrs[i].ss_family == AF_INET6) {
347
 
                            if (gdm_is_local_addr6 (&((struct sockaddr_in6 *)(&(d->addrs[i])))->sin6_addr)) {
348
 
                                    is_local = TRUE;
349
 
                                    break;
350
 
                            }
351
 
                    }
352
 
                    else
353
 
#endif
354
 
                    {
355
 
                            if (gdm_is_local_addr (&((struct sockaddr_in *)(&(d->addrs[i])))->sin_addr)) {
356
 
                                    is_local = TRUE;
357
 
                                    break;
358
 
                            }
359
 
                    }
360
 
            }
361
 
    }
362
 
 
363
 
    /* Local access also in case the host is very local */
364
 
    if (is_local) {
365
 
            gdm_debug ("get_local_auths: Setting up socket access");
366
 
 
367
 
            if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal,
368
 
                                   d->hostname, strlen (d->hostname)))
369
 
                    goto get_local_auth_error;
370
 
 
371
 
            /* local machine but not local if you get my meaning, add
372
 
             * the host gotten by gethostname as well if it's different
373
 
             * since the above is probably localhost */
374
 
            if ( ! SERVER_IS_LOCAL (d)) {
375
 
                    char hostname[1024];
376
 
 
377
 
                    hostname[1023] = '\0';
378
 
                    if (gethostname (hostname, 1023) == 0 &&
379
 
                        strcmp (hostname, d->hostname) != 0) {
380
 
                            if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal,
381
 
                                                   hostname,
382
 
                                                   strlen (hostname)))
383
 
                                    goto get_local_auth_error;
384
 
                    }
385
 
            } else {
386
 
                    /* local machine, perhaps we haven't added
387
 
                     * localhost.localdomain to socket access */
388
 
                    const char *localhost = "localhost.localdomain";
389
 
                    if (strcmp (localhost, d->hostname) != 0) {
390
 
                            if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal,
391
 
                                                   localhost,
392
 
                                                   strlen (localhost))) {
393
 
                                    goto get_local_auth_error;
394
 
                            }
395
 
                    }
396
 
            }
397
 
    }
398
 
 
399
 
    gdm_debug ("get_local_auths: Setting up network access");
400
 
 
401
 
    if ( ! SERVER_IS_LOCAL (d)) {
402
 
            /* we should write out an entry for d->addr since
403
 
               possibly it is not in d->addrs */
404
 
#ifdef ENABLE_IPV6
405
 
            if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyInternetV6, (char *)((d->addr6).s6_addr), sizeof (struct in6_addr)))
406
 
                    goto get_local_auth_error;
407
 
            else
408
 
#endif
409
 
            if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyInternet, (char *)&(d->addr), sizeof (struct in_addr)))
410
 
                    goto get_local_auth_error;
411
 
 
412
 
#ifdef ENABLE_IPV6
413
 
            if (d->addrtype == AF_INET6 &&  gdm_is_loopback_addr6 (&(d->addr6)))
414
 
                added_lo = TRUE;
415
 
#endif
416
 
            if (d->addrtype == AF_INET && gdm_is_loopback_addr (&(d->addr)))
417
 
                added_lo = TRUE;
418
 
    }
419
 
    
420
 
    /* Network access: Write out an authentication entry for each of
421
 
     * this host's official addresses */
422
 
    for (i = 0; i < d->addr_count; i++) {
423
 
#ifdef ENABLE_IPV6
424
 
            struct in6_addr *ia6;
425
 
#endif   
426
 
            struct in_addr *ia;
427
 
 
428
 
#ifdef ENABLE_IPV6
429
 
            if (d->addrs[i].ss_family == AF_INET6) {
430
 
                    ia6 = &(((struct sockaddr_in6 *)(&(d->addrs[i])))->sin6_addr);
431
 
                    if (memcmp (ia6, &(d->addr6), sizeof (struct in6_addr)) == 0)
432
 
                            continue;
433
 
 
434
 
                    if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyInternetV6, (char *)(ia6->s6_addr), sizeof (struct in6_addr)))
435
 
                            goto get_local_auth_error;
436
 
 
437
 
                    if (gdm_is_loopback_addr6 (ia6))
438
 
                            added_lo = TRUE;
439
 
            }
440
 
            else
441
 
#endif   
442
 
            {
443
 
                    ia = &(((struct sockaddr_in *)(&(d->addrs[i])))->sin_addr);
444
 
                    if (memcmp (ia, &(d->addr), sizeof (struct in_addr)) == 0)
445
 
                            continue;
446
 
 
447
 
                    if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyInternet, (char *)&ia->s_addr, sizeof (struct in_addr)))
448
 
                            goto get_local_auth_error;
449
 
 
450
 
                    if (gdm_is_loopback_addr (ia))
451
 
                            added_lo = TRUE;
452
 
            }
453
 
    }
454
 
 
455
 
    /* Network access: Write out an authentication entry for each of
456
 
     * this host's local addresses if any */
457
 
    for (; local_addys != NULL; local_addys = local_addys->next) {
458
 
            struct sockaddr *ia = (struct sockaddr *) local_addys->data;
459
 
 
460
 
            if (ia == NULL)
461
 
                    break;
462
 
 
463
 
#ifdef ENABLE_IPV6
464
 
            if (ia->sa_family == AF_INET6) {
465
 
                    if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyInternetV6, (char *)(((struct sockaddr_in6 *)ia)->sin6_addr.s6_addr), sizeof (struct in6_addr)))
466
 
                            goto get_local_auth_error;
467
 
 
468
 
                    if (gdm_is_loopback_addr6 (&((struct sockaddr_in6 *)ia)->sin6_addr))
469
 
                            added_lo = TRUE;
470
 
            }
471
 
            else
472
 
#endif
473
 
            {
474
 
                    if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyInternet, (char *)&((struct sockaddr_in *)ia)->sin_addr, sizeof (struct in_addr)))
475
 
                            goto get_local_auth_error;
476
 
 
477
 
                    if (gdm_is_loopback_addr (&((struct sockaddr_in *)ia)->sin_addr))
478
 
                            added_lo = TRUE;
479
 
 
480
 
            }
481
 
    }
482
 
 
483
 
    /* if local server add loopback */
484
 
    if (SERVER_IS_LOCAL (d) && ! added_lo && ! d->tcp_disallowed) {
485
 
 
486
 
#ifdef ENABLE_IPV6
487
 
            if (d->addrtype == AF_INET6) {
488
 
                    if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyInternetV6, lo6, sizeof (struct in6_addr)))
489
 
                            goto get_local_auth_error;
490
 
            }
491
 
            else
492
 
#endif
493
 
            {
494
 
                    if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyInternet, lo, sizeof (struct in_addr)))
495
 
                            goto get_local_auth_error;
496
 
            }
497
 
 
498
 
    }
499
 
 
500
 
    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG))
501
 
            gdm_debug ("get_local_auths: Setting up access for %s - %d entries", 
502
 
                       d->name, g_slist_length (auths));
503
 
 
504
 
    return auths;
505
 
 
506
 
get_local_auth_error:
507
 
 
508
 
    gdm_auth_free_auth_list (auths);
509
 
 
510
 
    return NULL;
511
490
}
512
491
 
513
492
static gboolean
548
527
 * @d: Pointer to a GdmDisplay struct
549
528
 * @user: Userid of the user whose cookie file to add entries to
550
529
 * @homedir: The user's home directory
551
 
 * 
 
530
 *
552
531
 * Remove all cookies referring to this display from user's cookie
553
532
 * file and append the ones specified in the display's authlist.
554
533
 *
555
 
 * Returns TRUE on success and FALSE on error.  
 
534
 * Returns TRUE on success and FALSE on error.
556
535
 */
557
536
 
558
537
gboolean
559
538
gdm_auth_user_add (GdmDisplay *d, uid_t user, const char *homedir)
560
539
{
561
 
    char *authdir;
562
 
    gint authfd;
563
 
    FILE *af;
564
 
    GSList *auths = NULL;
565
 
    gchar *userauthdir;
566
 
    gchar *userauthfile;
567
 
    gboolean ret = TRUE;
568
 
    gboolean automatic_tmp_dir = FALSE;
569
 
    gboolean authdir_is_tmp_dir = FALSE;
570
 
    gboolean locked;
571
 
    gboolean user_auth_exists;
572
 
    int closeret;
573
 
 
574
 
    if (!d)
575
 
        return FALSE;
576
 
 
577
 
    if (d->local_auths != NULL) {
578
 
            gdm_auth_free_auth_list (d->local_auths);
579
 
            d->local_auths = NULL;
580
 
    }
581
 
 
582
 
    d->local_auths = get_local_auths (d);
583
 
 
584
 
    if (d->local_auths == NULL) {
585
 
            gdm_error ("Can't make cookies");
586
 
            return FALSE;
587
 
    }
588
 
 
589
 
    gdm_debug ("gdm_auth_user_add: Adding cookie for %d", user);
590
 
 
591
 
    userauthdir  = gdm_get_value_string (GDM_KEY_USER_AUTHDIR);
592
 
    userauthfile = gdm_get_value_string (GDM_KEY_USER_AUTHFILE);
593
 
 
594
 
    /* Determine whether UserAuthDir is specified. Otherwise ~user is used */
595
 
    if ( ! ve_string_empty (userauthdir) &&
596
 
        strcmp (userauthdir, "~") != 0) {
597
 
            if (strncmp (userauthdir, "~/", 2) == 0) {
598
 
                    authdir = g_build_filename (homedir, &userauthdir[2], NULL);
599
 
            } else {
600
 
                    authdir = g_strdup (userauthdir);
601
 
                    automatic_tmp_dir = TRUE;
602
 
                    authdir_is_tmp_dir = TRUE;
603
 
            }
604
 
    } else {
605
 
            authdir = g_strdup (homedir);
606
 
    }
607
 
 
608
 
try_user_add_again:
609
 
 
610
 
    locked = FALSE;
611
 
 
612
 
    umask (077);
613
 
 
614
 
    if (authdir == NULL)
615
 
            d->userauth = NULL;
616
 
    else
617
 
            d->userauth = g_build_filename (authdir, userauthfile, NULL);
618
 
 
619
 
    user_auth_exists = (d->userauth != NULL &&
620
 
                        g_access (d->userauth, F_OK) == 0);
621
 
 
622
 
    /* Find out if the Xauthority file passes the paranoia check */
623
 
    /* Note that this is not very efficient, we stat the files over
624
 
       and over, but we don't care, we don't do this too often */
625
 
    if (automatic_tmp_dir ||
626
 
        authdir == NULL ||
627
 
 
628
 
        /* first the standard paranoia check (this checks the home dir
629
 
         * too which is useful here) */
630
 
        ! gdm_file_check ("gdm_auth_user_add", user, authdir, userauthfile, 
631
 
                          TRUE, FALSE, gdm_get_value_int (GDM_KEY_USER_MAX_FILE),
632
 
                          gdm_get_value_int (GDM_KEY_RELAX_PERM)) ||
633
 
 
634
 
        /* now the auth file checking routine */
635
 
        ! gdm_auth_file_check ("gdm_auth_user_add", user, d->userauth, TRUE /* absentok */, NULL) ||
636
 
 
637
 
        /* now see if we can actually append this file */
638
 
        ! try_open_append (d->userauth) ||
639
 
 
640
 
        /* try opening as root, if we can't open as root,
641
 
           then this is a NFS mounted directory with root squashing,
642
 
           and we don't want to write cookies over NFS */
643
 
        (gdm_get_value_bool (GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS) &&
644
 
         ! try_open_read_as_root (d->userauth))) {
645
 
 
646
 
        /* if the userauth file didn't exist and we were looking at it,
647
 
           it likely exists now but empty, so just whack it
648
 
           (it may not exist if the file didn't exist and the directory
649
 
            was of wrong permissions, but more likely this is
650
 
            file on NFS dir with root-squashing enabled) */
651
 
        if ( ! user_auth_exists && d->userauth != NULL)
652
 
                g_unlink (d->userauth);
653
 
 
654
 
        /* No go. Let's create a fallback file in GDM_KEY_USER_AUTHDIR_FALLBACK (/tmp)
655
 
         * or perhaps userauthfile directory (usually would be /tmp) */
656
 
        d->authfb = TRUE;
657
 
        g_free (d->userauth);
658
 
        if (authdir_is_tmp_dir && authdir != NULL)
659
 
                d->userauth = g_build_filename (authdir, ".gdmXXXXXX", NULL);
 
540
        char *authdir;
 
541
        gint authfd;
 
542
        FILE *af;
 
543
        GSList *auths = NULL;
 
544
        const gchar *userauthdir;
 
545
        const gchar *userauthfile;
 
546
        gboolean ret = TRUE;
 
547
        gboolean automatic_tmp_dir = FALSE;
 
548
        gboolean authdir_is_tmp_dir = FALSE;
 
549
        gboolean locked;
 
550
        gboolean user_auth_exists;
 
551
        int closeret;
 
552
 
 
553
        if (!d)
 
554
                return FALSE;
 
555
 
 
556
        if (d->local_auths != NULL) {
 
557
                gdm_auth_free_auth_list (d->local_auths);
 
558
                d->local_auths = NULL;
 
559
        }
 
560
 
 
561
        d->local_auths = get_local_auths (d);
 
562
 
 
563
        if (d->local_auths == NULL) {
 
564
                gdm_error ("Can't make cookies");
 
565
                return FALSE;
 
566
        }
 
567
 
 
568
        gdm_debug ("gdm_auth_user_add: Adding cookie for %d", user);
 
569
 
 
570
        userauthdir  = gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR);
 
571
        userauthfile = gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHFILE);
 
572
 
 
573
        /* Determine whether UserAuthDir is specified. Otherwise ~user is used */
 
574
        if ( ! ve_string_empty (userauthdir) &&
 
575
             strcmp (userauthdir, "~") != 0) {
 
576
                if (strncmp (userauthdir, "~/", 2) == 0) {
 
577
                        authdir = g_build_filename (homedir, &userauthdir[2], NULL);
 
578
                } else {
 
579
                        authdir = g_strdup (userauthdir);
 
580
                        automatic_tmp_dir = TRUE;
 
581
                        authdir_is_tmp_dir = TRUE;
 
582
                }
 
583
        } else {
 
584
                authdir = g_strdup (homedir);
 
585
        }
 
586
 
 
587
 try_user_add_again:
 
588
 
 
589
        locked = FALSE;
 
590
 
 
591
        umask (077);
 
592
 
 
593
        if (authdir == NULL)
 
594
                d->userauth = NULL;
660
595
        else
661
 
                d->userauth = g_build_filename (gdm_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL);
662
 
        authfd = g_mkstemp (d->userauth);
663
 
 
664
 
        if G_UNLIKELY (authfd < 0 && authdir_is_tmp_dir) {
665
 
            g_free (d->userauth);
666
 
            d->userauth = NULL;
667
 
 
668
 
            umask (022);
669
 
 
670
 
            authdir_is_tmp_dir = FALSE;
671
 
            goto try_user_add_again;
672
 
        }
673
 
 
674
 
        if G_UNLIKELY (authfd < 0) {
675
 
            gdm_error (_("%s: Could not open cookie file %s"),
676
 
                       "gdm_auth_user_add",
677
 
                       d->userauth);
678
 
            g_free (d->userauth);
679
 
            d->userauth = NULL;
680
 
 
681
 
            umask (022);
682
 
 
683
 
            g_free (authdir);
684
 
            return FALSE;
685
 
        }
686
 
 
687
 
        d->last_auth_touch = time (NULL);
688
 
 
689
 
        VE_IGNORE_EINTR (af = fdopen (authfd, "w"));
690
 
    }
691
 
    else { /* User's Xauthority file is ok */
692
 
        d->authfb = FALSE;
693
 
 
694
 
        /* FIXME: Better implement my own locking. The libXau one is not kosher */
695
 
        if G_UNLIKELY (XauLockAuth (d->userauth, 3, 3, 0) != LOCK_SUCCESS) {
696
 
            gdm_error (_("%s: Could not lock cookie file %s"),
697
 
                       "gdm_auth_user_add",
698
 
                       d->userauth);
699
 
            g_free (d->userauth);
700
 
            d->userauth = NULL;
701
 
 
702
 
            umask (022);
703
 
 
704
 
            automatic_tmp_dir = TRUE;
705
 
            goto try_user_add_again;
706
 
        }
707
 
 
708
 
        locked = TRUE;
709
 
 
710
 
        af = gdm_safe_fopen_ap (d->userauth);
711
 
    }
712
 
 
713
 
    /* Set to NULL, because can goto try_user_add_again. */
714
 
    g_free (authdir);
715
 
    authdir = NULL;
716
 
 
717
 
    if G_UNLIKELY (af == NULL) {
718
 
        /* Really no need to clean up here - this process is a goner anyway */
719
 
        gdm_error (_("%s: Could not open cookie file %s"),
720
 
                   "gdm_auth_user_add",
721
 
                   d->userauth);
722
 
        if (locked)
723
 
                XauUnlockAuth (d->userauth);
724
 
        g_free (d->userauth);
725
 
        d->userauth = NULL;
726
 
 
727
 
        umask (022);
728
 
 
729
 
        if ( ! d->authfb) {
730
 
                automatic_tmp_dir = TRUE;
731
 
                goto try_user_add_again;
732
 
        }
733
 
 
734
 
        return FALSE; 
735
 
    }
736
 
 
737
 
    gdm_debug ("gdm_auth_user_add: Using %s for cookies", d->userauth);
738
 
 
739
 
    /* If not a fallback file, nuke any existing cookies for this display */
740
 
    if (! d->authfb)
741
 
        af = gdm_auth_purge (d, af, FALSE /* remove when empty */);
742
 
 
743
 
    /* Append the authlist for this display to the cookie file */
744
 
    auths = d->local_auths;
745
 
 
746
 
    while (auths) {
747
 
        if G_UNLIKELY ( ! XauWriteAuth (af, auths->data)) {
 
596
                d->userauth = g_build_filename (authdir, userauthfile, NULL);
 
597
 
 
598
        user_auth_exists = (d->userauth != NULL &&
 
599
                            g_access (d->userauth, F_OK) == 0);
 
600
 
 
601
        /* Find out if the Xauthority file passes the paranoia check */
 
602
        /* Note that this is not very efficient, we stat the files over
 
603
           and over, but we don't care, we don't do this too often */
 
604
        if (automatic_tmp_dir ||
 
605
            authdir == NULL ||
 
606
 
 
607
            /* first the standard paranoia check (this checks the home dir
 
608
             * too which is useful here) */
 
609
            ! gdm_file_check ("gdm_auth_user_add", user, authdir, userauthfile, 
 
610
                              TRUE, FALSE, gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE),
 
611
                              gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM)) ||
 
612
 
 
613
            /* now the auth file checking routine */
 
614
            ! gdm_auth_file_check ("gdm_auth_user_add", user, d->userauth, TRUE /* absentok */, NULL) ||
 
615
 
 
616
            /* now see if we can actually append this file */
 
617
            ! try_open_append (d->userauth) ||
 
618
 
 
619
            /* try opening as root, if we can't open as root,
 
620
               then this is a NFS mounted directory with root squashing,
 
621
               and we don't want to write cookies over NFS */
 
622
            (gdm_daemon_config_get_value_bool (GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS) &&
 
623
             ! try_open_read_as_root (d->userauth))) {
 
624
 
 
625
                /* if the userauth file didn't exist and we were looking at it,
 
626
                   it likely exists now but empty, so just whack it
 
627
                   (it may not exist if the file didn't exist and the directory
 
628
                   was of wrong permissions, but more likely this is
 
629
                   file on NFS dir with root-squashing enabled) */
 
630
                if ( ! user_auth_exists && d->userauth != NULL)
 
631
                        g_unlink (d->userauth);
 
632
 
 
633
                /* No go. Let's create a fallback file in GDM_KEY_USER_AUTHDIR_FALLBACK (/tmp)
 
634
                 * or perhaps userauthfile directory (usually would be /tmp) */
 
635
                d->authfb = TRUE;
 
636
                g_free (d->userauth);
 
637
                if (authdir_is_tmp_dir && authdir != NULL)
 
638
                        d->userauth = g_build_filename (authdir, ".gdmXXXXXX", NULL);
 
639
                else
 
640
                        d->userauth = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL);
 
641
                authfd = g_mkstemp (d->userauth);
 
642
 
 
643
                if G_UNLIKELY (authfd < 0 && authdir_is_tmp_dir) {
 
644
                        g_free (d->userauth);
 
645
                        d->userauth = NULL;
 
646
 
 
647
                        authdir_is_tmp_dir = FALSE;
 
648
                        goto try_user_add_again;
 
649
                }
 
650
 
 
651
                if G_UNLIKELY (authfd < 0) {
 
652
                        gdm_error (_("%s: Could not open cookie file %s"),
 
653
                                   "gdm_auth_user_add",
 
654
                                   d->userauth);
 
655
                        g_free (d->userauth);
 
656
                        d->userauth = NULL;
 
657
 
 
658
                        umask (022);
 
659
 
 
660
                        g_free (authdir);
 
661
                        return FALSE;
 
662
                }
 
663
 
 
664
                d->last_auth_touch = time (NULL);
 
665
 
 
666
                VE_IGNORE_EINTR (af = fdopen (authfd, "w"));
 
667
        } else { /* User's Xauthority file is ok */
 
668
                d->authfb = FALSE;
 
669
 
 
670
                /* FIXME: Better implement my own locking. The libXau one is not kosher */
 
671
                if G_UNLIKELY (XauLockAuth (d->userauth, 3, 3, 0) != LOCK_SUCCESS) {
 
672
                        gdm_error (_("%s: Could not lock cookie file %s"),
 
673
                                   "gdm_auth_user_add",
 
674
                                   d->userauth);
 
675
                        g_free (d->userauth);
 
676
                        d->userauth = NULL;
 
677
 
 
678
                        automatic_tmp_dir = TRUE;
 
679
                        goto try_user_add_again;
 
680
                }
 
681
 
 
682
                locked = TRUE;
 
683
 
 
684
                af = gdm_safe_fopen_ap (d->userauth, 0600);
 
685
        }
 
686
 
 
687
        /* Set to NULL, because can goto try_user_add_again. */
 
688
        g_free (authdir);
 
689
        authdir = NULL;
 
690
 
 
691
        if G_UNLIKELY (af == NULL) {
 
692
                /* Really no need to clean up here - this process is a goner anyway */
 
693
                gdm_error (_("%s: Could not open cookie file %s"),
 
694
                           "gdm_auth_user_add",
 
695
                           d->userauth);
 
696
                if (locked)
 
697
                        XauUnlockAuth (d->userauth);
 
698
                g_free (d->userauth);
 
699
                d->userauth = NULL;
 
700
 
 
701
                if ( ! d->authfb) {
 
702
                        automatic_tmp_dir = TRUE;
 
703
                        goto try_user_add_again;
 
704
                }
 
705
 
 
706
                umask (022);
 
707
                return FALSE; 
 
708
        }
 
709
 
 
710
        gdm_debug ("gdm_auth_user_add: Using %s for cookies", d->userauth);
 
711
 
 
712
        /* If not a fallback file, nuke any existing cookies for this display */
 
713
        if (! d->authfb)
 
714
                af = gdm_auth_purge (d, af, FALSE /* remove when empty */);
 
715
 
 
716
        /* Append the authlist for this display to the cookie file */
 
717
        auths = d->local_auths;
 
718
 
 
719
        while (auths) {
 
720
                if G_UNLIKELY ( ! XauWriteAuth (af, auths->data)) {
 
721
                        gdm_error (_("%s: Could not write cookie"),
 
722
                                   "gdm_auth_user_add");
 
723
 
 
724
                        if ( ! d->authfb) {
 
725
                                VE_IGNORE_EINTR (fclose (af));
 
726
                                if (locked)
 
727
                                        XauUnlockAuth (d->userauth);
 
728
                                g_free (d->userauth);
 
729
                                d->userauth = NULL;
 
730
                                automatic_tmp_dir = TRUE;
 
731
                                goto try_user_add_again;
 
732
                        }
 
733
 
 
734
                        ret = FALSE;
 
735
                        break;
 
736
                }
 
737
 
 
738
                auths = auths->next;
 
739
        }
 
740
 
 
741
        VE_IGNORE_EINTR (closeret = fclose (af));
 
742
        if G_UNLIKELY (closeret < 0) {
748
743
                gdm_error (_("%s: Could not write cookie"),
749
744
                           "gdm_auth_user_add");
750
745
 
751
746
                if ( ! d->authfb) {
752
 
                        VE_IGNORE_EINTR (fclose (af));
753
747
                        if (locked)
754
748
                                XauUnlockAuth (d->userauth);
755
749
                        g_free (d->userauth);
759
753
                }
760
754
 
761
755
                ret = FALSE;
762
 
                break;
763
756
        }
764
757
 
765
 
        auths = auths->next;
766
 
    }
767
 
 
768
 
    VE_IGNORE_EINTR (closeret = fclose (af));
769
 
    if G_UNLIKELY (closeret < 0) {
770
 
            gdm_error (_("%s: Could not write cookie"),
771
 
                       "gdm_auth_user_add");
772
 
 
773
 
            if ( ! d->authfb) {
774
 
                    if (locked)
775
 
                            XauUnlockAuth (d->userauth);
776
 
                    g_free (d->userauth);
777
 
                    d->userauth = NULL;
778
 
                    automatic_tmp_dir = TRUE;
779
 
                    goto try_user_add_again;
780
 
            }
781
 
 
782
 
            ret = FALSE;
783
 
    }
784
 
 
785
 
    if (locked)
786
 
            XauUnlockAuth (d->userauth);
787
 
 
788
 
    gdm_debug ("gdm_auth_user_add: Done");
789
 
 
790
 
    umask (022);
791
 
    return ret;
 
758
        if (locked)
 
759
                XauUnlockAuth (d->userauth);
 
760
 
 
761
        gdm_debug ("gdm_auth_user_add: Done");
 
762
 
 
763
        umask (022);
 
764
        return ret;
792
765
}
793
766
 
794
767
 
804
777
void 
805
778
gdm_auth_user_remove (GdmDisplay *d, uid_t user)
806
779
{
807
 
    FILE *af;
808
 
    gchar *authfile;
809
 
    gchar *authdir;
810
 
    mode_t oldmode;
811
 
 
812
 
    if G_UNLIKELY (!d || !d->userauth)
813
 
        return;
814
 
 
815
 
    gdm_debug ("gdm_auth_user_remove: Removing cookie from %s (%d)", d->userauth, d->authfb);
816
 
 
817
 
    /* If we are using the fallback cookie location, simply nuke the
818
 
     * cookie file */
819
 
    if (d->authfb) {
820
 
        VE_IGNORE_EINTR (g_unlink (d->userauth));
821
 
        g_free (d->userauth);
822
 
        d->userauth = NULL;
823
 
        return;
824
 
    }
825
 
 
826
 
    /* if the file doesn't exist, oh well, just ignore this then */
827
 
    if G_UNLIKELY (g_access (d->userauth, F_OK) != 0) {
828
 
        g_free (d->userauth);
829
 
        d->userauth = NULL;
830
 
        return;
831
 
    }
832
 
 
833
 
    authfile = g_path_get_basename (d->userauth);
834
 
    authdir = g_path_get_dirname (d->userauth);
835
 
 
836
 
    if (ve_string_empty (authfile) ||
837
 
        ve_string_empty (authdir)) {
838
 
            g_free (authdir);
839
 
            g_free (authfile);
840
 
            return;
841
 
    }
842
 
 
843
 
    /* Now, the cookie file could be owned by a malicious user who
844
 
     * decided to concatenate something like his entire MP3 collection
845
 
     * to it. So we better play it safe... */
846
 
 
847
 
    if G_UNLIKELY ( ! gdm_file_check ("gdm_auth_user_remove", user, authdir, authfile, 
848
 
                           TRUE, FALSE, gdm_get_value_int (GDM_KEY_USER_MAX_FILE),
849
 
                           gdm_get_value_int (GDM_KEY_RELAX_PERM)) ||
850
 
                    /* be even paranoider with permissions */
851
 
                    ! gdm_auth_file_check ("gdm_auth_user_remove", user, d->userauth, FALSE /* absentok */, NULL)) {
852
 
            g_free (authdir);
853
 
            g_free (authfile);
854
 
            gdm_error (_("%s: Ignoring suspiciously looking cookie file %s"),
855
 
                       "gdm_auth_user_remove",
856
 
                       d->userauth);
857
 
 
858
 
            return; 
859
 
    }
860
 
 
861
 
    g_free (authdir);
862
 
    g_free (authfile);
863
 
 
864
 
    /* Lock user's cookie jar and open it for writing */
865
 
    if G_UNLIKELY (XauLockAuth (d->userauth, 3, 3, 0) != LOCK_SUCCESS) {
866
 
        g_free (d->userauth);
867
 
        d->userauth = NULL;
868
 
        return;
869
 
    }
870
 
 
871
 
    oldmode = umask (077);
872
 
    af = gdm_safe_fopen_ap (d->userauth);
873
 
    umask (oldmode);
874
 
 
875
 
    if G_UNLIKELY (af == NULL) {
 
780
        FILE *af;
 
781
        gchar *authfile;
 
782
        gchar *authdir;
 
783
 
 
784
        if G_UNLIKELY (!d || !d->userauth)
 
785
                return;
 
786
 
 
787
        gdm_debug ("gdm_auth_user_remove: Removing cookie from %s (%d)", d->userauth, d->authfb);
 
788
 
 
789
        /* If we are using the fallback cookie location, simply nuke the
 
790
         * cookie file */
 
791
        if (d->authfb) {
 
792
                VE_IGNORE_EINTR (g_unlink (d->userauth));
 
793
                g_free (d->userauth);
 
794
                d->userauth = NULL;
 
795
                return;
 
796
        }
 
797
 
 
798
        /* if the file doesn't exist, oh well, just ignore this then */
 
799
        if G_UNLIKELY (g_access (d->userauth, F_OK) != 0) {
 
800
                g_free (d->userauth);
 
801
                d->userauth = NULL;
 
802
                return;
 
803
        }
 
804
 
 
805
        authfile = g_path_get_basename (d->userauth);
 
806
        authdir = g_path_get_dirname (d->userauth);
 
807
 
 
808
        if (ve_string_empty (authfile) ||
 
809
            ve_string_empty (authdir)) {
 
810
                g_free (authdir);
 
811
                g_free (authfile);
 
812
                return;
 
813
        }
 
814
 
 
815
        /* Now, the cookie file could be owned by a malicious user who
 
816
         * decided to concatenate something like his entire MP3 collection
 
817
         * to it. So we better play it safe... */
 
818
 
 
819
        if G_UNLIKELY ( ! gdm_file_check ("gdm_auth_user_remove", user, authdir, authfile, 
 
820
                                          TRUE, FALSE, gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE),
 
821
                                          gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM)) ||
 
822
                        /* be even paranoider with permissions */
 
823
                        ! gdm_auth_file_check ("gdm_auth_user_remove", user, d->userauth, FALSE /* absentok */, NULL)) {
 
824
                g_free (authdir);
 
825
                g_free (authfile);
 
826
                gdm_error (_("%s: Ignoring suspiciously looking cookie file %s"),
 
827
                           "gdm_auth_user_remove",
 
828
                           d->userauth);
 
829
 
 
830
                return; 
 
831
        }
 
832
 
 
833
        g_free (authdir);
 
834
        g_free (authfile);
 
835
 
 
836
        /* Lock user's cookie jar and open it for writing */
 
837
        if G_UNLIKELY (XauLockAuth (d->userauth, 3, 3, 0) != LOCK_SUCCESS) {
 
838
                g_free (d->userauth);
 
839
                d->userauth = NULL;
 
840
                return;
 
841
        }
 
842
 
 
843
        af = gdm_safe_fopen_ap (d->userauth, 0600);
 
844
 
 
845
        if G_UNLIKELY (af == NULL) {
 
846
                XauUnlockAuth (d->userauth);
 
847
 
 
848
                gdm_error (_("%s: Cannot safely open %s"),
 
849
                           "gdm_auth_user_remove",
 
850
                           d->userauth);
 
851
 
 
852
                g_free (d->userauth);
 
853
                d->userauth = NULL;
 
854
 
 
855
                return;
 
856
        }
 
857
 
 
858
        /* Purge entries for this display from the cookie jar */
 
859
        af = gdm_auth_purge (d, af, TRUE /* remove when empty */);
 
860
 
 
861
        /* Close the file and unlock it */
 
862
        if (af != NULL) {
 
863
                /* FIXME: what about out of diskspace errors on errors close */
 
864
                errno = 0;
 
865
                VE_IGNORE_EINTR (fclose (af));
 
866
                if G_UNLIKELY (errno != 0) {
 
867
                        gdm_error (_("Can't write to %s: %s"), d->userauth,
 
868
                                   strerror (errno));
 
869
                }
 
870
        }
 
871
 
876
872
        XauUnlockAuth (d->userauth);
877
873
 
878
 
        gdm_error (_("%s: Cannot safely open %s"),
879
 
                   "gdm_auth_user_remove",
880
 
                   d->userauth);
881
 
 
882
874
        g_free (d->userauth);
883
875
        d->userauth = NULL;
884
 
 
885
 
        return;
886
 
    }
887
 
 
888
 
    /* Purge entries for this display from the cookie jar */
889
 
    af = gdm_auth_purge (d, af, TRUE /* remove when empty */);
890
 
 
891
 
    /* Close the file and unlock it */
892
 
    if (af != NULL) {
893
 
            /* FIXME: what about out of diskspace errors on errors close */
894
 
            errno = 0;
895
 
            VE_IGNORE_EINTR (fclose (af));
896
 
            if G_UNLIKELY (errno != 0) {
897
 
                    gdm_error (_("Can't write to %s: %s"), d->userauth,
898
 
                               strerror (errno));
899
 
            }
900
 
    }
901
 
 
902
 
    XauUnlockAuth (d->userauth);
903
 
 
904
 
    g_free (d->userauth);
905
 
    d->userauth = NULL;
906
876
}
907
877
 
908
878
static gboolean
941
911
 * @d: Pointer to a GdmDisplay struct
942
912
 * @af: File handle to a cookie file
943
913
 * @remove_when_empty: remove the file when empty
944
 
 * 
 
914
 *
945
915
 * Remove all cookies referring to this display a cookie file.
946
916
 */
947
917
 
948
918
static FILE *
949
919
gdm_auth_purge (GdmDisplay *d, FILE *af, gboolean remove_when_empty)
950
920
{
951
 
    Xauth *xa;
952
 
    GSList *keep = NULL, *li;
953
 
    mode_t oldmode;
954
 
    int cnt;
955
 
 
956
 
    if G_UNLIKELY (!d || !af)
 
921
        Xauth *xa;
 
922
        GSList *keep = NULL, *li;
 
923
        int cnt;
 
924
 
 
925
        if G_UNLIKELY (!d || !af)
 
926
                return af;
 
927
 
 
928
        gdm_debug ("gdm_auth_purge: %s", d->name);
 
929
 
 
930
        fseek (af, 0L, SEEK_SET);
 
931
 
 
932
        /* Read the user's entire Xauth file into memory to avoid
 
933
         * temporary file issues. Then remove any instance of this display
 
934
         * in the cookie jar... */
 
935
 
 
936
        cnt = 0;
 
937
 
 
938
        while ( (xa = XauReadAuth (af)) != NULL ) {
 
939
                GSList *li;
 
940
                /* We look at the current auths, but those may
 
941
                   have different cookies then what is in the file,
 
942
                   so don't compare those, but we wish to purge all
 
943
                   the entries that we'd normally write */
 
944
                for (li = d->local_auths; li != NULL; li = li->next) {
 
945
                        Xauth *xb = li->data;
 
946
                        if (auth_same_except_data (xa, xb)) {
 
947
                                XauDisposeAuth (xa);
 
948
                                xa = NULL;
 
949
                                break;
 
950
                        }
 
951
                }
 
952
                if (xa != NULL)
 
953
                        keep = g_slist_append (keep, xa);
 
954
 
 
955
                /* just being ultra anal */
 
956
                cnt++;
 
957
                if (cnt > 500)
 
958
                        break;
 
959
        }
 
960
 
 
961
        VE_IGNORE_EINTR (fclose (af));
 
962
 
 
963
        if (remove_when_empty &&
 
964
            keep == NULL) {
 
965
                VE_IGNORE_EINTR (g_unlink (d->userauth));
 
966
                return NULL;
 
967
        }
 
968
 
 
969
        af = gdm_safe_fopen_w (d->userauth, 0600);
 
970
 
 
971
        /* Write out remaining entries */
 
972
        for (li = keep; li != NULL; li = li->next) {
 
973
                /* FIXME: is this correct, if we can't open
 
974
                 * this is quite bad isn't it ... */
 
975
                if G_LIKELY (af != NULL)
 
976
                        XauWriteAuth (af, li->data);
 
977
                /* FIXME: what about errors? */
 
978
                XauDisposeAuth (li->data);
 
979
                li->data = NULL;
 
980
        }
 
981
 
 
982
        g_slist_free (keep);
 
983
 
957
984
        return af;
958
 
 
959
 
    gdm_debug ("gdm_auth_purge: %s", d->name);
960
 
 
961
 
    fseek (af, 0L, SEEK_SET);
962
 
 
963
 
    /* Read the user's entire Xauth file into memory to avoid
964
 
     * temporary file issues. Then remove any instance of this display
965
 
     * in the cookie jar... */
966
 
 
967
 
    cnt = 0;
968
 
 
969
 
    while ( (xa = XauReadAuth (af)) != NULL ) {
970
 
        GSList *li;
971
 
        /* We look at the current auths, but those may
972
 
           have different cookies then what is in the file,
973
 
           so don't compare those, but we wish to purge all
974
 
           the entries that we'd normally write */
975
 
        for (li = d->local_auths; li != NULL; li = li->next) {
976
 
                Xauth *xb = li->data;
977
 
                if (auth_same_except_data (xa, xb)) {
978
 
                        XauDisposeAuth (xa);
979
 
                        xa = NULL;
980
 
                        break;
981
 
                }
982
 
        }
983
 
        if (xa != NULL)
984
 
                keep = g_slist_append (keep, xa);
985
 
 
986
 
        /* just being ultra anal */
987
 
        cnt++;
988
 
        if (cnt > 500)
989
 
                break;
990
 
    }
991
 
 
992
 
    VE_IGNORE_EINTR (fclose (af));
993
 
 
994
 
    if (remove_when_empty &&
995
 
        keep == NULL) {
996
 
            VE_IGNORE_EINTR (g_unlink (d->userauth));
997
 
            return NULL;
998
 
    }
999
 
 
1000
 
    oldmode = umask (077);
1001
 
    af = gdm_safe_fopen_w (d->userauth);
1002
 
    umask (oldmode);
1003
 
 
1004
 
    /* Write out remaining entries */
1005
 
    for (li = keep; li != NULL; li = li->next) {
1006
 
            /* FIXME: is this correct, if we can't open
1007
 
             * this is quite bad isn't it ... */
1008
 
            if G_LIKELY (af != NULL)
1009
 
                    XauWriteAuth (af, li->data);
1010
 
                    /* FIXME: what about errors? */
1011
 
            XauDisposeAuth (li->data);
1012
 
            li->data = NULL;
1013
 
    }
1014
 
 
1015
 
    g_slist_free (keep);
1016
 
 
1017
 
    return af;
1018
985
}
1019
986
 
1020
987
void
1021
988
gdm_auth_set_local_auth (GdmDisplay *d)
1022
989
{
1023
 
        XSetAuthorization ((char *)"MIT-MAGIC-COOKIE-1", (int) strlen ("MIT-MAGIC-COOKIE-1"),
1024
 
                           (char *)d->bcookie, (int) 16);
 
990
        XSetAuthorization ((char *)"MIT-MAGIC-COOKIE-1",
 
991
                           (int) strlen ("MIT-MAGIC-COOKIE-1"),
 
992
                           (char *)d->bcookie,
 
993
                           (int) 16);
1025
994
}
1026
995
 
1027
996
void
1036
1005
 
1037
1006
        g_slist_free (list);
1038
1007
}
1039
 
 
1040
 
/* EOF */