~ubuntu-branches/debian/stretch/lightdm/stretch

« back to all changes in this revision

Viewing changes to src/x-authority.c

  • Committer: Package Import Robot
  • Author(s): Yves-Alexis Perez
  • Date: 2013-10-20 20:45:55 UTC
  • mfrom: (1.1.17)
  • Revision ID: package-import@ubuntu.com-20131020204555-0ht6bt0lw5bof9fn
Tags: 1.8.2-1
* New upstream release.
* debian/patches:
  - 01_set-default-path, 02_default-config, 05_debianize-pam-files
    refreshed.
  - 03_quit-plymouth disabled for now, to check if problem is really fixed
    upstream.
* debian/control:
  - rename liblightdm-qt-2-0 to liblightdm-qt-3-0 to match updated soname.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2010-2011 Robert Ancell.
 
3
 * Author: Robert Ancell <robert.ancell@canonical.com>
 
4
 * 
 
5
 * This program is free software: you can redistribute it and/or modify it under
 
6
 * the terms of the GNU General Public License as published by the Free Software
 
7
 * Foundation, either version 3 of the License, or (at your option) any later
 
8
 * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
 
9
 * license.
 
10
 */
 
11
 
 
12
#include <string.h>
 
13
#include <stdio.h>
 
14
#include <errno.h>
 
15
#include <unistd.h>
 
16
#include <sys/stat.h>
 
17
#include <fcntl.h>
 
18
#include <glib/gstdio.h>
 
19
 
 
20
#include "x-authority.h"
 
21
 
 
22
struct XAuthorityPrivate
 
23
{
 
24
    /* Protocol family */
 
25
    guint16 family;
 
26
 
 
27
    /* Address of the X server (format dependent on family) */
 
28
    guint8 *address;
 
29
    gsize address_length;
 
30
  
 
31
    /* Display number of X server */
 
32
    gchar *number;
 
33
 
 
34
    /* Authorization scheme */
 
35
    gchar *authorization_name;
 
36
 
 
37
    /* Authorization data */
 
38
    guint8 *authorization_data;
 
39
    gsize authorization_data_length;
 
40
};
 
41
 
 
42
G_DEFINE_TYPE (XAuthority, x_authority, G_TYPE_OBJECT);
 
43
 
 
44
XAuthority *
 
45
x_authority_new (guint16 family, const guint8 *address, gsize address_length, const gchar *number, const gchar *name, const guint8 *data, gsize data_length)
 
46
{
 
47
    XAuthority *auth = g_object_new (X_AUTHORITY_TYPE, NULL);
 
48
 
 
49
    x_authority_set_family (auth, family);  
 
50
    x_authority_set_address (auth, address, address_length);
 
51
    x_authority_set_number (auth, number);
 
52
    x_authority_set_authorization_name (auth, name);
 
53
    x_authority_set_authorization_data (auth, data, data_length);
 
54
 
 
55
    return auth;
 
56
}
 
57
 
 
58
XAuthority *
 
59
x_authority_new_cookie (guint16 family, const guint8 *address, gsize address_length, const gchar *number)
 
60
{
 
61
    guint8 cookie[16];
 
62
    gint i;
 
63
  
 
64
    for (i = 0; i < 16; i++)
 
65
        cookie[i] = g_random_int () & 0xFF;
 
66
 
 
67
    return x_authority_new (family, address, address_length, number, "MIT-MAGIC-COOKIE-1", cookie, 16);
 
68
}
 
69
 
 
70
void
 
71
x_authority_set_family (XAuthority *auth, guint16 family)
 
72
{
 
73
    g_return_if_fail (auth != NULL);
 
74
    auth->priv->family = family;
 
75
}
 
76
 
 
77
guint16
 
78
x_authority_get_family (XAuthority *auth)
 
79
{
 
80
    g_return_val_if_fail (auth != NULL, 0);
 
81
    return auth->priv->family;
 
82
}
 
83
 
 
84
void
 
85
x_authority_set_address (XAuthority *auth, const guint8 *address, gsize address_length)
 
