diff options
author | Robert Ancell <robert.ancell@canonical.com> | 2011-07-15 10:16:13 +1000 |
---|---|---|
committer | Robert Ancell <robert.ancell@canonical.com> | 2011-07-15 10:16:13 +1000 |
commit | bb774efe7f674c8740781724280cb802c53d40a5 (patch) | |
tree | dc90493f19b3e6511952a8fe1e2836759be1d431 /src | |
parent | 747b5449507fa3e246367801814ebce11b1b3116 (diff) | |
download | lightdm-bb774efe7f674c8740781724280cb802c53d40a5.tar.gz |
Reworked X authority code
Diffstat (limited to 'src')
-rw-r--r-- | src/child-process.c | 8 | ||||
-rw-r--r-- | src/display-manager.c | 35 | ||||
-rw-r--r-- | src/display.c | 26 | ||||
-rw-r--r-- | src/session.c | 54 | ||||
-rw-r--r-- | src/session.h | 2 | ||||
-rw-r--r-- | src/xauth.c | 312 | ||||
-rw-r--r-- | src/xauth.h | 39 | ||||
-rw-r--r-- | src/xdmcp-server.c | 4 | ||||
-rw-r--r-- | src/xserver.c | 34 |
9 files changed, 404 insertions, 110 deletions
diff --git a/src/child-process.c b/src/child-process.c index 8a81a81a..72689cf3 100644 --- a/src/child-process.c +++ b/src/child-process.c @@ -98,10 +98,7 @@ void child_process_set_env (ChildProcess *process, const gchar *name, const gchar *value) { g_return_if_fail (process != NULL); - if (value) - g_hash_table_insert (process->priv->env, g_strdup (name), g_strdup (value)); - else - g_hash_table_remove (process->priv->env, name); + g_hash_table_insert (process->priv->env, g_strdup (name), g_strdup (value)); } static void @@ -144,6 +141,7 @@ run_child_process (ChildProcess *process, char *const argv[]) close (fd); /* Set environment */ + clearenv (); g_hash_table_iter_init (&iter, process->priv->env); while (g_hash_table_iter_next (&iter, &key, &value)) g_setenv ((gchar *)key, (gchar *)value, TRUE); @@ -205,7 +203,7 @@ run_child_process (ChildProcess *process, char *const argv[]) } } - execvp (argv[0], argv); + execv (argv[0], argv); g_warning ("Error executing child process %s: %s", argv[0], g_strerror (errno)); _exit (EXIT_FAILURE); diff --git a/src/display-manager.c b/src/display-manager.c index e4531c0b..042ed013 100644 --- a/src/display-manager.c +++ b/src/display-manager.c @@ -126,13 +126,7 @@ start_session (Display *display, Session *session, gboolean is_greeter, DisplayM authorization = xserver_get_authorization (display_get_xserver (display)); if (authorization) - { - gchar *path; - - path = get_authorization_path (manager); - session_set_authorization (session, authorization, path); - g_free (path); - } + session_set_authorization (session, authorization); if (is_greeter) { @@ -201,10 +195,13 @@ end_session_cb (Display *display, Session *session, DisplayManager *manager) xserver = display_get_xserver (display); if (xserver && xserver_get_server_type (xserver) == XSERVER_TYPE_LOCAL) { - XAuthorization *authorization; + XAuthorization *old_authorization, *authorization; g_debug ("Generating new authorization cookie for %s", xserver_get_address (xserver)); - authorization = xauth_new_cookie (); + old_authorization = xserver_get_authorization (xserver); + authorization = xauth_new_cookie (xauth_get_family (old_authorization), + xauth_get_address (old_authorization), + xauth_get_number (old_authorization)); xserver_set_authorization (xserver, authorization, xserver_get_authorization_path (xserver)); g_object_unref (authorization); } @@ -298,13 +295,19 @@ make_xserver (DisplayManager *manager, gchar *config_section) string_to_xdm_auth_key (key, data); xserver_set_authentication (xserver, "XDM-AUTHENTICATION-1", data, 8); - authorization = xauth_new ("XDM-AUTHORIZATION-1", data, 8); + authorization = xauth_new (XAUTH_FAMILY_WILD, "", "", "XDM-AUTHORIZATION-1", data, 8); } } else { + gchar *number; + gchar hostname[1024]; + xserver = xserver_new (XSERVER_TYPE_LOCAL, NULL, display_number); - authorization = xauth_new_cookie (); + number = g_strdup_printf ("%d", display_number); + gethostname (hostname, 1024); + authorization = xauth_new_cookie (XAUTH_FAMILY_LOCAL, hostname, number); + g_free (number); } g_free (xdmcp_manager); @@ -476,7 +479,7 @@ xdmcp_session_cb (XDMCPServer *server, XDMCPSession *session, DisplayManager *ma gchar *address; XServer *xserver; gboolean result; - + // FIXME: Try IPv6 then fallback to IPv4 address = g_inet_address_to_string (G_INET_ADDRESS (xdmcp_session_get_address (session))); @@ -487,10 +490,16 @@ xdmcp_session_cb (XDMCPServer *server, XDMCPSession *session, DisplayManager *ma { XAuthorization *authorization = NULL; gchar *path; + gchar *number; - authorization = xauth_new (xdmcp_session_get_authorization_name (session), + number = g_strdup_printf ("%d", xdmcp_session_get_display_number (session)); + authorization = xauth_new (XAUTH_FAMILY_INTERNET, // FIXME: Handle IPv6 + address, + number, + xdmcp_session_get_authorization_name (session), xdmcp_session_get_authorization_data (session), xdmcp_session_get_authorization_data_length (session)); + g_free (number); path = get_authorization_path (manager); xserver_set_authorization (xserver, authorization, path); diff --git a/src/display.c b/src/display.c index b7147b85..8ffb8485 100644 --- a/src/display.c +++ b/src/display.c @@ -585,10 +585,23 @@ start_user_session (Display *display, const gchar *session) session_set_user (display->priv->user_session, user); session_set_command (display->priv->user_session, session_command); + child_process_set_env (CHILD_PROCESS (display->priv->user_session), "PATH", "/usr/local/bin:/usr/bin:/bin"); + child_process_set_env (CHILD_PROCESS (display->priv->user_session), "USER", user_get_name (user)); + child_process_set_env (CHILD_PROCESS (display->priv->user_session), "USERNAME", user_get_name (user)); // FIXME: Is this required? + child_process_set_env (CHILD_PROCESS (display->priv->user_session), "HOME", user_get_home_directory (user)); + child_process_set_env (CHILD_PROCESS (display->priv->user_session), "SHELL", user_get_shell (user)); child_process_set_env (CHILD_PROCESS (display->priv->user_session), "DESKTOP_SESSION", session); // FIXME: Apparently deprecated? child_process_set_env (CHILD_PROCESS (display->priv->user_session), "GDMSESSION", session); // FIXME: Not cross-desktop child_process_set_env (CHILD_PROCESS (display->priv->user_session), "DISPLAY", xserver_get_address (display->priv->xserver)); set_env_from_pam_session (display->priv->user_session, display->priv->user_pam_session); + + /* Variable required for regression tests */ + if (getenv ("LIGHTDM_TEST_STATUS_SOCKET")) + { + child_process_set_env (CHILD_PROCESS (display->priv->user_session), "LIGHTDM_TEST_STATUS_SOCKET", getenv ("LIGHTDM_TEST_STATUS_SOCKET")); + child_process_set_env (CHILD_PROCESS (display->priv->user_session), "LIGHTDM_TEST_CONFIG", getenv ("LIGHTDM_TEST_CONFIG")); + child_process_set_env (CHILD_PROCESS (display->priv->user_session), "LIGHTDM_TEST_HOME_DIR", getenv ("LIGHTDM_TEST_HOME_DIR")); + } g_object_unref (user); g_free (session_command); @@ -780,11 +793,24 @@ start_greeter (Display *display) command = theme_get_command (theme); session_set_command (SESSION (display->priv->greeter_session), command); g_free (command); + + child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "PATH", "/usr/local/bin:/usr/bin:/bin"); + child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "USER", user_get_name (user)); + child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "HOME", user_get_home_directory (user)); + child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "SHELL", user_get_shell (user)); child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "DISPLAY", xserver_get_address (display->priv->xserver)); if (display->priv->greeter_ck_cookie) child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "XDG_SESSION_COOKIE", display->priv->greeter_ck_cookie); set_env_from_pam_session (SESSION (display->priv->greeter_session), display->priv->greeter_pam_session); + /* Variable required for regression tests */ + if (getenv ("LIGHTDM_TEST_STATUS_SOCKET")) + { + child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "LIGHTDM_TEST_STATUS_SOCKET", getenv ("LIGHTDM_TEST_STATUS_SOCKET")); + child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "LIGHTDM_TEST_CONFIG", getenv ("LIGHTDM_TEST_CONFIG")); + child_process_set_env (CHILD_PROCESS (display->priv->greeter_session), "LIGHTDM_TEST_HOME_DIR", getenv ("LIGHTDM_TEST_HOME_DIR")); + } + g_signal_emit (display, signals[START_GREETER], 0, display->priv->greeter_session); result = session_start (SESSION (display->priv->greeter_session), TRUE); diff --git a/src/session.c b/src/session.c index 61267f01..937e4d93 100644 --- a/src/session.c +++ b/src/session.c @@ -23,18 +23,11 @@ struct SessionPrivate /* User running this session */ User *user; - /* Path of file to log to */ - gchar *log_file; - - /* Environment variables */ - GHashTable *env; - /* Command to run for this session */ gchar *command; /* X authorization */ XAuthorization *authorization; - gchar *authorization_path; GFile *authorization_file; }; @@ -80,15 +73,13 @@ session_get_command (Session *session) } void -session_set_authorization (Session *session, XAuthorization *authorization, const gchar *path) +session_set_authorization (Session *session, XAuthorization *authorization) { g_return_if_fail (session != NULL); if (session->priv->authorization) g_object_unref (session->priv->authorization); session->priv->authorization = g_object_ref (authorization); - g_free (session->priv->authorization_path); - session->priv->authorization_path = g_strdup (path); } XAuthorization * @@ -104,23 +95,29 @@ session_start (Session *session, gboolean create_pipe) //gint session_stdin, session_stdout, session_stderr; gboolean result; GError *error = NULL; + gchar *full_path; g_return_val_if_fail (session != NULL, FALSE); g_return_val_if_fail (session->priv->user != NULL, FALSE); g_return_val_if_fail (session->priv->command != NULL, FALSE); - child_process_set_env (CHILD_PROCESS (session), "USER", user_get_name (session->priv->user)); - child_process_set_env (CHILD_PROCESS (session), "USERNAME", user_get_name (session->priv->user)); // FIXME: Is this required? - child_process_set_env (CHILD_PROCESS (session), "HOME", user_get_home_directory (session->priv->user)); - child_process_set_env (CHILD_PROCESS (session), "SHELL", user_get_shell (session->priv->user)); + full_path = g_find_program_in_path (session->priv->command); + if (!full_path) + { + g_debug ("Can't launch session %s, not found in path", session->priv->command); + return FALSE; + } if (session->priv->authorization) { - g_debug ("Writing session authority to %s", session->priv->authorization_path); - session->priv->authorization_file = xauth_write (session->priv->authorization, session->priv->user, session->priv->authorization_path, &error); - if (session->priv->authorization_file) - child_process_set_env (CHILD_PROCESS (session), "XAUTHORITY", session->priv->authorization_path); - else + gchar *path; + + path = g_build_filename (user_get_home_directory (session->priv->user), ".Xauthority", NULL); + session->priv->authorization_file = g_file_new_for_path (path); + g_free (path); + + g_debug ("Adding session authority to %s", g_file_get_path (session->priv->authorization_file)); + if (!xauth_update (session->priv->authorization, session->priv->user, session->priv->authorization_file, &error)) g_warning ("Failed to write authorization: %s", error->message); g_clear_error (&error); } @@ -130,9 +127,10 @@ session_start (Session *session, gboolean create_pipe) result = child_process_start (CHILD_PROCESS (session), session->priv->user, user_get_home_directory (session->priv->user), - session->priv->command, + full_path, create_pipe, &error); + g_free (full_path); if (!result) g_warning ("Failed to spawn session: %s", error->message); @@ -152,7 +150,6 @@ static void session_init (Session *session) { session->priv = G_TYPE_INSTANCE_GET_PRIVATE (session, SESSION_TYPE, SessionPrivate); - session->priv->env = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } static void @@ -161,18 +158,19 @@ session_finalize (GObject *object) Session *self; self = SESSION (object); + + if (self->priv->authorization_file) + { + g_debug ("Removing session authority from %s", g_file_get_path (self->priv->authorization_file)); + xauth_remove (self->priv->authorization, self->priv->user, self->priv->authorization_file, NULL); + g_object_unref (self->priv->authorization_file); + } + if (self->priv->user) g_object_unref (self->priv->user); - g_hash_table_unref (self->priv->env); g_free (self->priv->command); if (self->priv->authorization) g_object_unref (self->priv->authorization); - g_free (self->priv->authorization_path); - if (self->priv->authorization_file) - { - g_file_delete (self->priv->authorization_file, NULL, NULL); - g_object_unref (self->priv->authorization_file); - } G_OBJECT_CLASS (session_parent_class)->finalize (object); } diff --git a/src/session.h b/src/session.h index 7383e742..7e79b3a9 100644 --- a/src/session.h +++ b/src/session.h @@ -46,7 +46,7 @@ void session_set_command (Session *session, const gchar *command); const gchar *session_get_command (Session *session); -void session_set_authorization (Session *session, XAuthorization *authorization, const gchar *path); +void session_set_authorization (Session *session, XAuthorization *authorization); XAuthorization *session_get_authorization (Session *session); diff --git a/src/xauth.c b/src/xauth.c index e4593648..72df2ca3 100644 --- a/src/xauth.c +++ b/src/xauth.c @@ -18,57 +18,135 @@ struct XAuthorizationPrivate { + /* Protocol family */ + guint16 family; + + /* Host address of X server */ + gchar *address; + + /* Display number of X server */ + gchar *number; + /* Authorization scheme */ gchar *authorization_name; /* Authorization data */ - guchar *authorization_data; + guint8 *authorization_data; gsize authorization_data_length; }; G_DEFINE_TYPE (XAuthorization, xauth, G_TYPE_OBJECT); XAuthorization * -xauth_new (const gchar *name, const guchar *data, gsize data_length) +xauth_new (guint16 family, const gchar *address, const gchar *number, const gchar *name, const guint8 *data, gsize data_length) { XAuthorization *auth = g_object_new (XAUTH_TYPE, NULL); - auth->priv->authorization_name = g_strdup (name); - auth->priv->authorization_data = g_malloc (data_length); - auth->priv->authorization_data_length = data_length; - memcpy (auth->priv->authorization_data, data, data_length); + xauth_set_family (auth, family); + xauth_set_address (auth, address); + xauth_set_number (auth, number); + xauth_set_authorization_name (auth, name); + xauth_set_authorization_data (auth, data, data_length); return auth; } XAuthorization * -xauth_new_cookie (void) +xauth_new_cookie (guint16 family, const gchar *address, const gchar *number) { - guchar cookie[16]; + guint8 cookie[16]; gint i; for (i = 0; i < 16; i++) cookie[i] = g_random_int () & 0xFF; - return xauth_new ("MIT-MAGIC-COOKIE-1", cookie, 16); + return xauth_new (family, address, number, "MIT-MAGIC-COOKIE-1", cookie, 16); +} + +void +xauth_set_family (XAuthorization *auth, guint16 family) +{ + g_return_if_fail (auth != NULL); + auth->priv->family = family; +} + +guint16 +xauth_get_family (XAuthorization *auth) +{ + g_return_val_if_fail (auth != NULL, 0); + return auth->priv->family; +} + +void +xauth_set_address (XAuthorization *auth, const gchar *address) +{ + g_return_if_fail (auth != NULL); + g_free (auth->priv->address); + auth->priv->address = g_strdup (address); +} + +const gchar * +xauth_get_address (XAuthorization *auth) +{ + g_return_val_if_fail (auth != NULL, NULL); + return auth->priv->address; +} + +void +xauth_set_number (XAuthorization *auth, const gchar *number) +{ + g_return_if_fail (auth != NULL); + g_free (auth->priv->number); + auth->priv->number = g_strdup (number); +} + +const gchar * +xauth_get_number (XAuthorization *auth) +{ + g_return_val_if_fail (auth != NULL, NULL); + return auth->priv->number; +} + +void +xauth_set_authorization_name (XAuthorization *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 * xauth_get_authorization_name (XAuthorization *auth) { + g_return_val_if_fail (auth != NULL, NULL); return auth->priv->authorization_name; } -const guchar * +void +xauth_set_authorization_data (XAuthorization *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 * xauth_get_authorization_data (XAuthorization *auth) { + g_return_val_if_fail (auth != NULL, NULL); return auth->priv->authorization_data; } -guchar * +guint8 * xauth_copy_authorization_data (XAuthorization *auth) { - guchar *data = g_malloc (auth->priv->authorization_data_length); + 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; } @@ -76,81 +154,211 @@ xauth_copy_authorization_data (XAuthorization *auth) gsize xauth_get_authorization_data_length (XAuthorization *auth) { + g_return_val_if_fail (auth != NULL, 0); return auth->priv->authorization_data_length; } -static void -write_uint16 (GString *string, guint16 value) +static guint16 +read_uint16 (GInputStream *stream, gboolean *eof, GError **error) +{ + guint8 data[2] = {0, 0}; + gsize n_read; + + if (error && *error) + return 0; + + if (g_input_stream_read_all (stream, data, 2, &n_read, NULL, error) < 0) + return 0; + + if (n_read == 0 && eof) + *eof = TRUE; + + return data[0] << 8 | data[1]; +} + +static guint8 * +read_data (GInputStream *stream, guint16 length, GError **error) { - g_string_append_c (string, (gchar) (value >> 8)); - g_string_append_c (string, (gchar) value); + guint8 *data; + + if (error && *error) + return NULL; + + data = g_malloc0 (length + 1); + if (g_input_stream_read_all (stream, data, length, NULL, NULL, error) < 0) + { + g_free (data); + return NULL; + } + data[length] = 0; + + return data; +} + +static gchar * +read_string (GInputStream *stream, GError **error) +{ + guint16 length; + length = read_uint16 (stream, NULL, error); + return (gchar *) read_data (stream, length, error); } static void -write_data (GString *string, guchar *value, gsize value_len) +write_uint16 (GOutputStream *stream, guint16 value, GError **error) { - g_string_append_len (string, (gchar *) value, value_len); + guint8 data[2]; + + if (error && *error) + return; + + data[0] = value >> 8; + data[1] = value & 0xFF; + g_output_stream_write (stream, data, 2, NULL, error); } static void -write_string (GString *string, const gchar *value) +write_data (GOutputStream *stream, const guint8 *data, gsize data_length, GError **error) { - write_uint16 (string, strlen (value)); - g_string_append (string, value); + if (error && *error) + return; + g_output_stream_write (stream, data, data_length, NULL, error); } -GFile * -xauth_write (XAuthorization *auth, User *user, const gchar *path, GError **error) +static void +write_string (GOutputStream *stream, const gchar *value, GError **error) { - GFile *file; - GFileOutputStream *stream; - GString *data; - gboolean result; - gsize n_written; + write_uint16 (stream, strlen (value), error); + write_data (stream, (guint8 *) value, strlen (value), error); +} - file = g_file_new_for_path (path); +static gboolean +xauth_merge (XAuthorization *auth, gboolean delete, User *user, GFile *file, GError **error) +{ + GList *link, *records = NULL; + GFileInputStream *input_stream; + GFileOutputStream *output_stream; + XAuthorization *a; + gboolean matched = FALSE; + + /* Read out existing records */ + input_stream = g_file_read (file, NULL, error); + if (!input_stream && error && !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + return FALSE; - stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_PRIVATE, NULL, error); - if (!stream) + while (input_stream) { - g_object_unref (file); + guint16 family; + gboolean eof = FALSE; + + family = read_uint16 (G_INPUT_STREAM (input_stream), &eof, error); + if (eof) + break; + + a = g_object_new (XAUTH_TYPE, NULL); + a->priv->family = family; + a->priv->address = read_string (G_INPUT_STREAM (input_stream), error); + a->priv->number = read_string (G_INPUT_STREAM (input_stream), error); + a->priv->authorization_name = read_string (G_INPUT_STREAM (input_stream), error); + a->priv->authorization_data_length = read_uint16 (G_INPUT_STREAM (input_stream), NULL, error); + a->priv->authorization_data = read_data (G_INPUT_STREAM (input_stream), a->priv->authorization_data_length, error); + + if (error && *error) + { + g_warning ("Error reading X authority %s: %s", g_file_get_path (file), (*error)->message); + g_clear_error (error); + break; + } + + /* If this record matches, then update or delete it */ + if (!matched && + auth->priv->family == family && + strcmp (auth->priv->address, a->priv->address) == 0 && + strcmp (auth->priv->number, a->priv->number) == 0) + { + matched = TRUE; + if (delete) + { + g_object_unref (a); + continue; + } + else + xauth_set_authorization_data (a, auth->priv->authorization_data, auth->priv->authorization_data_length); + } + + records = g_list_append (records, a); + } + if (input_stream) + { + g_input_stream_close (G_INPUT_STREAM (input_stream), NULL, error); + g_object_unref (input_stream); + } + + /* If didn't exist, then add a new one */ + if (!matched) + records = g_list_append (records, g_object_ref (auth)); + + output_stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_PRIVATE, NULL, error); + if (!output_stream) return FALSE; + + /* Workaround because g_file_replace () generates a file does not exist error even though it can replace it */ + g_clear_error (error); + + /* Write records back */ + for (link = records; link; link = link->next) + { + XAuthorization *a = link->data; + + write_uint16 (G_OUTPUT_STREAM (output_stream), a->priv->family, error); + write_string (G_OUTPUT_STREAM (output_stream), a->priv->address, error); + write_string (G_OUTPUT_STREAM (output_stream), a->priv->number, error); + write_string (G_OUTPUT_STREAM (output_stream), a->priv->authorization_name, error); + write_uint16 (G_OUTPUT_STREAM (output_stream), a->priv->authorization_data_length, error); + write_data (G_OUTPUT_STREAM (output_stream), a->priv->authorization_data, a->priv->authorization_data_length, error); + + g_object_unref (a); } + g_list_free (records); + g_output_stream_close (G_OUTPUT_STREAM (output_stream), NULL, error); + g_object_unref (output_stream); + + if (error && *error) + return FALSE; /* NOTE: Would like to do: * g_file_set_attribute_string (file, G_FILE_ATTRIBUTE_OWNER_USER, username, G_FILE_QUERY_INFO_NONE, NULL, error)) * but not supported. */ if (user && getuid () == 0) { - if (chown (path, user_get_uid (user), user_get_gid (user)) < 0) + if (chown (g_file_get_path (file), user_get_uid (user), user_get_gid (user)) < 0) g_warning ("Failed to set authorization owner: %s", strerror (errno)); } + + return TRUE; +} - data = g_string_sized_new (1024); - write_uint16 (data, 0xFFFF); /* FamilyWild - this entry is used for all connections */ - write_string (data, ""); /* Not requires as using FamilyWild */ - write_string (data, ""); /* Not requires as using FamilyWild */ - write_string (data, auth->priv->authorization_name); - write_uint16 (data, auth->priv->authorization_data_length); - write_data (data, auth->priv->authorization_data, auth->priv->authorization_data_length); - - result = g_output_stream_write_all (G_OUTPUT_STREAM (stream), data->str, data->len, &n_written, NULL, error); - g_string_free (data, TRUE); +gboolean +xauth_update (XAuthorization *auth, User *user, GFile *file, GError **error) +{ + g_return_val_if_fail (auth != NULL, FALSE); + g_return_val_if_fail (file != NULL, FALSE); + return xauth_merge (auth, FALSE, user, file, error); +} - g_object_unref (stream); - if (!result) - { - g_object_unref (file); - file = NULL; - } - - return file; +gboolean +xauth_remove (XAuthorization *auth, User *user, GFile *file, GError **error) +{ + g_return_val_if_fail (auth != NULL, FALSE); + g_return_val_if_fail (file != NULL, FALSE); + return xauth_merge (auth, TRUE, user, file, error); } static void xauth_init (XAuthorization *auth) { auth->priv = G_TYPE_INSTANCE_GET_PRIVATE (auth, XAUTH_TYPE, XAuthorizationPrivate); + auth->priv->address = g_strdup (""); + auth->priv->number = g_strdup (""); } static void @@ -160,6 +368,8 @@ xauth_finalize (GObject *object) self = XAUTH (object); + g_free (self->priv->address); + g_free (self->priv->number); g_free (self->priv->authorization_name); g_free (self->priv->authorization_data); diff --git a/src/xauth.h b/src/xauth.h index 538e1704..6f4b3ae6 100644 --- a/src/xauth.h +++ b/src/xauth.h @@ -35,21 +35,50 @@ typedef struct GObjectClass parent_class; } XAuthorizationClass; +#define XAUTH_FAMILY_INTERNET 0 +#define XAUTH_FAMILY_DECNET 1 +#define XAUTH_FAMILY_CHAOS 2 +#define XAUTH_FAMILY_SERVER_INTERPRETED 5 +#define XAUTH_FAMILY_INTERNET6 6 +#define XAUTH_FAMILY_LOCALHOST 252 +#define XAUTH_FAMILY_KRB5_PRINCIPAL 253 +#define XAUTH_FAMILY_NETNAME 254 +#define XAUTH_FAMILY_LOCAL 256 +#define XAUTH_FAMILY_WILD 65535 + GType xauth_get_type (void); -XAuthorization *xauth_new (const gchar *name, const guchar *data, gsize data_length); +XAuthorization *xauth_new (guint16 family, const gchar *address, const gchar *number, const gchar *name, const guint8 *data, gsize data_length); + +XAuthorization *xauth_new_cookie (guint16 family, const gchar *address, const gchar *number); + +void xauth_set_family (XAuthorization *auth, guint16 family); + +guint16 xauth_get_family (XAuthorization *auth); + +void xauth_set_address (XAuthorization *auth, const gchar *address); -XAuthorization *xauth_new_cookie (void); +const gchar *xauth_get_address (XAuthorization *auth); + +void xauth_set_number (XAuthorization *auth, const gchar *number); + +const gchar *xauth_get_number (XAuthorization *auth); + +void xauth_set_authorization_name (XAuthorization *auth, const gchar *name); const gchar *xauth_get_authorization_name (XAuthorization *auth); -const guchar *xauth_get_authorization_data (XAuthorization *auth); +void xauth_set_authorization_data (XAuthorization *auth, const guint8 *data, gsize data_length); -guchar *xauth_copy_authorization_data (XAuthorization *auth); +const guint8 *xauth_get_authorization_data (XAuthorization *auth); + +guint8 *xauth_copy_authorization_data (XAuthorization *auth); gsize xauth_get_authorization_data_length (XAuthorization *auth); -GFile *xauth_write (XAuthorization *auth, User *user, const gchar *path, GError **error); +gboolean xauth_update (XAuthorization *auth, User *user, GFile *file, GError **error); + +gboolean xauth_remove (XAuthorization *auth, User *user, GFile *file, GError **error); G_END_DECLS diff --git a/src/xdmcp-server.c b/src/xdmcp-server.c index 67b90c6c..bc914610 100644 --- a/src/xdmcp-server.c +++ b/src/xdmcp-server.c @@ -362,11 +362,13 @@ handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, X XAuthorization *auth; /* Data is the cookie */ - auth = xauth_new_cookie (); + auth = xauth_new_cookie (XAUTH_FAMILY_WILD, "", ""); authorization_data = xauth_copy_authorization_data (auth); authorization_data_length = xauth_get_authorization_data_length (auth); session_authorization_data = xauth_copy_authorization_data (auth); session_authorization_data_length = xauth_get_authorization_data_length (auth); + + g_object_unref (auth); } else if (strcmp (server->priv->authorization_name, "XDM-AUTHORIZATION-1") == 0) { diff --git a/src/xserver.c b/src/xserver.c index f17ada24..b10f4337 100644 --- a/src/xserver.c +++ b/src/xserver.c @@ -260,8 +260,8 @@ write_authorization_file (XServer *server) g_debug ("Writing X server authorization to %s", server->priv->authorization_path); - server->priv->authorization_file = xauth_write (server->priv->authorization, NULL, server->priv->authorization_path, &error); - if (!server->priv->authorization_file) + server->priv->authorization_file = g_file_new_for_path (server->priv->authorization_path); + if (!xauth_update (server->priv->authorization, NULL, server->priv->authorization_file, &error)) g_warning ("Failed to write authorization: %s", error->message); g_clear_error (&error); } @@ -372,6 +372,7 @@ xserver_start (XServer *server) { GError *error = NULL; gboolean result; + gchar *full_path; GString *command; g_return_val_if_fail (server != NULL, FALSE); @@ -392,12 +393,16 @@ xserver_start (XServer *server) g_return_val_if_fail (server->priv->command != NULL, FALSE); - /* Write the authorization file */ - write_authorization_file (server); + full_path = g_find_program_in_path (server->priv->command); + if (!full_path) + { + g_debug ("Can't launch X server %s, not found in path", server->priv->command); + return FALSE; + } + command = g_string_new (full_path); + g_free (full_path); - command = g_string_new (server->priv->command); g_string_append_printf (command, " :%d", server->priv->display_number); - //g_string_append_printf (command, " vt%d"); if (server->priv->config_file) g_string_append_printf (command, " -config %s", server->priv->config_file); @@ -434,8 +439,25 @@ xserver_start (XServer *server) if (server->priv->no_root) g_string_append (command, " -background none"); + /* Write the authorization file */ + write_authorization_file (server); + g_debug ("Launching X Server"); + /* If running inside another display then pass through those variables */ + if (getenv ("DISPLAY")) + child_process_set_env (CHILD_PROCESS (server), "DISPLAY", getenv ("DISPLAY")); + if (getenv ("XAUTHORITY")) + child_process_set_env (CHILD_PROCESS (server), "XAUTHORITY", getenv ("XAUTHORITY")); + + /* Variable required for regression tests */ + if (getenv ("LIGHTDM_TEST_STATUS_SOCKET")) + { + child_process_set_env (CHILD_PROCESS (server), "LIGHTDM_TEST_STATUS_SOCKET", getenv ("LIGHTDM_TEST_STATUS_SOCKET")); + child_process_set_env (CHILD_PROCESS (server), "LIGHTDM_TEST_CONFIG", getenv ("LIGHTDM_TEST_CONFIG")); + child_process_set_env (CHILD_PROCESS (server), "LIGHTDM_TEST_HOME_DIR", getenv ("LIGHTDM_TEST_HOME_DIR")); + } + result = child_process_start (CHILD_PROCESS (server), user_get_current (), NULL, |