2
* Copyright (C) 2010-2011 Robert Ancell.
3
* Author: Robert Ancell <robert.ancell@canonical.com>
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
18
#include <glib/gstdio.h>
20
#include "x-authority.h"
22
struct XAuthorityPrivate
27
/* Address of the X server (format dependent on family) */
31
/* Display number of X server */
34
/* Authorization scheme */
35
gchar *authorization_name;
37
/* Authorization data */
38
guint8 *authorization_data;
39
gsize authorization_data_length;
42
G_DEFINE_TYPE (XAuthority, x_authority, G_TYPE_OBJECT);
45
x_authority_new (guint16 family, const guint8 *address, gsize address_length, const gchar *number, const gchar *name, const guint8 *data, gsize data_length)
47
XAuthority *auth = g_object_new (X_AUTHORITY_TYPE, NULL);
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);
59
x_authority_new_cookie (guint16 family, const guint8 *address, gsize address_length, const gchar *number)
64
for (i = 0; i < 16; i++)
65
cookie[i] = g_random_int () & 0xFF;
67
return x_authority_new (family, address, address_length, number, "MIT-MAGIC-COOKIE-1", cookie, 16);
71
x_authority_set_family (XAuthority *auth, guint16 family)
73
g_return_if_fail (auth != NULL);
74
auth->priv->family = family;
78
x_authority_get_family (XAuthority *auth)
80
g_return_val_if_fail (auth != NULL, 0);
81
return auth->priv->family;
85
x_authority_set_address (XAuthority *auth, const guint8 *address, gsize address_length)
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;
95
x_authority_get_address (XAuthority *auth)
97
g_return_val_if_fail (auth != NULL, NULL);
98
return auth->priv->address;
102
x_authority_get_address_length (XAuthority *auth)
104
g_return_val_if_fail (auth != NULL, 0);
105
return auth->priv->address_length;
109
x_authority_set_number (XAuthority *auth, const gchar *number)
111
g_return_if_fail (auth != NULL);
112
g_free (auth->priv->number);
113
auth->priv->number = g_strdup (number);
117
x_authority_get_number (XAuthority *auth)
119
g_return_val_if_fail (auth != NULL, NULL);
120
return auth->priv->number;
124
x_authority_set_authorization_name (XAuthority *auth, const gchar *name)
126
g_return_if_fail (auth != NULL);
127
g_free (auth->priv->authorization_name);
128
auth->priv->authorization_name = g_strdup (name);
132
x_authority_get_authorization_name (XAuthority *auth)
134
g_return_val_if_fail (auth != NULL, NULL);
135
return auth->priv->authorization_name;
139
x_authority_set_authorization_data (XAuthority *auth, const guint8 *data, gsize data_length)
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;
149
x_authority_get_authorization_data (XAuthority *auth)
151
g_return_val_if_fail (auth != NULL, NULL);
152
return auth->priv->authorization_data;
156
x_authority_copy_authorization_data (XAuthority *auth)
160
g_return_val_if_fail (auth != NULL, NULL);
162
data = g_malloc (auth->priv->authorization_data_length);
163
memcpy (data, auth->priv->authorization_data, auth->priv->authorization_data_length);
168
x_authority_get_authorization_data_length (XAuthority *auth)
170
g_return_val_if_fail (auth != NULL, 0);
171
return auth->priv->authorization_data_length;
175
read_uint16 (gchar *data, gsize data_length, gsize *offset, guint16 *value)
177
if (data_length - *offset < 2)
180
*value = data[*offset] << 8 | data[*offset + 1];
187
read_data (gchar *data, gsize data_length, gsize *offset, guint16 length, guint8 **value)
194
if (data_length - *offset < length)
197
*value = g_malloc0 (length + 1);
198
for (i = 0; i < length; i++)
199
(*value)[i] = data[*offset + i];
201
(*value)[length] = 0;
207
read_string (gchar *data, gsize data_length, gsize *offset, gchar **value)
210
if (!read_uint16 (data, data_length, offset, &length))
212
return read_data (data, data_length, offset, length, (guint8 **) value);
216
write_uint16 (int fd, guint16 value)
221
return write (fd, v, 2) == 2;
225
write_data (int fd, const guint8 *value, gsize value_length)
227
return write (fd, value, value_length) == value_length;
231
write_string (int fd, const gchar *value)
233
size_t value_length = strlen (value);
234
return write_uint16 (fd, value_length) && write_data (fd, (guint8 *) value, value_length);
238
x_authority_write (XAuthority *auth, XAuthWriteMode mode, const gchar *filename, GError **error)
241
gsize input_length = 0, input_offset = 0;
242
GList *link, *records = NULL;
244
gboolean result = TRUE;
245
gboolean matched = FALSE;
248
g_return_val_if_fail (auth != NULL, FALSE);
249
g_return_val_if_fail (filename != NULL, FALSE);
251
/* Read out existing records */
252
if (mode != XAUTH_WRITE_MODE_SET)
254
GError *read_error = NULL;
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);
261
while (input_offset != input_length)
263
gboolean address_matches = FALSE;
264
guint16 address_length = 0;
265
guint16 authorization_data_length = 0;
267
a = g_object_new (X_AUTHORITY_TYPE, NULL);
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;
285
if (auth->priv->address_length == a->priv->address_length)
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;
292
/* If this record matches, then update or delete it */
294
auth->priv->family == a->priv->family &&
296
strcmp (auth->priv->number, a->priv->number) == 0)
299
if (mode == XAUTH_WRITE_MODE_REMOVE)
305
x_authority_set_authorization_data (a, auth->priv->authorization_data, auth->priv->authorization_data_length);
308
records = g_list_append (records, a);
312
/* If didn't exist, then add a new one */
314
records = g_list_append (records, g_object_ref (auth));
316
/* Write records back */
318
output_fd = g_open (filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
323
g_file_error_from_errno (errno),
324
"Failed to open X authority %s: %s",
332
for (link = records; link && result; link = link->next)
334
XAuthority *a = link->data;
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);
346
g_list_free (records);
354
g_file_error_from_errno (errno),
355
"Failed to write X authority %s: %s",
365
x_authority_init (XAuthority *auth)
367
auth->priv = G_TYPE_INSTANCE_GET_PRIVATE (auth, X_AUTHORITY_TYPE, XAuthorityPrivate);
368
auth->priv->number = g_strdup ("");
372
x_authority_finalize (GObject *object)
376
self = X_AUTHORITY (object);
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);
383
G_OBJECT_CLASS (x_authority_parent_class)->finalize (object);
387
x_authority_class_init (XAuthorityClass *klass)
389
GObjectClass *object_class = G_OBJECT_CLASS (klass);
391
object_class->finalize = x_authority_finalize;
393
g_type_class_add_private (klass, sizeof (XAuthorityPrivate));