86
{
 
87
    g_return_if_fail (auth != NULL);
 
88
    g_free (auth->priv->address);
 
89
    auth->priv->address = g_malloc (address_length);
 
90
    memcpy (auth->priv->address, address, address_length);
 
91
    auth->priv->address_length = address_length;
 
92
}
 
93
 
 
94
const guint8 *
 
95
x_authority_get_address (XAuthority *auth)
 
96
{
 
97
    g_return_val_if_fail (auth != NULL, NULL);
 
98
    return auth->priv->address;
 
99
}
 
100
 
 
101
const gsize
 
102
x_authority_get_address_length (XAuthority *auth)
 
103
{
 
104
    g_return_val_if_fail (auth != NULL, 0);
 
105
    return auth->priv->address_length;
 
106
}
 
107
 
 
108
void
 
109
x_authority_set_number (XAuthority *auth, const gchar *number)
 
110
{
 
111
    g_return_if_fail (auth != NULL);
 
112
    g_free (auth->priv->number);
 
113
    auth->priv->number = g_strdup (number);
 
114
}
 
115
 
 
116
const gchar *
 
117
x_authority_get_number (XAuthority *auth)
 
118
{
 
119
    g_return_val_if_fail (auth != NULL, NULL);
 
120
    return auth->priv->number;
 
121
}
 
122
 
 
123
void
 
124
x_authority_set_authorization_name (XAuthority *auth, const gchar *name)
 
125
{
 
126
    g_return_if_fail (auth != NULL);
 
127
    g_free (auth->priv->authorization_name);
 
128
    auth->priv->authorization_name = g_strdup (name);
 
129
}
 
130
 
 
131
const gchar *
 
132
x_authority_get_authorization_name (XAuthority *auth)
 
133
{
 
134
    g_return_val_if_fail (auth != NULL, NULL);
 
135
    return auth->priv->authorization_name;
 
136
}
 
137
 
 
138
void
 
139
x_authority_set_authorization_data (XAuthority *auth, const guint8 *data, gsize data_length)
 
140
{
 
141
    g_return_if_fail (auth != NULL);
 
142
    g_free (auth->priv->authorization_data);
 
143
    auth->priv->authorization_data = g_malloc (data_length);
 
144
    memcpy (auth->priv->authorization_data, data, data_length);
 
145
    auth->priv->authorization_data_length = data_length;
 
146
}
 
147
 
 
148
const guint8 *
 
149
x_authority_get_authorization_data (XAuthority *auth)
 
150
{
 
151
    g_return_val_if_fail (auth != NULL, NULL);
 
152
    return auth->priv->authorization_data;
 
153
}
 
154
 
 
155
guint8 *
 
156
x_authority_copy_authorization_data (XAuthority *auth)
 
157
{
 
158
    guint8 *data;
 
159
 
 
160
    g_return_val_if_fail (auth != NULL, NULL);
 
161
 
 
162
    data = g_malloc (auth->priv->authorization_data_length);
 
163
    memcpy (data, auth->priv->authorization_data, auth->priv->authorization_data_length);
 
164
    return data;
 
165
}
 
166
 
 
167
gsize
 
168
x_authority_get_authorization_data_length (XAuthority *auth)
 
169
{
 
170
    g_return_val_if_fail (auth != NULL, 0);
 
171
    return auth->priv->authorization_data_length;
 
172
}
 
173
 
 
174
static gboolean
 
175
read_uint16 (gchar *data, gsize data_length, gsize *offset, guint16 *value)
 
176
{
 
177
    if (data_length - *offset < 2)
 
178
        return FALSE;
 
179
 
 
180
    *value = data[*offset] << 8 | data[*offset + 1];
 
181
    *offset += 2;
 
182
 
 
183
    return TRUE;
 
184
}
 
185
 
 
186
static gboolean
 
187
read_data (gchar *data, gsize data_length, gsize *offset, guint16 length, guint8 **value)
 
