diff options
author | Robert Ancell <robert.ancell@canonical.com> | 2013-07-24 15:02:30 +1200 |
---|---|---|
committer | Robert Ancell <robert.ancell@canonical.com> | 2013-07-24 15:02:30 +1200 |
commit | 2085c8a8160dc661f7b5486e4cd700c57b63dffd (patch) | |
tree | 4ab352dad74ad4951bc0ea2f6fa387cefc023079 /src/x-authority.c | |
parent | e7d20496246a38ec388a6be665c1a0154dab7478 (diff) | |
download | lightdm-2085c8a8160dc661f7b5486e4cd700c57b63dffd.tar.gz |
Name X modules with standard naming format
Diffstat (limited to 'src/x-authority.c')
-rw-r--r-- | src/x-authority.c | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/src/x-authority.c b/src/x-authority.c new file mode 100644 index 00000000..c51896f0 --- /dev/null +++ b/src/x-authority.c @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2010-2011 Robert Ancell. + * Author: Robert Ancell <robert.ancell@canonical.com> + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. See http://www.gnu.org/copyleft/gpl.html the full text of the + * license. + */ + +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <sys/stat.h> + +#include "x-authority.h" + +struct XAuthorityPrivate +{ + /* Protocol family */ + guint16 family; + + /* Address of the X server (format dependent on family) */ + guint8 *address; + gsize address_length; + + /* Display number of X server */ + gchar *number; + + /* Authorization scheme */ + gchar *authorization_name; + + /* Authorization data */ + guint8 *authorization_data; + gsize authorization_data_length; +}; + +G_DEFINE_TYPE (XAuthority, x_authority, G_TYPE_OBJECT); + +XAuthority * +x_authority_new (guint16 family, const guint8 *address, gsize address_length, const gchar *number, const gchar *name, const guint8 *data, gsize data_length) +{ + XAuthority *auth = g_object_new (X_AUTHORITY_TYPE, NULL); + + x_authority_set_family (auth, family); + x_authority_set_address (auth, address, address_length); + x_authority_set_number (auth, number); + x_authority_set_authorization_name (auth, name); + x_authority_set_authorization_data (auth, data, data_length); + + return auth; +} + +XAuthority * +x_authority_new_cookie (guint16 family, const guint8 *address, gsize address_length, const gchar *number) +{ + guint8 cookie[16]; + gint i; + + for (i = 0; i < 16; i++) + cookie[i] = g_random_int () & 0xFF; + + return x_authority_new (family, address, address_length, number, "MIT-MAGIC-COOKIE-1", cookie, 16); +} + +void +x_authority_set_family (XAuthority *auth, guint16 family) +{ + g_return_if_fail (auth != NULL); + auth->priv->family = family; +} + +guint16 +x_authority_get_family (XAuthority *auth) +{ + g_return_val_if_fail (auth != NULL, 0); + return auth->priv->family; +} + +void +x_authority_set_address (XAuthority *auth, const guint8 *address, gsize address_length) +{ + g_return_if_fail (auth != NULL); + g_free (auth->priv->address); + auth->priv->address = g_malloc (address_length); + memcpy (auth->priv->address, address, address_length); + auth->priv->address_length = address_length; +} + +const guint8 * +x_authority_get_address (XAuthority *auth) +{ + g_return_val_if_fail (auth != NULL, NULL); + return auth->priv->address; +} + +const gsize +x_authority_get_address_length (XAuthority *auth) +{ + g_return_val_if_fail (auth != NULL, 0); + return auth->priv->address_length; +} + +void +x_authority_set_number (XAuthority *auth, const gchar *number) +{ + g_return_if_fail (auth != NULL); + g_free (auth->priv->number); + auth->priv->number = g_strdup (number); +} + +const gchar * +x_authority_get_number (XAuthority *auth) +{ + g_return_val_if_fail (auth != NULL, NULL); + return auth->priv->number; +} + +void +x_authority_set_authorization_name (XAuthority *auth, const gchar *name) +{ + g_return_if_fail (auth != NULL); + g_free (auth->priv->authorization_name); + auth->priv->authorization_name = g_strdup (name); +} + +const gchar * +x_authority_get_authorization_name (XAuthority *auth) +{ + g_return_val_if_fail (auth != NULL, NULL); + return auth->priv->authorization_name; +} + +void +x_authority_set_authorization_data (XAuthority *auth, const guint8 *data, gsize data_length) +{ + g_return_if_fail (auth != NULL); + g_free (auth->priv->authorization_data); + auth->priv->authorization_data = g_malloc (data_length); + memcpy (auth->priv->authorization_data, data, data_length); + auth->priv->authorization_data_length = data_length; +} + +const guint8 * +x_authority_get_authorization_data (XAuthority *auth) +{ + g_return_val_if_fail (auth != NULL, NULL); + return auth->priv->authorization_data; +} + +guint8 * +x_authority_copy_authorization_data (XAuthority *auth) +{ + guint8 *data; + + g_return_val_if_fail (auth != NULL, NULL); + + data = g_malloc (auth->priv->authorization_data_length); + memcpy (data, auth->priv->authorization_data, auth->priv->authorization_data_length); + return data; +} + +gsize +x_authority_get_authorization_data_length (XAuthority *auth) +{ + g_return_val_if_fail (auth != NULL, 0); + return auth->priv->authorization_data_length; +} + +static gboolean +read_uint16 (gchar *data, gsize data_length, gsize *offset, guint16 *value) +{ + if (data_length - *offset < 2) + return FALSE; + + *value = data[*offset] << 8 | data[*offset + 1]; + *offset += 2; + + return TRUE; +} + +static gboolean +read_data (gchar *data, gsize data_length, gsize *offset, guint16 length, guint8 **value) +{ + int i; + + g_free (*value); + *value = NULL; + + if (data_length - *offset < length) + return FALSE; + + *value = g_malloc0 (length + 1); + for (i = 0; i < length; i++) + (*value)[i] = data[*offset + i]; + *offset += length; + (*value)[length] = 0; + + return TRUE; +} + +static gboolean +read_string (gchar *data, gsize data_length, gsize *offset, gchar **value) +{ + guint16 length; + if (!read_uint16 (data, data_length, offset, &length)) + return FALSE; + return read_data (data, data_length, offset, length, (guint8 **) value); +} + +static void +write_uint16 (FILE *file, guint16 value) +{ + guint8 v[2]; + v[0] = value >> 8; + v[1] = value & 0xFF; + fwrite (v, 2, 1, file); +} + +static void +write_data (FILE *file, const guint8 *value, gsize value_length) +{ + fwrite (value, value_length, 1, file); +} + +static void +write_string (FILE *file, const gchar *value) +{ + write_uint16 (file, strlen (value)); + write_data (file, (guint8 *) value, strlen (value)); +} + +gboolean +x_authority_write (XAuthority *auth, XAuthWriteMode mode, const gchar *filename, GError **error) +{ + gchar *input; + gsize input_length = 0, input_offset = 0; + GList *link, *records = NULL; + XAuthority *a; + gboolean result; + gboolean matched = FALSE; + FILE *output; + + g_return_val_if_fail (auth != NULL, FALSE); + g_return_val_if_fail (filename != NULL, FALSE); + + /* Read out existing records */ + if (mode != XAUTH_WRITE_MODE_SET) + { + GError *read_error = NULL; + + g_file_get_contents (filename, &input, &input_length, &read_error); + if (read_error && !g_error_matches (read_error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) + g_warning ("Error reading existing Xauthority: %s", read_error->message); + g_clear_error (&read_error); + } + while (input_offset != input_length) + { + gboolean address_matches = FALSE; + guint16 address_length = 0; + guint16 authorization_data_length = 0; + + a = g_object_new (X_AUTHORITY_TYPE, NULL); + + result = read_uint16 (input, input_length, &input_offset, &a->priv->family) && + read_uint16 (input, input_length, &input_offset, &address_length) && + read_data (input, input_length, &input_offset, address_length, &a->priv->address) && + read_string (input, input_length, &input_offset, &a->priv->number) && + read_string (input, input_length, &input_offset, &a->priv->authorization_name) && + read_uint16 (input, input_length, &input_offset, &authorization_data_length) && + read_data (input, input_length, &input_offset, authorization_data_length, &a->priv->authorization_data); + a->priv->address_length = address_length; + a->priv->authorization_data_length = authorization_data_length; + + if (!result) + { + g_object_unref (a); + break; + } + + if (auth->priv->address_length == a->priv->address_length) + { + guint16 i; + for (i = 0; i < auth->priv->address_length && auth->priv->address[i] == a->priv->address[i]; i++); + address_matches = i == auth->priv->address_length; + } + + /* If this record matches, then update or delete it */ + if (!matched && + auth->priv->family == a->priv->family && + address_matches && + strcmp (auth->priv->number, a->priv->number) == 0) + { + matched = TRUE; + if (mode == XAUTH_WRITE_MODE_REMOVE) + { + g_object_unref (a); + continue; + } + else + x_authority_set_authorization_data (a, auth->priv->authorization_data, auth->priv->authorization_data_length); + } + + records = g_list_append (records, a); + } + g_free (input); + + /* If didn't exist, then add a new one */ + if (!matched) + records = g_list_append (records, g_object_ref (auth)); + + /* Write records back */ + errno = 0; + output = fopen (filename, "w"); + if (output == NULL) + { + g_set_error (error, + G_FILE_ERROR, + g_file_error_from_errno (errno), + "Failed to write X authority %s: %s", + filename, + g_strerror (errno)); + return FALSE; + } + + for (link = records; link && result; link = link->next) + { + XAuthority *a = link->data; + + write_uint16 (output, a->priv->family); + write_uint16 (output, a->priv->address_length); + write_data (output, a->priv->address, a->priv->address_length); + write_string (output, a->priv->number); + write_string (output, a->priv->authorization_name); + write_uint16 (output, a->priv->authorization_data_length); + write_data (output, a->priv->authorization_data, a->priv->authorization_data_length); + + g_object_unref (a); + } + g_list_free (records); + + fclose (output); + + return TRUE; +} + +static void +x_authority_init (XAuthority *auth) +{ + auth->priv = G_TYPE_INSTANCE_GET_PRIVATE (auth, X_AUTHORITY_TYPE, XAuthorityPrivate); + auth->priv->number = g_strdup (""); +} + +static void +x_authority_finalize (GObject *object) +{ + XAuthority *self; + + self = X_AUTHORITY (object); + + g_free (self->priv->address); + g_free (self->priv->number); + g_free (self->priv->authorization_name); + g_free (self->priv->authorization_data); + + G_OBJECT_CLASS (x_authority_parent_class)->finalize (object); +} + +static void +x_authority_class_init (XAuthorityClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = x_authority_finalize; + + g_type_class_add_private (klass, sizeof (XAuthorityPrivate)); +} |