188
{
 
189
    int i;
 
190
 
 
191
    g_free (*value);
 
192
    *value = NULL;
 
193
 
 
194
    if (data_length - *offset < length)
 
195
        return FALSE;
 
196
  
 
197
    *value = g_malloc0 (length + 1);
 
198
    for (i = 0; i < length; i++)
 
199
        (*value)[i] = data[*offset + i];
 
200
    *offset += length;
 
201
    (*value)[length] = 0;
 
202
 
 
203
    return TRUE;
 
204
}
 
205
 
 
206
static gboolean
 
207
read_string (gchar *data, gsize data_length, gsize *offset, gchar **value)
 
208
{
 
209
    guint16 length;
 
210
    if (!read_uint16 (data, data_length, offset, &length))
 
211
        return FALSE;
 
212
    return read_data (data, data_length, offset, length, (guint8 **) value);
 
213
}
 
214
 
 
215
static gboolean
 
216
write_uint16 (int fd, guint16 value)
 
217
{
 
218
    guint8 v[2];
 
219
    v[0] = value >> 8;
 
220
    v[1] = value & 0xFF;
 
221
    return write (fd, v, 2) == 2;
 
222
}
 
223
 
 
224
static gboolean
 
225
write_data (int fd, const guint8 *value, gsize value_length)
 
226
{
 
227
    return write (fd, value, value_length) == value_length;
 
228
}
 
229
 
 
230
static gboolean
 
231
write_string (int fd, const gchar *value)
 
232
{
 
233
    size_t value_length = strlen (value);
 
234
    return write_uint16 (fd, value_length) && write_data (fd, (guint8 *) value, value_length);
 
235
}
 
236
 
 
237
gboolean
 
238
x_authority_write (XAuthority *auth, XAuthWriteMode mode, const gchar *filename, GError **error)
 
239
{
 
240
    gchar *input = NULL;
 
241
    gsize input_length = 0, input_offset = 0;
 
242
    GList *link, *records = NULL;
 
243
    XAuthority *a;
 
244
    gboolean result = TRUE;
 
245
    gboolean matched = FALSE;
 
246
    int output_fd;
 
247
 
 
248
    g_return_val_if_fail (auth != NULL, FALSE);
 
249
    g_return_val_if_fail (filename != NULL, FALSE);
 
250
 
 
251
    /* Read out existing records */
 
252
    if (mode != XAUTH_WRITE_MODE_SET)
 
253
    {
 
254
        GError *read_error = NULL;
 
255
 
 
256
        g_file_get_contents (filename, &input, &input_length, &read_error);
 
257
        if (read_error && !g_error_matches (read_error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
 
258
            g_warning ("Error reading existing Xauthority: %s", read_error->message);
 
259
        g_clear_error (&read_error);
 
260
    }
 
261
    while (input_offset != input_length)
 
262
    {
 
263
        gboolean address_matches = FALSE;
 
264
        guint16 address_length = 0;
 
265
        guint16 authorization_data_length = 0;
 
266
 
 
267
        a = g_object_new (X_AUTHORITY_TYPE, NULL);
 
268
 
 
269
        result = read_uint16 (input, input_length, &input_offset, &a->priv->family) &&
 
270
                 read_uint16 (input, input_length, &input_offset, &address_length) &&
 
271
                 read_data (input, input_length, &input_offset, address_length, &a->priv->address) &&
 
272
                 read_string (input, input_length, &input_offset, &a->priv->number) &&
 
273
                 read_string (input, input_length, &input_offset, &a->priv->authorization_name) &&
 
274
                 read_uint16 (input, input_length, &input_offset, &authorization_data_length) &&
 
275
                 read_data (input, input_length, &input_offset, authorization_data_length, &a->priv->authorization_data);
 
276
        a->priv->address_length = address_length;
 
277
        a->priv->authorization_data_length = authorization_data_length;
 
278
 
 
279
        if (!result)
 
280
        {
 
281
            g_object_unref (a);
 
282
            break;
 
283
        }
 
284
 
 
285
        if (auth->priv->address_length == a->priv->address_length)
 
286
        {
 
287
            guint16 i;
 
288
            for (i = 0; i < auth->priv->address_length && auth->priv->address[i] == a->priv->address[i]; i++);
 
289
            address_matches = i == auth->priv->address_length;
 
290
        }
 
291
 
 
292
        /* If this record matches, then update or delete it */
 
293
        if (!matched &&
 
294
            auth->priv->family == a->priv->family &&
 
295
            address_matches &&
 
296
            strcmp (auth->priv->number, a->priv->number) == 0)
 
297
        {
 
298
            matched = TRUE;
 
299
            if (mode == XAUTH_WRITE_MODE_REMOVE)
 
300
            {
 
301
                g_object_unref (a);
 
302
                continue;
 
303
            }
 
304
            else
 
305
                x_authority_set_authorization_data (a, auth->priv->authorization_data, auth->priv->authorization_data_length);
 
306
        }
 
307
 
 
308
        records = g_list_append (records, a);
 
309
    }
 
310
    g_free (input);
 
311
 
 
312
    /* If didn't exist, then add a new one */
 
313
    if (!matched)
 
314
        records = g_list_append (records, g_object_ref (auth));
 
315
 
 
316
    /* Write records back */
 
317
    errno = 0;
 
318
    output_fd = g_open (filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
 
319
    if (output_fd < 0)
 
320
    {
 
321
        g_set_error (error,
 
322
                     G_FILE_ERROR,
 
323
                     g_file_error_from_errno (errno),
 
324
                     "Failed to open X authority %s: %s",
 
325
                     filename,
 
326
                     g_strerror (errno));
 
327
        return FALSE;
 
328
    }
 
329
 
 
330
    errno = 0;
 
331
    result = TRUE;
 
332
    for (link = records; link && result; link = link->next)
 
333
    {
 
334
        XAuthority *a = link->data;
 
335
 
 
336
        result = write_uint16 (output_fd, a->priv->family) &&
 
337
                 write_uint16 (output_fd, a->priv->address_length) &&
 
338
                 write_data (output_fd, a->priv->address, a->priv->address_length) &&
 
339
                 write_string (output_fd, a->priv->number) &&
 
340
                 write_string (output_fd, a->priv->authorization_name) &&
 
341
                 write_uint16 (output_fd, a->priv->authorization_data_length) &&
 
342
                 write_data (output_fd, a->priv->authorization_data, a->priv->authorization_data_length);
 
343
 
 
344
        g_object_unref (a);
 
345
    }
 
346
    g_list_free (records);
 
347
 
 
348
    close (output_fd);
 
349
 
 
350
    if (!result)
 
351
    {
 
352
        g_set_error (error,
 
353
                     G_FILE_ERROR,
 
354
                     g_file_error_from_errno (errno),
 
355
                     "Failed to write X authority %s: %s",
 
356
                     filename,
 
357
                     g_strerror (errno));
 
358
        return FALSE;
 
359
    }
 
360
 
 
361
    return TRUE;
 
362
}    
 
363
 
 
364
static void
 
365
x_authority_init (XAuthority *auth)
 
366
{
 
367
    auth->priv = G_TYPE_INSTANCE_GET_PRIVATE (auth, X_AUTHORITY_TYPE, XAuthorityPrivate);
 
368
    auth->priv->number = g_strdup ("");
 
369
}
 
370
 
 
371
static void
 
372
x_authority_finalize (GObject *object)
 
373
{
 
374
    XAuthority *self;
 
375
 
 
376
    self = X_AUTHORITY (object);
 
377
 
 
378
    g_free (self->priv->address);
 
379
    g_free (self->priv->number);
 
380
    g_free (self->priv->authorization_name);
 
381
    g_free (self->priv->authorization_data);
 
382
 
 
383
    G_OBJECT_CLASS (x_authority_parent_class)->finalize (object);  
 
384
}
 
385
 
 
386
static void
 
387
x_authority_class_init (XAuthorityClass *klass)
 
388
{
 
389
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
390
 
 
391
    object_class->finalize = x_authority_finalize;
 
392
 
 
393
    g_type_class_add_private (klass, sizeof (XAuthorityPrivate));
 
394
}