diff options
Diffstat (limited to 'daemon')
45 files changed, 0 insertions, 30599 deletions
diff --git a/daemon/.cvsignore b/daemon/.cvsignore deleted file mode 100644 index 6f47639e..00000000 --- a/daemon/.cvsignore +++ /dev/null @@ -1,6 +0,0 @@ -Makefile -Makefile.in -.deps -.libs -gdm -gdm-binary diff --git a/daemon/Makefile.am b/daemon/Makefile.am deleted file mode 100644 index 300538e8..00000000 --- a/daemon/Makefile.am +++ /dev/null @@ -1,127 +0,0 @@ -NULL = - -# Note that we have cflags for just about everything even if -# we don't link to everything -INCLUDES = \ - -I. \ - -I.. \ - -I$(top_srcdir)/common \ - -DAUTHDIR=\"$(authdir)\" \ - -DBINDIR=\"$(bindir)\" \ - -DDATADIR=\"$(datadir)\" \ - -DDMCONFDIR=\"$(dmconfdir)\" \ - -DGDMCONFDIR=\"$(gdmconfdir)\" \ - -DGDMLOCALEDIR=\"$(gdmlocaledir)\" \ - -DLIBDIR=\"$(libdir)\" \ - -DLIBEXECDIR=\"$(libexecdir)\" \ - -DLOGDIR=\"$(logdir)\" \ - -DPIXMAPDIR=\"$(pixmapdir)\" \ - -DSBINDIR=\"$(sbindir)\" \ - -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ - -DGDM_DEFAULTS_CONF=\"$(GDM_DEFAULTS_CONF)\" \ - -DGDM_CUSTOM_CONF=\"$(GDM_CUSTOM_CONF)\" \ - -DGDM_OLD_CONF=\"$(GDM_OLD_CONF)\" \ - $(GUI_CFLAGS) \ - $(DAEMON_CFLAGS) \ - -DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\" \ - $(GNOME_INCLUDEDIR) \ - -DGREETERTHEMEDIR=\""$(datadir)/gdm/themes"\" \ - $(NULL) - -sbin_PROGRAMS = gdm-binary \ - $(NULL) - -gdm_binary_SOURCES = \ - gdm.c \ - gdm.h \ - gdm-daemon-config.c \ - gdm-daemon-config.h \ - gdm-daemon-config-entries.h \ - display.c \ - display.h \ - fstype.c \ - slave.c \ - slave.h \ - server.c \ - server.h \ - misc.c \ - misc.h \ - auth.c \ - auth.h \ - cookie.c \ - cookie.h \ - xdmcp.c \ - xdmcp.h \ - choose.c \ - choose.h \ - filecheck.c \ - filecheck.h \ - md5.c \ - md5.h \ - @VRFY@.c \ - verify.h \ - errorgui.c \ - errorgui.h \ - gdm-net.c \ - gdm-net.h \ - getvt.c \ - getvt.h \ - $(NULL) - -XDMCP_SOURCES = \ - gdm-xdmcp-manager.c \ - gdm-xdmcp-manager.h \ - $(NULL) - -if XDMCP_SUPPORT -gdm_binary_SOURCES += $(XDMCP_SOURCES) -endif - -EXTRA_gdm_binary_SOURCES = \ - verify-pam.c \ - verify-crypt.c \ - verify-shadow.c \ - $(XDMCP_SOURCES) \ - $(NULL) - -CONSOLE_KIT_SOURCES = \ - gdmconsolekit.c \ - gdmconsolekit.h \ - $(NULL) - -EXTRA_gdm_binary_SOURCES += $(CONSOLE_KIT_SOURCES) - -# Note that these libs are in LDFLAGS because they should come before -# everything else on the link line as they may override stuff -gdm_binary_LDFLAGS = \ - $(EXTRA_DAEMON_LIBS) \ - $(NULL) - -gdm_binary_LDADD = \ - $(DAEMON_LIBS) \ - $(INTLLIBS) \ - $(GLIB_LIBS) \ - $(GOBJECT_LIBS) \ - $(GDK_LIBS) \ - $(top_builddir)/common/libgdmcommon.a \ - $(X_LIBS) \ - $(XINERAMA_LIBS) \ - $(XDMCP_LIBS) \ - -lXau \ - -lX11 \ - -lXext \ - $(NULL) - -if WITH_CONSOLE_KIT -gdm_binary_SOURCES += $(CONSOLE_KIT_SOURCES) -gdm_binary_LDADD += $(DBUS_LIBS) -INCLUDES += $(DBUS_CFLAGS) -endif - -sbin_SCRIPTS = gdm -CLEANFILES = gdm - -gdm: $(srcdir)/gdm.in - sed -e 's,[@]sbindir[@],$(sbindir),g' <$(srcdir)/gdm.in >gdm - -EXTRA_DIST = gdm.in diff --git a/daemon/auth.c b/daemon/auth.c deleted file mode 100644 index b47c7316..00000000 --- a/daemon/auth.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Code for cookie handling. This really needs to be modularized to - * support other XAuth types and possibly DECnet... */ - -#include "config.h" - -#include <stdlib.h> -#include <unistd.h> -#include <fcntl.h> -#include <netdb.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <netinet/in.h> -#include <errno.h> - -#include <X11/Xauth.h> -#include <glib/gi18n.h> - -#include "gdm.h" -#include "cookie.h" -#include "misc.h" -#include "filecheck.h" -#include "auth.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -/* Ensure we know about FamilyInternetV6 even if what we're compiling - against doesn't */ -#ifdef ENABLE_IPV6 -#ifndef FamilyInternetV6 -#define FamilyInternetV6 6 -#endif /* ! FamilyInternetV6 */ -#endif /* ENABLE_IPV6 */ - -/* Local prototypes */ -static FILE *gdm_auth_purge (GdmDisplay *d, FILE *af, gboolean remove_when_empty); - -static void -display_add_error (GdmDisplay *d) -{ - if (errno != 0) - gdm_error (_("%s: Could not write new authorization entry: %s"), - "add_auth_entry", strerror (errno)); - else - gdm_error (_("%s: Could not write new authorization entry. " - "Possibly out of diskspace"), - "add_auth_entry"); - if (d->attached) { - char *s = g_strdup_printf - (C_(N_("GDM could not write a new authorization " - "entry to disk. Possibly out of diskspace.%s%s")), - errno != 0 ? " Error: " : "", - errno != 0 ? strerror (errno) : ""); - gdm_text_message_dialog (s); - g_free (s); - } -} - -static gboolean -add_auth_entry (GdmDisplay *d, - GSList **authlist, - FILE *af, - FILE *af2, - unsigned short family, - const char *addr, - int addrlen) -{ - Xauth *xa; - gchar *dispnum; - - if G_UNLIKELY (!d) - return FALSE; - - xa = malloc (sizeof (Xauth)); - - if G_UNLIKELY (xa == NULL) - return FALSE; - - xa->family = family; - if (addrlen == 0) { - xa->address = NULL; - xa->address_length = 0; - } else { - xa->address = malloc (addrlen); - if G_UNLIKELY (xa->address == NULL) { - free (xa); - return FALSE; - } - - memcpy (xa->address, addr, addrlen); - xa->address_length = addrlen; - } - - dispnum = g_strdup_printf ("%d", d->dispnum); - xa->number = strdup (dispnum); - xa->number_length = strlen (dispnum); - g_free (dispnum); - - xa->name = strdup ("MIT-MAGIC-COOKIE-1"); - xa->name_length = strlen ("MIT-MAGIC-COOKIE-1"); - xa->data = malloc (16); - if G_UNLIKELY (xa->data == NULL) { - free (xa->number); - free (xa->name); - free (xa->address); - free (xa); - return FALSE; - } - memcpy (xa->data, d->bcookie, 16); - xa->data_length = 16; - - if (af != NULL) { - errno = 0; - if G_UNLIKELY ( ! XauWriteAuth (af, xa)) { - free (xa->data); - free (xa->number); - free (xa->name); - free (xa->address); - free (xa); - display_add_error (d); - return FALSE; - } - - if (af2 != NULL) { - errno = 0; - if G_UNLIKELY ( ! XauWriteAuth (af2, xa)) { - free (xa->data); - free (xa->number); - free (xa->name); - free (xa->address); - free (xa); - display_add_error (d); - return FALSE; - } - } - } - - *authlist = g_slist_append (*authlist, xa); - - return TRUE; -} - -/** - * gdm_auth_secure_display: - * @d: Pointer to a GdmDisplay struct - * - * Create authentication cookies for local and remote displays. - * - * Returns TRUE on success and FALSE on error. - */ - -gboolean -gdm_auth_secure_display (GdmDisplay *d) -{ - FILE *af, *af_gdm; - int closeret; - - if G_UNLIKELY (!d) - return FALSE; - - umask (022); - - gdm_debug ("gdm_auth_secure_display: Setting up access for %s", d->name); - - g_free (d->authfile); - d->authfile = NULL; - g_free (d->authfile_gdm); - d->authfile_gdm = NULL; - - if (d->server_uid != 0) { - int authfd; - - /* Note, nested display can't use the GDM_KEY_SERV_AUTHDIR unless - * running as root, which is rare anyway. */ - - d->authfile = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL); - - umask (077); - authfd = g_mkstemp (d->authfile); - umask (022); - - if G_UNLIKELY (authfd == -1) { - gdm_error (_("%s: Could not make new cookie file in %s"), - "gdm_auth_secure_display", gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK)); - g_free (d->authfile); - d->authfile = NULL; - return FALSE; - } - - /* Make it owned by the user that nested display is started as */ - fchown (authfd, d->server_uid, -1); - - VE_IGNORE_EINTR (af = fdopen (authfd, "w")); - - if G_UNLIKELY (af == NULL) { - g_free (d->authfile); - d->authfile = NULL; - return FALSE; - } - - /* Make another authfile since the greeter can't read the server/user - * readable file */ - d->authfile_gdm = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth"); - af_gdm = gdm_safe_fopen_w (d->authfile_gdm); - - if G_UNLIKELY (af_gdm == NULL) { - gdm_error (_("%s: Cannot safely open %s"), - "gdm_auth_secure_display", - d->authfile_gdm); - - g_free (d->authfile_gdm); - d->authfile_gdm = NULL; - g_free (d->authfile); - d->authfile = NULL; - VE_IGNORE_EINTR (fclose (af)); - return FALSE; - } - } else { - /* gdm and xserver authfile can be the same, server will run as root */ - d->authfile = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth"); - af = gdm_safe_fopen_w (d->authfile); - - if G_UNLIKELY (af == NULL) { - gdm_error (_("%s: Cannot safely open %s"), - "gdm_auth_secure_display", - d->authfile); - - g_free (d->authfile); - d->authfile = NULL; - return FALSE; - } - - af_gdm = NULL; - } - - /* If this is a local display the struct hasn't changed and we - * have to eat up old authentication cookies before baking new - * ones... */ - if (SERVER_IS_LOCAL (d) && d->auths) { - gdm_auth_free_auth_list (d->auths); - d->auths = NULL; - - g_free (d->cookie); - d->cookie = NULL; - g_free (d->bcookie); - d->bcookie = NULL; - } - - /* Create new random cookie */ - gdm_cookie_generate (&d->cookie, &d->bcookie); - - /* reget local host if local as it may have changed */ - if (SERVER_IS_LOCAL (d)) { - char hostname[1024]; - - hostname[1023] = '\0'; - if G_LIKELY (gethostname (hostname, 1023) == 0) { - g_free (d->hostname); - d->hostname = g_strdup (hostname); - } - } - - if ( ! add_auth_entry (d, &(d->auths), af, af_gdm, FamilyWild, NULL, 0)) - return FALSE; - - gdm_debug ("gdm_auth_secure_display: Setting up access"); - - VE_IGNORE_EINTR (closeret = fclose (af)); - if G_UNLIKELY (closeret < 0) { - display_add_error (d); - return FALSE; - } - if (af_gdm != NULL) { - VE_IGNORE_EINTR (closeret = fclose (af_gdm)); - if G_UNLIKELY (closeret < 0) { - display_add_error (d); - return FALSE; - } - } - g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE); - - if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) - gdm_debug ("gdm_auth_secure_display: Setting up access for %s - %d entries", - d->name, g_slist_length (d->auths)); - - return TRUE; -} - -#define SA(__s) ((struct sockaddr *) __s) -#define SIN(__s) ((struct sockaddr_in *) __s) -#define SIN6(__s) ((struct sockaddr_in6 *) __s) - -static gboolean -add_auth_entry_for_addr (GdmDisplay *d, - GSList **authlist, - struct sockaddr_storage *ss) -{ - const char *addr; - int len; - unsigned short family; - - switch (ss->ss_family) { -#if IPV6_ENABLED - case AF_INET6: - family = FamilyInternetV6; - addr = (const char *) &SIN6 (ss)->sin6_addr; - len = sizeof (struct in6_addr); - break; -#endif - case AF_INET: - default: - family = FamilyInternet; - addr = (const char *) &SIN (ss)->sin_addr; - len = sizeof (struct in_addr); - break; - } - - return add_auth_entry (d, authlist, NULL, NULL, family, addr, len); -} - -static GSList * -get_local_auths (GdmDisplay *d) -{ - gboolean is_local = FALSE; - guint i; - const GList *local_addys = NULL; - gboolean added_lo = FALSE; - GSList *auths = NULL; - - if G_UNLIKELY (!d) - return NULL; - - if (SERVER_IS_LOCAL (d)) { - char hostname[1024]; - - /* reget local host if local as it may have changed */ - hostname[1023] = '\0'; - if G_LIKELY (gethostname (hostname, 1023) == 0) { - g_free (d->hostname); - d->hostname = g_strdup (hostname); - } - if ( ! d->tcp_disallowed) - local_addys = gdm_address_peek_local_list (); - - is_local = TRUE; - } else { - is_local = FALSE; - - if (gdm_address_is_local (&(d->addr))) { - is_local = TRUE; - } - - for (i = 0; ! is_local && i < d->addr_count; i++) { - if (gdm_address_is_local (&d->addrs[i])) { - is_local = TRUE; - break; - } - } - } - - /* Local access also in case the host is very local */ - if (is_local) { - gdm_debug ("get_local_auths: Setting up socket access"); - - if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal, - d->hostname, strlen (d->hostname))) - goto get_local_auth_error; - - /* local machine but not local if you get my meaning, add - * the host gotten by gethostname as well if it's different - * since the above is probably localhost */ - if ( ! SERVER_IS_LOCAL (d)) { - char hostname[1024]; - - hostname[1023] = '\0'; - if (gethostname (hostname, 1023) == 0 && - strcmp (hostname, d->hostname) != 0) { - if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal, - hostname, - strlen (hostname))) - goto get_local_auth_error; - } - } else { - /* local machine, perhaps we haven't added - * localhost.localdomain to socket access */ - const char *localhost = "localhost.localdomain"; - if (strcmp (localhost, d->hostname) != 0) { - if ( ! add_auth_entry (d, &auths, NULL, NULL, FamilyLocal, - localhost, - strlen (localhost))) { - goto get_local_auth_error; - } - } - } - } - - gdm_debug ("get_local_auths: Setting up network access"); - - if ( ! SERVER_IS_LOCAL (d)) { - /* we should write out an entry for d->addr since - possibly it is not in d->addrs */ - - if (! add_auth_entry_for_addr (d, &auths, &d->addr)) { - goto get_local_auth_error; - } - - if (gdm_address_is_loopback (&(d->addr))) { - added_lo = TRUE; - } - } - - /* Network access: Write out an authentication entry for each of - * this host's official addresses */ - for (i = 0; i < d->addr_count; i++) { - struct sockaddr_storage *sa; - - sa = &d->addrs[i]; - if (gdm_address_equal (sa, &d->addr)) { - continue; - } - - if (! add_auth_entry_for_addr (d, &auths, sa)) { - goto get_local_auth_error; - } - - if (gdm_address_is_loopback (sa)) { - added_lo = TRUE; - } - } - - /* Network access: Write out an authentication entry for each of - * this host's local addresses if any */ - for (; local_addys != NULL; local_addys = local_addys->next) { - struct sockaddr_storage *ia = local_addys->data; - - if (ia == NULL) - break; - - if (! add_auth_entry_for_addr (d, &auths, ia)) { - goto get_local_auth_error; - } - - if (gdm_address_is_loopback (ia)) { - added_lo = TRUE; - } - } - - /* if local server add loopback */ - if (SERVER_IS_LOCAL (d) && ! added_lo && ! d->tcp_disallowed) { - struct sockaddr_storage *lo_ss = NULL; - /* FIXME: get loobback ss */ - if (! add_auth_entry_for_addr (d, &auths, lo_ss)) { - goto get_local_auth_error; - } - } - - if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) - gdm_debug ("get_local_auths: Setting up access for %s - %d entries", - d->name, g_slist_length (auths)); - - return auths; - - get_local_auth_error: - - gdm_auth_free_auth_list (auths); - - return NULL; -} - -static gboolean -try_open_append (const char *file) -{ - FILE *fp; - - VE_IGNORE_EINTR (fp = fopen (file, "a+")); - if G_LIKELY (fp != NULL) { - VE_IGNORE_EINTR (fclose (fp)); - return TRUE; - } else { - return FALSE; - } -} - -static gboolean -try_open_read_as_root (const char *file) -{ - int fd; - uid_t oldeuid = geteuid (); - uid_t oldegid = getegid (); - NEVER_FAILS_root_set_euid_egid (0, 0); - - VE_IGNORE_EINTR (fd = open (file, O_RDONLY)); - if G_UNLIKELY (fd < 0) { - NEVER_FAILS_root_set_euid_egid (oldeuid, oldegid); - return FALSE; - } else { - VE_IGNORE_EINTR (close (fd)); - NEVER_FAILS_root_set_euid_egid (oldeuid, oldegid); - return TRUE; - } -} - -/** - * gdm_auth_user_add: - * @d: Pointer to a GdmDisplay struct - * @user: Userid of the user whose cookie file to add entries to - * @homedir: The user's home directory - * - * Remove all cookies referring to this display from user's cookie - * file and append the ones specified in the display's authlist. - * - * Returns TRUE on success and FALSE on error. - */ - -gboolean -gdm_auth_user_add (GdmDisplay *d, uid_t user, const char *homedir) -{ - char *authdir; - gint authfd; - FILE *af; - GSList *auths = NULL; - const gchar *userauthdir; - const gchar *userauthfile; - gboolean ret = TRUE; - gboolean automatic_tmp_dir = FALSE; - gboolean authdir_is_tmp_dir = FALSE; - gboolean locked; - gboolean user_auth_exists; - int closeret; - - if (!d) - return FALSE; - - if (d->local_auths != NULL) { - gdm_auth_free_auth_list (d->local_auths); - d->local_auths = NULL; - } - - d->local_auths = get_local_auths (d); - - if (d->local_auths == NULL) { - gdm_error ("Can't make cookies"); - return FALSE; - } - - gdm_debug ("gdm_auth_user_add: Adding cookie for %d", user); - - userauthdir = gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR); - userauthfile = gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHFILE); - - /* Determine whether UserAuthDir is specified. Otherwise ~user is used */ - if ( ! ve_string_empty (userauthdir) && - strcmp (userauthdir, "~") != 0) { - if (strncmp (userauthdir, "~/", 2) == 0) { - authdir = g_build_filename (homedir, &userauthdir[2], NULL); - } else { - authdir = g_strdup (userauthdir); - automatic_tmp_dir = TRUE; - authdir_is_tmp_dir = TRUE; - } - } else { - authdir = g_strdup (homedir); - } - - try_user_add_again: - - locked = FALSE; - - umask (077); - - if (authdir == NULL) - d->userauth = NULL; - else - d->userauth = g_build_filename (authdir, userauthfile, NULL); - - user_auth_exists = (d->userauth != NULL && - g_access (d->userauth, F_OK) == 0); - - /* Find out if the Xauthority file passes the paranoia check */ - /* Note that this is not very efficient, we stat the files over - and over, but we don't care, we don't do this too often */ - if (automatic_tmp_dir || - authdir == NULL || - - /* first the standard paranoia check (this checks the home dir - * too which is useful here) */ - ! gdm_file_check ("gdm_auth_user_add", user, authdir, userauthfile, - TRUE, FALSE, gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE), - gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM)) || - - /* now the auth file checking routine */ - ! gdm_auth_file_check ("gdm_auth_user_add", user, d->userauth, TRUE /* absentok */, NULL) || - - /* now see if we can actually append this file */ - ! try_open_append (d->userauth) || - - /* try opening as root, if we can't open as root, - then this is a NFS mounted directory with root squashing, - and we don't want to write cookies over NFS */ - (gdm_daemon_config_get_value_bool (GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS) && - ! try_open_read_as_root (d->userauth))) { - - /* if the userauth file didn't exist and we were looking at it, - it likely exists now but empty, so just whack it - (it may not exist if the file didn't exist and the directory - was of wrong permissions, but more likely this is - file on NFS dir with root-squashing enabled) */ - if ( ! user_auth_exists && d->userauth != NULL) - g_unlink (d->userauth); - - /* No go. Let's create a fallback file in GDM_KEY_USER_AUTHDIR_FALLBACK (/tmp) - * or perhaps userauthfile directory (usually would be /tmp) */ - d->authfb = TRUE; - g_free (d->userauth); - if (authdir_is_tmp_dir && authdir != NULL) - d->userauth = g_build_filename (authdir, ".gdmXXXXXX", NULL); - else - d->userauth = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL); - authfd = g_mkstemp (d->userauth); - - if G_UNLIKELY (authfd < 0 && authdir_is_tmp_dir) { - g_free (d->userauth); - d->userauth = NULL; - - umask (022); - - authdir_is_tmp_dir = FALSE; - goto try_user_add_again; - } - - if G_UNLIKELY (authfd < 0) { - gdm_error (_("%s: Could not open cookie file %s"), - "gdm_auth_user_add", - d->userauth); - g_free (d->userauth); - d->userauth = NULL; - - umask (022); - - g_free (authdir); - return FALSE; - } - - d->last_auth_touch = time (NULL); - - VE_IGNORE_EINTR (af = fdopen (authfd, "w")); - } else { /* User's Xauthority file is ok */ - d->authfb = FALSE; - - /* FIXME: Better implement my own locking. The libXau one is not kosher */ - if G_UNLIKELY (XauLockAuth (d->userauth, 3, 3, 0) != LOCK_SUCCESS) { - gdm_error (_("%s: Could not lock cookie file %s"), - "gdm_auth_user_add", - d->userauth); - g_free (d->userauth); - d->userauth = NULL; - - umask (022); - - automatic_tmp_dir = TRUE; - goto try_user_add_again; - } - - locked = TRUE; - - af = gdm_safe_fopen_ap (d->userauth); - } - - /* Set to NULL, because can goto try_user_add_again. */ - g_free (authdir); - authdir = NULL; - - if G_UNLIKELY (af == NULL) { - /* Really no need to clean up here - this process is a goner anyway */ - gdm_error (_("%s: Could not open cookie file %s"), - "gdm_auth_user_add", - d->userauth); - if (locked) - XauUnlockAuth (d->userauth); - g_free (d->userauth); - d->userauth = NULL; - - umask (022); - - if ( ! d->authfb) { - automatic_tmp_dir = TRUE; - goto try_user_add_again; - } - - return FALSE; - } - - gdm_debug ("gdm_auth_user_add: Using %s for cookies", d->userauth); - - /* If not a fallback file, nuke any existing cookies for this display */ - if (! d->authfb) - af = gdm_auth_purge (d, af, FALSE /* remove when empty */); - - /* Append the authlist for this display to the cookie file */ - auths = d->local_auths; - - while (auths) { - if G_UNLIKELY ( ! XauWriteAuth (af, auths->data)) { - gdm_error (_("%s: Could not write cookie"), - "gdm_auth_user_add"); - - if ( ! d->authfb) { - VE_IGNORE_EINTR (fclose (af)); - if (locked) - XauUnlockAuth (d->userauth); - g_free (d->userauth); - d->userauth = NULL; - automatic_tmp_dir = TRUE; - goto try_user_add_again; - } - - ret = FALSE; - break; - } - - auths = auths->next; - } - - VE_IGNORE_EINTR (closeret = fclose (af)); - if G_UNLIKELY (closeret < 0) { - gdm_error (_("%s: Could not write cookie"), - "gdm_auth_user_add"); - - if ( ! d->authfb) { - if (locked) - XauUnlockAuth (d->userauth); - g_free (d->userauth); - d->userauth = NULL; - automatic_tmp_dir = TRUE; - goto try_user_add_again; - } - - ret = FALSE; - } - - if (locked) - XauUnlockAuth (d->userauth); - - gdm_debug ("gdm_auth_user_add: Done"); - - umask (022); - return ret; -} - - -/** - * gdm_auth_user_remove: - * @d: Pointer to a GdmDisplay struct - * @user: Userid of the user whose cookie file to remove entries from - * - * Remove all cookies referring to this display from user's cookie - * file. - */ - -void -gdm_auth_user_remove (GdmDisplay *d, uid_t user) -{ - FILE *af; - gchar *authfile; - gchar *authdir; - mode_t oldmode; - - if G_UNLIKELY (!d || !d->userauth) - return; - - gdm_debug ("gdm_auth_user_remove: Removing cookie from %s (%d)", d->userauth, d->authfb); - - /* If we are using the fallback cookie location, simply nuke the - * cookie file */ - if (d->authfb) { - VE_IGNORE_EINTR (g_unlink (d->userauth)); - g_free (d->userauth); - d->userauth = NULL; - return; - } - - /* if the file doesn't exist, oh well, just ignore this then */ - if G_UNLIKELY (g_access (d->userauth, F_OK) != 0) { - g_free (d->userauth); - d->userauth = NULL; - return; - } - - authfile = g_path_get_basename (d->userauth); - authdir = g_path_get_dirname (d->userauth); - - if (ve_string_empty (authfile) || - ve_string_empty (authdir)) { - g_free (authdir); - g_free (authfile); - return; - } - - /* Now, the cookie file could be owned by a malicious user who - * decided to concatenate something like his entire MP3 collection - * to it. So we better play it safe... */ - - if G_UNLIKELY ( ! gdm_file_check ("gdm_auth_user_remove", user, authdir, authfile, - TRUE, FALSE, gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE), - gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM)) || - /* be even paranoider with permissions */ - ! gdm_auth_file_check ("gdm_auth_user_remove", user, d->userauth, FALSE /* absentok */, NULL)) { - g_free (authdir); - g_free (authfile); - gdm_error (_("%s: Ignoring suspiciously looking cookie file %s"), - "gdm_auth_user_remove", - d->userauth); - - return; - } - - g_free (authdir); - g_free (authfile); - - /* Lock user's cookie jar and open it for writing */ - if G_UNLIKELY (XauLockAuth (d->userauth, 3, 3, 0) != LOCK_SUCCESS) { - g_free (d->userauth); - d->userauth = NULL; - return; - } - - oldmode = umask (077); - af = gdm_safe_fopen_ap (d->userauth); - umask (oldmode); - - if G_UNLIKELY (af == NULL) { - XauUnlockAuth (d->userauth); - - gdm_error (_("%s: Cannot safely open %s"), - "gdm_auth_user_remove", - d->userauth); - - g_free (d->userauth); - d->userauth = NULL; - - return; - } - - /* Purge entries for this display from the cookie jar */ - af = gdm_auth_purge (d, af, TRUE /* remove when empty */); - - /* Close the file and unlock it */ - if (af != NULL) { - /* FIXME: what about out of diskspace errors on errors close */ - errno = 0; - VE_IGNORE_EINTR (fclose (af)); - if G_UNLIKELY (errno != 0) { - gdm_error (_("Can't write to %s: %s"), d->userauth, - strerror (errno)); - } - } - - XauUnlockAuth (d->userauth); - - g_free (d->userauth); - d->userauth = NULL; -} - -static gboolean -memory_same (const char *sa, int lena, const char *sb, int lenb) -{ - if (lena == lenb) { - if (lena == 0) - return TRUE; - /* sanity */ - if G_UNLIKELY (sa == NULL || sb == NULL) - return FALSE; - return memcmp (sa, sb, lena) == 0; - } else { - return FALSE; - } -} - -static gboolean -auth_same_except_data (Xauth *xa, Xauth *xb) -{ - if (xa->family == xb->family && - memory_same (xa->number, xa->number_length, - xb->number, xb->number_length) && - memory_same (xa->name, xa->name_length, - xb->name, xb->name_length) && - memory_same (xa->address, xa->address_length, - xb->address, xb->address_length)) - return TRUE; - else - return FALSE; -} - - -/** - * gdm_auth_purge: - * @d: Pointer to a GdmDisplay struct - * @af: File handle to a cookie file - * @remove_when_empty: remove the file when empty - * - * Remove all cookies referring to this display a cookie file. - */ - -static FILE * -gdm_auth_purge (GdmDisplay *d, FILE *af, gboolean remove_when_empty) -{ - Xauth *xa; - GSList *keep = NULL, *li; - mode_t oldmode; - int cnt; - - if G_UNLIKELY (!d || !af) - return af; - - gdm_debug ("gdm_auth_purge: %s", d->name); - - fseek (af, 0L, SEEK_SET); - - /* Read the user's entire Xauth file into memory to avoid - * temporary file issues. Then remove any instance of this display - * in the cookie jar... */ - - cnt = 0; - - while ( (xa = XauReadAuth (af)) != NULL ) { - GSList *li; - /* We look at the current auths, but those may - have different cookies then what is in the file, - so don't compare those, but we wish to purge all - the entries that we'd normally write */ - for (li = d->local_auths; li != NULL; li = li->next) { - Xauth *xb = li->data; - if (auth_same_except_data (xa, xb)) { - XauDisposeAuth (xa); - xa = NULL; - break; - } - } - if (xa != NULL) - keep = g_slist_append (keep, xa); - - /* just being ultra anal */ - cnt++; - if (cnt > 500) - break; - } - - VE_IGNORE_EINTR (fclose (af)); - - if (remove_when_empty && - keep == NULL) { - VE_IGNORE_EINTR (g_unlink (d->userauth)); - return NULL; - } - - oldmode = umask (077); - af = gdm_safe_fopen_w (d->userauth); - umask (oldmode); - - /* Write out remaining entries */ - for (li = keep; li != NULL; li = li->next) { - /* FIXME: is this correct, if we can't open - * this is quite bad isn't it ... */ - if G_LIKELY (af != NULL) - XauWriteAuth (af, li->data); - /* FIXME: what about errors? */ - XauDisposeAuth (li->data); - li->data = NULL; - } - - g_slist_free (keep); - - return af; -} - -void -gdm_auth_set_local_auth (GdmDisplay *d) -{ - XSetAuthorization ((char *)"MIT-MAGIC-COOKIE-1", - (int) strlen ("MIT-MAGIC-COOKIE-1"), - (char *)d->bcookie, - (int) 16); -} - -void -gdm_auth_free_auth_list (GSList *list) -{ - GSList *li; - - for (li = list; li != NULL; li = li->next) { - XauDisposeAuth ((Xauth *) li->data); - li->data = NULL; - } - - g_slist_free (list); -} diff --git a/daemon/auth.h b/daemon/auth.h deleted file mode 100644 index f01ebcbf..00000000 --- a/daemon/auth.h +++ /dev/null @@ -1,35 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_AUTH_H -#define GDM_AUTH_H - -#include "gdm.h" - -gboolean gdm_auth_secure_display (GdmDisplay *d); -gboolean gdm_auth_user_add (GdmDisplay *d, uid_t user, const char *homedir); -void gdm_auth_user_remove (GdmDisplay *d, uid_t user); - -/* Call XSetAuthorization */ -void gdm_auth_set_local_auth (GdmDisplay *d); - -void gdm_auth_free_auth_list (GSList *list); - -#endif /* GDM_AUTH_H */ - -/* EOF */ diff --git a/daemon/choose.c b/daemon/choose.c deleted file mode 100644 index bd08b10c..00000000 --- a/daemon/choose.c +++ /dev/null @@ -1,363 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* This file contains the XDMCP chooser glue */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <errno.h> -#include <X11/Xlib.h> -#include <X11/Xmd.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <fcntl.h> -#include <string.h> - -#include "gdm.h" -#include "misc.h" -#include "choose.h" -#include "xdmcp.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -#include "gdm-socket-protocol.h" - -static gint ipending = 0; -static GSList *indirect = NULL; - -static guint indirect_id = 1; - -static gboolean -remove_oldest_pending (void) -{ - GSList *li; - GdmIndirectDisplay *oldest = NULL; - - for (li = indirect; li != NULL; li = li->next) { - GdmIndirectDisplay *idisp = li->data; - if (idisp->acctime == 0) - continue; - - if (oldest == NULL || - idisp->acctime < oldest->acctime) { - oldest = idisp; - } - } - - if (oldest != NULL) { - gdm_choose_indirect_dispose (oldest); - return TRUE; - } else { - return FALSE; - } -} - -#ifndef XDM_UDP_PORT -#define XDM_UDP_PORT 177 -#endif - -static gboolean -get_first_address_for_node (const char *node, - struct sockaddr_storage **sa) -{ - struct addrinfo hints; - struct addrinfo *ai_list; - struct addrinfo *ai; - int gaierr; - gboolean found; - char strport[NI_MAXSERV]; - - found = FALSE; - - memset (&hints, 0, sizeof (hints)); - hints.ai_family = AF_UNSPEC; - - snprintf (strport, sizeof (strport), "%u", XDM_UDP_PORT); - - if ((gaierr = getaddrinfo (node, strport, &hints, &ai_list)) != 0) { - g_warning ("Unable get address: %s", gai_strerror (gaierr)); - return FALSE; - } - - for (ai = ai_list; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { - continue; - } -#ifndef ENABLE_IPV6 - if (ai->ai_family == AF_INET6) { - continue; - } -#endif - found = TRUE; - break; - } - - if (ai != NULL) { - if (sa != NULL) { - *sa = g_memdup (ai->ai_addr, ai->ai_addrlen); - } - } - - freeaddrinfo (ai_list); - - return found; -} - -gboolean -gdm_choose_data (const char *data) -{ - int id; - struct sockaddr_storage *sa; - GSList *li; - char *msg; - char *p; - char *host; - gboolean ret; - - msg = g_strdup (data); - sa = NULL; - ret = FALSE; - - p = strtok (msg, " "); - if (p == NULL || strcmp (GDM_SOP_CHOSEN, p) != 0) { - goto out; - } - - p = strtok (NULL, " "); - if (p == NULL || sscanf (p, "%d", &id) != 1) { - goto out; - } - - p = strtok (NULL, " "); - - if (p == NULL) { - goto out; - } - - if (! get_first_address_for_node (p, &sa)) { - goto out; - } - - gdm_address_get_info (sa, &host, NULL); - gdm_debug ("gdm_choose_data: got indirect id: %d address: %s", - id, - host); - g_free (host); - - for (li = indirect; li != NULL; li = li->next) { - GdmIndirectDisplay *idisp = li->data; - if (idisp->id == id) { - /* whack the oldest if more then allowed */ - while (ipending >= gdm_daemon_config_get_value_int (GDM_KEY_MAX_INDIRECT) && - remove_oldest_pending ()) - ; - - idisp->acctime = time (NULL); - - g_free (idisp->chosen_host); - idisp->chosen_host = g_memdup (sa, sizeof (struct sockaddr_storage)); - - /* Now this display is pending */ - ipending++; - - ret = TRUE; - break; - } - } - out: - g_free (sa); - g_free (msg); - - return ret; -} - - -GdmIndirectDisplay * -gdm_choose_indirect_alloc (struct sockaddr_storage *clnt_sa) -{ - GdmIndirectDisplay *id; - char *host; - - if (clnt_sa == NULL) - return NULL; - - id = g_new0 (GdmIndirectDisplay, 1); - id->id = indirect_id++; - /* deal with a rollover, that will NEVER EVER happen, - * but I'm a paranoid bastard */ - if (id->id == 0) - id->id = indirect_id++; - - id->dsp_sa = g_memdup (clnt_sa, sizeof (struct sockaddr_storage)); - id->chosen_host = NULL; - - id->acctime = 0; - - indirect = g_slist_prepend (indirect, id); - - gdm_address_get_info (id->dsp_sa, &host, NULL); - - gdm_debug ("gdm_choose_display_alloc: display=%s, pending=%d ", - host, - ipending); - g_free (host); - - return (id); -} - -/* dispose of indirect display of id, if no host is set */ -void -gdm_choose_indirect_dispose_empty_id (guint id) -{ - GSList *li; - - if (id == 0) - return; - - for (li = indirect; li != NULL; li = li->next) { - GdmIndirectDisplay *idisp = li->data; - - if (idisp == NULL) - continue; - - if (idisp->id == id) { - if (idisp->chosen_host == NULL) - gdm_choose_indirect_dispose (idisp); - return; - } - } -} - -GdmIndirectDisplay * -gdm_choose_indirect_lookup_by_chosen (struct sockaddr_storage *chosen, - struct sockaddr_storage *origin) -{ - GSList *li; - char *host; - - for (li = indirect; li != NULL; li = li->next) { - GdmIndirectDisplay *id = li->data; - - if (id != NULL && - id->chosen_host != NULL && - gdm_address_equal (id->chosen_host, chosen)) { - if (gdm_address_equal (id->dsp_sa, origin)) { - return id; - } else if (gdm_address_is_loopback (id->dsp_sa) && - gdm_address_is_local (origin)) { - return id; - } - } - } - - gdm_address_get_info (chosen, &host, NULL); - - gdm_debug ("gdm_choose_indirect_lookup_by_chosen: Chosen %s host not found", - host); - gdm_debug ("gdm_choose_indirect_lookup_by_chosen: Origin was: %s", - host); - g_free (host); - - return NULL; -} - - -GdmIndirectDisplay * -gdm_choose_indirect_lookup (struct sockaddr_storage *clnt_sa) -{ - GSList *li, *ilist; - GdmIndirectDisplay *id; - time_t curtime = time (NULL); - char *host; - - ilist = g_slist_copy (indirect); - - for (li = ilist; li != NULL; li = li->next) { - id = (GdmIndirectDisplay *) li->data; - if (id == NULL) - continue; - - if (id->acctime > 0 && - curtime > id->acctime + gdm_daemon_config_get_value_int (GDM_KEY_MAX_WAIT_INDIRECT)) { - - gdm_address_get_info (clnt_sa, &host, NULL); - gdm_debug ("gdm_choose_indirect_check: Disposing stale INDIRECT query from %s", - host); - g_free (host); - - gdm_choose_indirect_dispose (id); - continue; - } - - if (gdm_address_equal (id->dsp_sa, clnt_sa)) { - g_slist_free (ilist); - return id; - } - } - g_slist_free (ilist); - - gdm_address_get_info (clnt_sa, &host, NULL); - gdm_debug ("gdm_choose_indirect_lookup: Host %s not found", - host); - g_free (host); - - return NULL; -} - - -void -gdm_choose_indirect_dispose (GdmIndirectDisplay *id) -{ - char *host; - - if (id == NULL) - return; - - indirect = g_slist_remove (indirect, id); - - if (id->acctime > 0) - ipending--; - id->acctime = 0; - - gdm_address_get_info (id->dsp_sa, &host, NULL); - gdm_debug ("gdm_choose_indirect_dispose: Disposing %s", - host); - g_free (host); - - g_free (id->chosen_host); - id->chosen_host = NULL; - - g_free (id->dsp_sa); - id->dsp_sa = NULL; - - g_free (id); -} diff --git a/daemon/choose.h b/daemon/choose.h deleted file mode 100644 index 3fface4d..00000000 --- a/daemon/choose.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef CHOOSE_H -#define CHOOSE_H - -#include "gdm.h" - -typedef struct _GdmIndirectDisplay GdmIndirectDisplay; -struct _GdmIndirectDisplay { - int id; - struct sockaddr_storage* dsp_sa; - struct sockaddr_storage* chosen_host; - time_t acctime; -}; - -GdmIndirectDisplay * gdm_choose_indirect_alloc (struct sockaddr_storage *clnt_sa); -GdmIndirectDisplay * gdm_choose_indirect_lookup (struct sockaddr_storage *clnt_sa); -GdmIndirectDisplay * gdm_choose_indirect_lookup_by_chosen (struct sockaddr_storage *chosen, - struct sockaddr_storage *origin); -void gdm_choose_indirect_dispose (GdmIndirectDisplay *id); - -/* dispose of indirect display of id, if no host is set */ -void gdm_choose_indirect_dispose_empty_id (guint id); - -gboolean gdm_choose_data (const char *data); - -#endif /* CHOOSE_H */ - -/* EOF */ - diff --git a/daemon/cookie.c b/daemon/cookie.c deleted file mode 100644 index 55f9621b..00000000 --- a/daemon/cookie.c +++ /dev/null @@ -1,272 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 2003 Red Hat, Inc. - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * Copyright (C) Rik Faith <faith@precisioninsight.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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Functions for generating MIT-MAGIC-COOKIEs. - * - * This code was derived (i.e. stolen) from mcookie.c written by Rik Faith - * - * Note that this code goes to much greater lengths to be as random as possible. - * Thus being more secure on systems without /dev/random and friends. - */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <sys/time.h> -#include <unistd.h> -#include <errno.h> - -#include "gdm.h" -#include "md5.h" -#include "cookie.h" - -#include "gdm-common.h" -#include "gdm-daemon-config.h" - -#define MAXBUFFERSIZE 1024 - -static struct rngs { - const char *path; /* null is the authfile name */ - int length; - off_t seek; -} rngs[] = { - { "/dev/random", 16, 0 }, -#ifdef __OpenBSD__ - { "/dev/srandom", 16, 0 }, -#endif - { "/dev/urandom", 128, 0 }, - { "/proc/stat", MAXBUFFERSIZE, 0 }, - { "/proc/interrupts", MAXBUFFERSIZE, 0 }, - { "/proc/loadavg", MAXBUFFERSIZE, 0 }, - { "/proc/meminfo", MAXBUFFERSIZE, 0 }, -#if defined (__i386__) || defined (__386__) || defined (_M_IX86) - /* On i386, we should not read the first 16megs */ - { "/dev/mem", MAXBUFFERSIZE, 0x100000 }, -#else - { "/dev/mem", MAXBUFFERSIZE, 0 }, -#endif - /* this will load the old authfile for the display */ - { NULL /* null means the authfile */, MAXBUFFERSIZE, 0 }, - { "/proc/net/dev", MAXBUFFERSIZE, 0 }, - { "/dev/audio", MAXBUFFERSIZE, 0 }, - { "/etc/shadow", MAXBUFFERSIZE, 0 }, - { "/var/log/messages", MAXBUFFERSIZE, 0 }, -}; - -/* Some semi random spinners to spin, - * this is 20 bytes of semi random data */ -#define RANDNUMS 5 -static guint32 randnums[RANDNUMS]; - -/* stolen from XDM which in turn stole this - from the C standard */ -static guint32 -next_rand_15 (guint32 num) -{ - num = num * 1103515245 + 12345; - return (unsigned int)(num/65536) % 32768; -} - -/* really quite apparently only 31 bits of entropy result (from tests), - but oh well */ -static guint32 -next_rand_32 (guint32 num) -{ - int i; - guint32 ret; - guint8 *p = (guint8 *)&ret; - - for (i = 0; i < 4; i++) { - num = next_rand_15 (num); - p[i] = (num & 0xff00) >> 8; - } - return ret; -} - -/* This adds a little bit of entropy to our buffer, - just in case /dev/random doesn't work out for us - really since that normally adds enough bytes of nice - randomness already */ -void -gdm_random_tick (void) -{ - struct timeval tv; - struct timezone tz; - - gettimeofday (&tv, &tz); - - /* the higher order bits of the seconds - are quite uninteresting */ - randnums[0] ^= next_rand_32 ((tv.tv_sec << 20) ^ tv.tv_usec); - - /* different method of combining */ - randnums[1] ^= next_rand_32 (tv.tv_sec) ^ next_rand_32 (tv.tv_usec); - - /* probably unneeded, but just being anal */ - randnums[2] ^= (tv.tv_sec << 20) ^ tv.tv_usec; - - /* probably unneeded, to guess above - the number of invocation is likely needed - anyway */ - randnums[3]++; - - /* also hope that other places call - g_random_int. Note that on systems - without /dev/urandom, this will yet again - measure time the first time it's called and - we'll add entropy based on the speed of the - computer. Yay */ - randnums[4] ^= g_random_int (); -} - -/* check a few values and if we get the same - value, it's not really random. Likely - we got perhaps a string of zeros or some - such. */ -static gboolean -data_seems_random (const char buf[], int size) -{ - int i, lastval = 0; - if (size < 16) - return FALSE; - for (i = 0; i < 10; i++) { - int idx = g_random_int_range (0, size); - if G_LIKELY (i > 0 && - lastval != buf[idx]) - return TRUE; - lastval = buf[idx]; - } - return FALSE; -} - -static unsigned char old_cookie[16]; - -void -gdm_cookie_generate (char **cookiep, - char **bcookiep) -{ - int i; - struct GdmMD5Context ctx; - unsigned char digest[16]; - unsigned char buf[MAXBUFFERSIZE]; - int fd; - pid_t pid; - int r; - char cookie[40]; /* 2*16 == 32, so 40 is enough */ - - cookie[0] = '\0'; - - gdm_md5_init (&ctx); - - /* spin the spinners according to current time */ - gdm_random_tick (); - - gdm_md5_update (&ctx, (unsigned char *) randnums, sizeof (int) * RANDNUMS); - - /* use the last cookie */ - gdm_md5_update (&ctx, old_cookie, 16); - - /* use some uninitialized stack space */ - gdm_md5_update (&ctx, (unsigned char *) cookie, sizeof (cookie)); - - pid = getppid (); - gdm_md5_update (&ctx, (unsigned char *) &pid, sizeof (pid)); - pid = getpid (); - gdm_md5_update (&ctx, (unsigned char *) &pid, sizeof (pid)); - - for (i = 0; i < G_N_ELEMENTS (rngs); i++) { - const char *file = rngs[i].path; - - if G_UNLIKELY (file == NULL) - continue; - do { - int flags; - - flags = O_RDONLY | O_NONBLOCK; -#ifdef O_NOCTTY - flags |= O_NOCTTY; -#endif -#ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; -#endif - - errno = 0; - fd = open (file, flags); - - } while G_UNLIKELY (errno == EINTR); - - if G_LIKELY (fd >= 0) { - /* Apparently this can sometimes block anyway even if it is O_NONBLOCK, - so use select to figure out if there is something available */ - fd_set rfds; - struct timeval tv; - - FD_ZERO (&rfds); - FD_SET (fd, &rfds); - - tv.tv_sec = 0; - tv.tv_usec = 10*1000 /* 10 ms */; - r = 0; - - if G_UNLIKELY (rngs[i].seek > 0) - lseek (fd, rngs[i].seek, SEEK_SET); - - if G_LIKELY (select (fd+1, &rfds, NULL, NULL, &tv) > 0) { - VE_IGNORE_EINTR (r = read (fd, buf, MIN (sizeof (buf), rngs[i].length))); - } - - if G_LIKELY (r > 0) - gdm_md5_update (&ctx, buf, r); - else - r = 0; - - VE_IGNORE_EINTR (close (fd)); - - if G_LIKELY (r >= rngs[i].length && - data_seems_random ((char *) buf, r)) - break; - } - } - - gdm_md5_final (digest, &ctx); - - for (i = 0; i < 16; i++) { - char sub[3]; - g_snprintf (sub, sizeof (sub), "%02x", (guint)digest[i]); - strcat (cookie, sub); - } - - if (cookiep != NULL) { - *cookiep = g_strdup (cookie); - } - - if (bcookiep != NULL) { - *bcookiep = g_new (char, 16); - memcpy (*bcookiep, digest, 16); - } - - memcpy (old_cookie, digest, 16); -} diff --git a/daemon/cookie.h b/daemon/cookie.h deleted file mode 100644 index 9342f037..00000000 --- a/daemon/cookie.h +++ /dev/null @@ -1,31 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_COOKIE_H -#define GDM_COOKIE_H - -void gdm_cookie_generate (char **cookie, - char **bcookie); - -/* Add some more time based randomness, should be done - * at less predictable events */ -void gdm_random_tick (void); - -#endif /* GDM_COOKIE_H */ - -/* EOF */ diff --git a/daemon/display.c b/daemon/display.c deleted file mode 100644 index 1f18f1b2..00000000 --- a/daemon/display.c +++ /dev/null @@ -1,589 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <glib/gi18n.h> -#include <signal.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> - -#include "gdm.h" -#include "gdm-net.h" -#include "server.h" -#include "display.h" -#include "slave.h" -#include "misc.h" -#include "choose.h" -#include "auth.h" -#include "gdm-net.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -/* External vars */ -extern GdmConnection *fifoconn; -extern GdmConnection *pipeconn; -extern GdmConnection *unixconn; -extern int slave_fifo_pipe_fd; /* the slavepipe (like fifo) connection, this is the write end */ -extern gint flexi_servers; - -static gboolean -gdm_display_check_loop (GdmDisplay *disp) -{ - time_t now; - time_t since_last; - time_t since_loop; - - now = time (NULL); - - gdm_debug ("loop check: last_start %ld, last_loop %ld, now: %ld, retry_count: %d", (long)disp->last_start_time, (long) disp->last_loop_start_time, (long) now, disp->retry_count); - - if (disp->last_loop_start_time > now || disp->last_loop_start_time == 0) - { - /* Reset everything if this is the first time in this - * function, or if the system clock got reset backward. - */ - disp->last_loop_start_time = now; - disp->last_start_time = now; - disp->retry_count = 1; - - gdm_debug ("Resetting counts for loop of death detection"); - - return TRUE; - } - - since_loop = now - disp->last_loop_start_time; - since_last = now - disp->last_start_time; - - /* If it's been at least 1.5 minutes since the last startup loop - * attempt, then we reset everything. Or if the last startup was more then - * 30 seconds ago, then it was likely a successful session. - */ - - if (since_loop >= 90 || since_last >= 30) - { - disp->last_loop_start_time = now; - disp->last_start_time = now; - disp->retry_count = 1; - - gdm_debug ("Resetting counts for loop of death detection, 90 seconds elapsed since loop started or session lasted more then 30 seconds."); - - return TRUE; - } - - /* If we've tried too many times we bail out. i.e. this means we - * tried too many times in the 90-second period. - */ - if (disp->retry_count >= 6) { - /* This means we have no clue what's happening, - * it's not X server crashing as we would have - * cought that elsewhere. Things are just - * not working out, so tell the user. - * However this may have been caused by a malicious local user - * zapping the display repeatedly, that shouldn't cause gdm - * to stop working completely so just wait for 2 minutes, - * that should give people ample time to stop gdm if needed, - * or just wait for the stupid malicious user to get bored - * and go away */ - char *s = g_strdup_printf (C_(N_("The display server has been shut down " - "about 6 times in the last 90 seconds. " - "It is likely that something bad is " - "going on. Waiting for 2 minutes " - "before trying again on display %s.")), - disp->name); - /* only display a dialog box if this is a local display */ - if (disp->type == TYPE_STATIC || - disp->type == TYPE_FLEXI) { - gdm_text_message_dialog (s); - } - gdm_error ("%s", s); - g_free (s); - - /* Wait 2 minutes */ - disp->sleep_before_run = 120; - /* well, "last" start time will really be in the future */ - disp->last_start_time = now + disp->sleep_before_run; - - disp->retry_count = 1; - /* this will reset stuff in the next run (after this - "after-two-minutes" server starts) */ - disp->last_loop_start_time = 0; - - return TRUE; - } - - /* At least 8 seconds between start attempts, but only after - * the second start attempt, so you can try to kill gdm from the console - * in these gaps. - */ - if (disp->retry_count > 2 && since_last < 8) - { - gdm_debug ("Will sleep %ld seconds before next X server restart attempt", - (long)(8 - since_last)); - now = time (NULL) + 8 - since_last; - disp->sleep_before_run = 8 - since_last; - /* well, "last" start time will really be in the future */ - disp->last_start_time = now + disp->sleep_before_run; - } - else - { - /* wait one second just for safety (avoids X server races) */ - disp->sleep_before_run = 1; - disp->last_start_time = now; - } - - disp->retry_count++; - - return TRUE; -} - -static void -whack_old_slave (GdmDisplay *d, gboolean kill_connection) -{ - time_t t = time (NULL); - gboolean waitsleep = TRUE; - - if (kill_connection) { - /* This should never happen, but just in case */ - if (d->socket_conn != NULL) { - GdmConnection *conn = d->socket_conn; - d->socket_conn = NULL; - gdm_connection_set_close_notify (conn, NULL, NULL); - } - } - - if (d->master_notify_fd >= 0) { - VE_IGNORE_EINTR (close (d->master_notify_fd)); - d->master_notify_fd = -1; - } - - /* if we have DISPLAY_DEAD set, then this has already been killed */ - if (d->dispstat == DISPLAY_DEAD) - waitsleep = FALSE; - - /* Kill slave */ - if (d->slavepid > 1 && - (d->dispstat == DISPLAY_DEAD || kill (d->slavepid, SIGTERM) == 0)) { - int exitstatus; - int ret; -wait_again: - - if (waitsleep) - /* wait for some signal, yes this is a race */ - sleep (10); - waitsleep = TRUE; - errno = 0; - ret = waitpid (d->slavepid, &exitstatus, WNOHANG); - if (ret <= 0) { - /* rekill the slave to tell it to - hurry up and die if we're getting - killed ourselves */ - if ((gdm_daemon_config_signal_terminthup_was_notified ()) || - (t + 10 <= time (NULL))) { - gdm_debug ("whack_old_slave: GOT ANOTHER SIGTERM (or it was 10 secs already), killing slave again with SIGKILL"); - t = time (NULL); - kill (d->slavepid, SIGKILL); - goto wait_again; - } else if (ret < 0 && errno == EINTR) { - goto wait_again; - } - } - - if (WIFSIGNALED (exitstatus)) { - gdm_debug ("whack_old_slave: Slave crashed (signal %d), killing its children", - (int)WTERMSIG (exitstatus)); - - if (d->sesspid > 1) - kill (-(d->sesspid), SIGTERM); - d->sesspid = 0; - if (d->greetpid > 1) - kill (-(d->greetpid), SIGTERM); - d->greetpid = 0; - if (d->chooserpid > 1) - kill (-(d->chooserpid), SIGTERM); - d->chooserpid = 0; - if (d->servpid > 1) - kill (d->servpid, SIGTERM); - d->servpid = 0; - } - } - d->slavepid = 0; -} - -/** - * gdm_display_manage: - * @d: Pointer to a GdmDisplay struct - * - * Manage (Initialize and start login session) display - */ - -gboolean -gdm_display_manage (GdmDisplay *d) -{ - pid_t pid; - int fds[2]; - - if (!d) - return FALSE; - - gdm_debug ("gdm_display_manage: Managing %s", d->name); - - if (pipe (fds) < 0) { - gdm_error (_("%s: Cannot create pipe"), "gdm_display_manage"); - } - - if ( ! gdm_display_check_loop (d)) - return FALSE; - - if (d->slavepid != 0) - gdm_debug ("gdm_display_manage: Old slave pid is %d", (int)d->slavepid); - - /* If we have an old slave process hanging around, kill it */ - /* This shouldn't be a normal code path however, so it doesn't matter - * that we are hanging */ - whack_old_slave (d, FALSE /* kill_connection */); - - /* Ensure that /tmp/.ICE-unix and /tmp/.X11-unix exist and have the - * correct permissions */ - gdm_ensure_sanity (); - - d->managetime = time (NULL); - - g_debug ("Forking slave process"); - - /* Fork slave process */ - pid = d->slavepid = fork (); - - switch (pid) { - - case 0: - setpgid (0, 0); - - /* Make the slave it's own leader. This 1) makes killing -pid of - * the daemon work more sanely because the daemon can whack the - * slave much better itself */ - setsid (); - - /* In the child setup empty mask and set all signals to - * default values, we'll make them more fun later */ - gdm_unset_signals (); - - d->slavepid = getpid (); - - gdm_connection_close (fifoconn); - fifoconn = NULL; - gdm_connection_close (pipeconn); - pipeconn = NULL; - gdm_connection_close (unixconn); - unixconn = NULL; - - gdm_log_shutdown (); - - /* Close everything */ - gdm_close_all_descriptors (0 /* from */, fds[0] /* except */, slave_fifo_pipe_fd /* except2 */); - - /* No error checking here - if it's messed the best response - * is to ignore & try to continue */ - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - gdm_log_init (); - - d->slave_notify_fd = fds[0]; - - fcntl (d->slave_notify_fd, F_SETFL, fcntl (d->slave_notify_fd, F_GETFL) | O_NONBLOCK); - - gdm_slave_start (d); - /* should never retern */ - - /* yaikes, how did we ever get here? */ - gdm_server_stop (d); - _exit (DISPLAY_REMANAGE); - - break; - - case -1: - d->slavepid = 0; - gdm_error (_("%s: Failed forking GDM slave process for %s"), - "gdm_display_manage", - d->name); - - return FALSE; - - default: - gdm_debug ("gdm_display_manage: Forked slave: %d", - (int)pid); - d->master_notify_fd = fds[1]; - VE_IGNORE_EINTR (close (fds[0])); - break; - } - - /* invalidate chosen hostname */ - g_free (d->chosen_hostname); - d->chosen_hostname = NULL; - - /* use_chooser can only be temporary, if you want it permanent you set it up - in the server definition with "chooser=true" and it will get set up during - server command line resolution */ - d->use_chooser = FALSE; - - if (SERVER_IS_LOCAL (d)) { - d->dispstat = DISPLAY_ALIVE; - } - - /* reset sleep to 1, to sleep just in case (avoids X server races) */ - d->sleep_before_run = 1; - - return TRUE; -} - - -/** - * gdm_display_unmanage: - * @d: Pointer to a GdmDisplay struct - * - * Stop services for a display - */ -void -gdm_display_unmanage (GdmDisplay *d) -{ - if (!d) - return; - - gdm_debug ("gdm_display_unmanage: Stopping %s (slave pid: %d)", - d->name, (int)d->slavepid); - - /* whack connections about this display */ - if (unixconn != NULL) - gdm_kill_subconnections_with_display (unixconn, d); - - /* Kill slave, this may in fact hang for a bit at least until the - * slave dies, which should be ASAP though */ - whack_old_slave (d, TRUE /* kill_connection */); - - d->dispstat = DISPLAY_DEAD; - if (d->type != TYPE_STATIC || d->removeconf) - gdm_display_dispose (d); - - gdm_debug ("gdm_display_unmanage: Display stopped"); -} - - -/* Why recount? It's just a lot more robust this way and - gets around those nasty one off errors and races. And we never - have so many displays that this would get too slow. */ -static void -count_session_limits (void) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - flexi_servers = 0; - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - - if (SERVER_IS_FLEXI (d)) { - flexi_servers++; - } - } -} - -/** - * gdm_display_dispose: - * @d: Pointer to a GdmDisplay struct - * - * Deallocate display and all its resources - */ - -void -gdm_display_dispose (GdmDisplay *d) -{ - - if (d == NULL) - return; - - /* paranoia */ - if (unixconn != NULL) - gdm_kill_subconnections_with_display (unixconn, d); - - if (d->socket_conn != NULL) { - GdmConnection *conn = d->socket_conn; - d->socket_conn = NULL; - gdm_connection_set_close_notify (conn, NULL, NULL); - } - - if (d->slave_notify_fd >= 0) { - VE_IGNORE_EINTR (close (d->slave_notify_fd)); - d->slave_notify_fd = -1; - } - - if (d->master_notify_fd >= 0) { - VE_IGNORE_EINTR (close (d->master_notify_fd)); - d->master_notify_fd = -1; - } - - gdm_daemon_config_display_list_remove (d); - - d->dispstat = DISPLAY_DEAD; - d->type = -1; - - count_session_limits (); - - if (d->name) { - gdm_debug ("gdm_display_dispose: Disposing %s", d->name); - g_free (d->name); - d->name = NULL; - } - - g_free (d->chosen_hostname); - d->chosen_hostname = NULL; - - g_free (d->hostname); - d->hostname = NULL; - - g_free (d->addrs); - d->addrs = NULL; - d->addr_count = 0; - - g_free (d->authfile); - d->authfile = NULL; - - g_free (d->authfile_gdm); - d->authfile_gdm = NULL; - - if (d->type == TYPE_XDMCP_PROXY) { - if (d->parent_auth_file != NULL) { - VE_IGNORE_EINTR (g_unlink (d->parent_auth_file)); - } - g_free (d->parent_auth_file); - d->parent_auth_file = NULL; - } - - if (d->parent_temp_auth_file != NULL) { - VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file)); - } - g_free (d->parent_temp_auth_file); - d->parent_temp_auth_file = NULL; - - if (d->auths) { - gdm_auth_free_auth_list (d->auths); - d->auths = NULL; - } - - if (d->local_auths) { - gdm_auth_free_auth_list (d->local_auths); - d->local_auths = NULL; - } - - g_free (d->userauth); - d->userauth = NULL; - - g_free (d->command); - d->command = NULL; - - g_free (d->cookie); - d->cookie = NULL; - - g_free (d->bcookie); - d->bcookie = NULL; - - if (d->indirect_id > 0) - gdm_choose_indirect_dispose_empty_id (d->indirect_id); - d->indirect_id = 0; - - g_free (d->parent_disp); - d->parent_disp = NULL; - - g_free (d->parent_auth_file); - d->parent_auth_file = NULL; - - g_free (d->login); - d->login = NULL; - - g_free (d->preset_user); - d->preset_user = NULL; - - g_free (d->xsession_errors_filename); - d->xsession_errors_filename = NULL; - - if (d->session_output_fd >= 0) { - VE_IGNORE_EINTR (close (d->session_output_fd)); - d->session_output_fd = -1; - } - - if (d->xsession_errors_fd >= 0) { - VE_IGNORE_EINTR (close (d->xsession_errors_fd)); - d->xsession_errors_fd = -1; - } - - g_free (d->chooser_last_line); - d->chooser_last_line = NULL; - - if (d->chooser_output_fd >= 0) { - VE_IGNORE_EINTR (close (d->chooser_output_fd)); - d->chooser_output_fd = -1; - } - - g_free (d->theme_name); - d->theme_name = NULL; - - g_free (d); -} - - -/** - * gdm_display_lookup: - * @pid: pid of slave process to look up - * - * Return the display managed by pid - */ - -GdmDisplay * -gdm_display_lookup (pid_t pid) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - /* Find slave in display list */ - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - - if (d != NULL && - pid == d->slavepid) - return d; - } - - /* Slave not found */ - return NULL; -} - - -/* EOF */ diff --git a/daemon/display.h b/daemon/display.h deleted file mode 100644 index 3fb281c9..00000000 --- a/daemon/display.h +++ /dev/null @@ -1,216 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _GDM_DISPLAY_H -#define _GDM_DISPLAY_H - -#include <X11/Xlib.h> /* for Display */ -#include <X11/Xmd.h> /* for CARD32 */ -#include <netinet/in.h> /* for in_addr */ - -typedef struct _GdmDisplay GdmDisplay; - -#include "gdm-net.h" /* for GdmConnection */ - -#define TYPE_STATIC 1 /* X server defined in GDM configuration */ -#define TYPE_XDMCP 2 /* Remote display/Xserver */ -#define TYPE_FLEXI 3 /* Local Flexi X server */ -#define TYPE_FLEXI_XNEST 4 /* Local Flexi Nested server */ -#define TYPE_XDMCP_PROXY 5 /* Proxy X server for XDMCP */ - -#define SERVER_IS_LOCAL(d) ((d)->type == TYPE_STATIC || \ - (d)->type == TYPE_FLEXI || \ - (d)->type == TYPE_FLEXI_XNEST || \ - (d)->type == TYPE_XDMCP_PROXY) -#define SERVER_IS_FLEXI(d) ((d)->type == TYPE_FLEXI || \ - (d)->type == TYPE_FLEXI_XNEST || \ - (d)->type == TYPE_XDMCP_PROXY) -#define SERVER_IS_PROXY(d) ((d)->type == TYPE_FLEXI_XNEST || \ - (d)->type == TYPE_XDMCP_PROXY) -#define SERVER_IS_XDMCP(d) ((d)->type == TYPE_XDMCP || \ - (d)->type == TYPE_XDMCP_PROXY) - -/* Use this to get the right authfile name */ -#define GDM_AUTHFILE(display) \ - (display->authfile_gdm != NULL ? display->authfile_gdm : display->authfile) - -/* Values between GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST and - GDM_LOGOUT_ACTION_CUSTOM_CMD_LAST are reserved and should not be used */ -typedef enum { - GDM_LOGOUT_ACTION_NONE = 0, - GDM_LOGOUT_ACTION_HALT, - GDM_LOGOUT_ACTION_REBOOT, - GDM_LOGOUT_ACTION_SUSPEND, - GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST, - GDM_LOGOUT_ACTION_CUSTOM_CMD_LAST, - GDM_LOGOUT_ACTION_LAST -} GdmLogoutAction; - -struct _GdmDisplay -{ - - /* ALL DISPLAY TYPES */ - - guint8 type; - Display *dsp; - - gchar *name; /* value of DISPLAY */ - gchar *hostname; /* remote hostname */ - - guint8 dispstat; - guint16 dispnum; - - gboolean logged_in; /* TRUE if someone is logged in */ - char *login; - - gboolean attached; /* Display is physically attached to the machine. */ - - gboolean handled; - gboolean tcp_disallowed; - int priority; - - gboolean timed_login_ok; - - gboolean try_different_greeter; - char *theme_name; - - time_t managetime; /* time the display was managed */ - - /* loop check stuff */ - time_t last_start_time; - time_t last_loop_start_time; - gint retry_count; - int sleep_before_run; - - gchar *cookie; - gchar *bcookie; - - gchar *authfile; /* authfile for the server */ - gchar *authfile_gdm; /* authfile readable by gdm user - if necessary */ - GSList *auths; - GSList *local_auths; - gchar *userauth; - gboolean authfb; - time_t last_auth_touch; - - int screenx; - int screeny; - int screenwidth; /* Note 0 means use the gdk size */ - int screenheight; - int lrh_offsetx; /* lower right hand corner x offset */ - int lrh_offsety; /* lower right hand corner y offset */ - - pid_t slavepid; - pid_t greetpid; - pid_t sesspid; - int last_sess_status; /* status returned by last session */ - - /* Notification connection */ - int master_notify_fd; /* write part of the connection */ - int slave_notify_fd; /* read part of the connection */ - /* The xsession-errors connection */ - int xsession_errors_fd; /* write to the file */ - int session_output_fd; /* read from the session */ - int xsession_errors_bytes; -#define MAX_XSESSION_ERRORS_BYTES (80*2500) /* maximum number of bytes in - the ~/.xsession-errors file */ - char *xsession_errors_filename; /* if NULL then there is no .xsession-errors - file */ - - /* chooser stuff */ - pid_t chooserpid; - gboolean use_chooser; /* run chooser instead of greeter */ - gchar *chosen_hostname; /* locally chosen hostname if not NULL, - "-query chosen_hostname" is appened to server command line */ - int chooser_output_fd; /* from the chooser */ - char *chooser_last_line; - guint indirect_id; - - gboolean is_emergency_server; - gboolean failsafe_xserver; - - /* Only set in the main daemon as that's the only place that cares */ - GdmLogoutAction logout_action; - - - /* XDMCP TYPE */ - - time_t acctime; - - int xdmcp_dispnum; - CARD32 sessionid; - - struct sockaddr_storage addr; - struct sockaddr_storage *addrs; /* array of addresses */ - int addr_count; /* number of addresses in array */ - /* Note that the above may in fact be empty even though - addr is set, these are just extra addresses - (it could also contain addr for all we know) */ - - - /* ALL LOCAL TYPE (static, flexi) */ - - int vt; - pid_t servpid; - guint8 servstat; - gchar *command; - time_t starttime; - /* order in the Xservers file for sessreg, -1 if unset yet */ - int x_servers_order; - - - /* STATIC TYPE */ - - gboolean removeconf; /* used to mark "dynamic" static displays for removal */ - gboolean busy_display; /* only needed on static displays since flexi try another */ - time_t last_x_failed; - int x_faileds; - - - /* FLEXI TYPE */ - - char *preset_user; - uid_t server_uid; - GdmConnection *socket_conn; - - - /* PROXY/Parented TYPE (flexi-xnest or xdmcp proxy) */ - - char *parent_disp; - Display *parent_dsp; - - - /* XDMCP PROXY TYPE */ - - char *parent_auth_file; - - - /* FLEXI XNEST TYPE */ - char *parent_temp_auth_file; -}; - -gboolean gdm_display_manage (GdmDisplay *d); -void gdm_display_dispose (GdmDisplay *d); -void gdm_display_unmanage (GdmDisplay *d); -GdmDisplay *gdm_display_lookup (pid_t pid); - -#endif /* _GDM_DISPLAY_H */ - diff --git a/daemon/errorgui.c b/daemon/errorgui.c deleted file mode 100644 index 082c7770..00000000 --- a/daemon/errorgui.c +++ /dev/null @@ -1,890 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <grp.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <fcntl.h> -#include <sys/stat.h> -#include <pwd.h> -#include <sys/types.h> -#include <signal.h> - -#include <glib/gi18n.h> -#include <gtk/gtk.h> -#include <gdk/gdkx.h> - -#include "gdm.h" -#include "misc.h" -#include "auth.h" -#include "errorgui.h" -#include "slave.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -#include "gdm-socket-protocol.h" - -static int screenx = 0; -static int screeny = 0; -static int screenwidth = 0; -static int screenheight = 0; - -static gboolean inhibit_gtk_modules = FALSE; -static gboolean inhibit_gtk_themes = FALSE; - -static void -setup_cursor (GdkCursorType type) -{ - GdkCursor *cursor = gdk_cursor_new (type); - gdk_window_set_cursor (gdk_get_default_root_window (), cursor); - gdk_cursor_unref (cursor); -} - -static gboolean -gdm_event (GSignalInvocationHint *ihint, - guint n_param_values, - const GValue *param_values, - gpointer data) -{ - GdkEvent *event; - - /* HAAAAAAAAAAAAAAAAACK */ - /* Since the user has not logged in yet and may have left/right - * mouse buttons switched, we just translate every right mouse click - * to a left mouse click */ - if (n_param_values != 2 || - !G_VALUE_HOLDS (¶m_values[1], GDK_TYPE_EVENT)) - return FALSE; - - event = g_value_get_boxed (¶m_values[1]); - if ((event->type == GDK_BUTTON_PRESS || - event->type == GDK_2BUTTON_PRESS || - event->type == GDK_3BUTTON_PRESS || - event->type == GDK_BUTTON_RELEASE) - && event->button.button == 3) - event->button.button = 1; - - return TRUE; -} - -static void -get_screen_size (GdmDisplay *d) -{ - if (d != NULL) { - screenx = d->screenx; - screeny = d->screeny; - screenwidth = d->screenwidth; - screenheight = d->screenheight; - } - - if (screenwidth <= 0) - screenwidth = gdk_screen_width (); - if (screenheight <= 0) - screenheight = gdk_screen_height (); -} - -static void -center_window (GtkWidget *window) -{ - int w, h; - - /* sanity, should never happen */ - if (window == NULL) - return; - - gtk_window_get_size (GTK_WINDOW (window), &w, &h); - - gtk_window_move (GTK_WINDOW (window), - screenx + - (screenwidth / 2) - - (w / 2), - screeny + - (screenheight / 2) - - (h / 2)); -} - -static void -show_errors (GtkWidget *button, gpointer data) -{ - GtkRequisition req; - GtkWidget *textsw = data; - GtkWidget *dlg = g_object_get_data (G_OBJECT (button), "dlg"); - - if (GTK_TOGGLE_BUTTON (button)->active) { - gtk_widget_show (textsw); - } else { - gtk_widget_hide (textsw); - } - - /* keep window at the size request size */ - gtk_widget_size_request (dlg, &req); - gtk_window_resize (GTK_WINDOW (dlg), req.width, req.height); -} - -static GtkWidget * -get_error_text_view (const char *details) -{ - GtkWidget *sw; - GtkWidget *tv; - GtkTextBuffer *buf; - GtkTextIter iter; - - tv = gtk_text_view_new (); - buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv)); - gtk_text_view_set_editable (GTK_TEXT_VIEW (tv), FALSE); - gtk_text_buffer_create_tag (buf, "foo", - "editable", FALSE, - "family", "monospace", - NULL); - gtk_text_buffer_get_iter_at_offset (buf, &iter, 0); - - gtk_text_buffer_insert_with_tags_by_name - (buf, &iter, - ve_sure_string (details), -1, - "foo", NULL); - - sw = gtk_scrolled_window_new (NULL, NULL); - if (gdk_screen_width () >= 800) - gtk_widget_set_size_request (sw, 500, 150); - else - gtk_widget_set_size_request (sw, 200, 150); - - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_ALWAYS); - - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), - GTK_SHADOW_IN); - - gtk_container_add (GTK_CONTAINER (sw), tv); - gtk_widget_show (tv); - - return sw; -} - -static void -setup_dialog (GdmDisplay *d, const char *name, int closefdexcept, gboolean set_gdm_ids, uid_t uid) -{ - int argc = 1; - char **argv; - struct passwd *pw; - - gdm_log_shutdown (); - - /* No error checking here - if it's messed the best response - * is to ignore & try to continue */ - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - if (set_gdm_ids) { - setgid (gdm_daemon_config_get_gdmgid ()); - initgroups (gdm_daemon_config_get_value_string (GDM_KEY_USER), gdm_daemon_config_get_gdmgid ()); - setuid (gdm_daemon_config_get_gdmuid ()); - pw = NULL; - } else { - pw = getpwuid (uid); - } - - gdm_desetuid (); - - /* restore initial environment */ - gdm_restoreenv (); - - gdm_log_init (); - - g_setenv ("LOGNAME", gdm_daemon_config_get_value_string (GDM_KEY_USER), TRUE); - g_setenv ("USER", gdm_daemon_config_get_value_string (GDM_KEY_USER), TRUE); - g_setenv ("USERNAME", gdm_daemon_config_get_value_string (GDM_KEY_USER), TRUE); - - g_setenv ("DISPLAY", d->name, TRUE); - g_unsetenv ("XAUTHORITY"); - - g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE); - - /* sanity env stuff */ - g_setenv ("SHELL", "/bin/sh", TRUE); - /* set HOME to /, we don't need no stinking HOME anyway */ - if (pw == NULL || - ve_string_empty (pw->pw_dir)) - g_setenv ("HOME", ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)), TRUE); - else - g_setenv ("HOME", pw->pw_dir, TRUE); - - argv = g_new0 (char *, 3); - argv[0] = (char *)name; - argc = 1; - - if ( ! inhibit_gtk_modules && - gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES) && - ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST))) { - argv[1] = g_strdup_printf ("--gtk-module=%s", gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST)); - argc = 2; - } - - if (inhibit_gtk_modules) { - g_unsetenv ("GTK_MODULES"); - } - - gtk_init (&argc, &argv); - - if ( ! inhibit_gtk_themes) { - const char *theme_name; - const gchar *gtkrc = gdm_daemon_config_get_value_string (GDM_KEY_GTKRC); - - if ( ! ve_string_empty (gtkrc) && - g_access (gtkrc, R_OK) == 0) - gtk_rc_parse (gtkrc); - - theme_name = d->theme_name; - if (ve_string_empty (theme_name)) - theme_name = gdm_daemon_config_get_value_string (GDM_KEY_GTK_THEME); - if ( ! ve_string_empty (theme_name)) { - gchar *theme_dir = gtk_rc_get_theme_dir (); - char *theme = g_strdup_printf ("%s/%s/gtk-2.0/gtkrc", theme_dir, theme_name); - g_free (theme_dir); - - if ( ! ve_string_empty (theme) && - g_access (theme, R_OK) == 0) - gtk_rc_parse (theme); - - g_free (theme); - } - } - - get_screen_size (d); -} - -static gboolean -dialog_failed (int status) -{ - if (WIFSIGNALED (status) && - (WTERMSIG (status) == SIGTERM || - WTERMSIG (status) == SIGINT || - WTERMSIG (status) == SIGQUIT || - WTERMSIG (status) == SIGHUP)) { - return FALSE; - } else if (WIFEXITED (status) && - WEXITSTATUS (status) == 0) { - return FALSE; - } else { - gdm_error ("failsafe dialog failed (inhibitions: %d %d)", - inhibit_gtk_modules, inhibit_gtk_themes); - return TRUE; - } -} - -void -gdm_errorgui_error_box_full (GdmDisplay *d, - GtkMessageType type, - const char *error, - const char *details_label, - const char *details_file, - uid_t uid, - gid_t gid) -{ - GdkDisplay *gdk_display; - pid_t pid; - - g_debug ("Forking extra process: error dialog"); - - pid = gdm_fork_extra (); - - if (pid == 0) { - guint sid; - GtkWidget *dlg; - GtkWidget *button; - char *loc; - char *details; - - if (details_label != NULL) { - if (strncmp (details_label, "NIL", 3) == 0) - details_label = NULL; - } - if (details_file != NULL) { - if (strncmp (details_file, "NIL", 3) == 0) - details_file = NULL; - } - - if (uid != 0) { - gid_t groups[1] = { gid }; - - /* if we for some reason fail here - don't allow the file */ - if G_UNLIKELY (setgid (gid) != 0) - details_file = NULL; - if G_UNLIKELY (setgroups (1, groups) != 0) - details_file = NULL; - if G_UNLIKELY (setuid (uid) != 0) - details_file = NULL; - - gdm_desetuid (); - } - - /* First read the details if they exist */ - if (details_label != NULL && details_file != NULL) { - FILE *fp; - struct stat s; - int r; - gboolean valid_utf8 = TRUE; - GString *gs = g_string_new (NULL); - - fp = NULL; - VE_IGNORE_EINTR (r = g_lstat (details_file, &s)); - if (r == 0) { - if (S_ISREG (s.st_mode)) { - VE_IGNORE_EINTR (fp = fopen (details_file, "r")); - } else { - loc = g_locale_to_utf8 (_("%s not a regular file!\n"), -1, NULL, NULL, NULL); - g_string_printf (gs, loc, details_file); - g_free (loc); - } - } - if (fp != NULL) { - char buf[256]; - int lines = 0; - char *getsret; - VE_IGNORE_EINTR (getsret = fgets (buf, sizeof (buf), fp)); - while (getsret != NULL) { - if ( ! g_utf8_validate (buf, -1, NULL)) - valid_utf8 = FALSE; - g_string_append (gs, buf); - /* cap the lines at 500, that's already - a possibility of 128k of data */ - if (lines++ > 500) { - loc = g_locale_to_utf8 (_("\n... File too long to display ...\n"), -1, NULL, NULL, NULL); - g_string_append (gs, loc); - g_free (loc); - break; - } - VE_IGNORE_EINTR (getsret = fgets (buf, sizeof (buf), fp)); - } - VE_IGNORE_EINTR (fclose (fp)); - } else { - loc = g_locale_to_utf8 (_("%s could not be opened"), -1, NULL, NULL, NULL); - g_string_append_printf (gs, loc, details_file); - g_free (loc); - } - - details = g_string_free (gs, FALSE); - - if ( ! valid_utf8) { - char *tmp = g_locale_to_utf8 (details, -1, NULL, NULL, NULL); - g_free (details); - details = tmp; - } - } else { - details = NULL; - } - - setup_dialog (d, "gtk-error-box", -1, TRUE, uid); - - loc = g_locale_to_utf8 (error, -1, NULL, NULL, NULL); - - dlg = gtk_message_dialog_new (NULL /* parent */, - 0 /* flags */, - type, - GTK_BUTTONS_NONE, - "%s", - loc); - g_free (loc); - gtk_widget_set_events (dlg, GDK_ALL_EVENTS_MASK); - gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); - - if (details_label != NULL) { - GtkWidget *text = get_error_text_view (details); - - loc = g_locale_to_utf8 (details_label, -1, NULL, NULL, NULL); - button = gtk_check_button_new_with_label (loc); - g_free (loc); - - gtk_widget_show (button); - g_object_set_data (G_OBJECT (button), "dlg", dlg); - g_signal_connect (button, "toggled", - G_CALLBACK (show_errors), - text); - - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), - button, FALSE, FALSE, 6); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), - text, FALSE, FALSE, 6); - - g_signal_connect_after (dlg, "size_allocate", - G_CALLBACK (center_window), - NULL); - } - - button = gtk_dialog_add_button (GTK_DIALOG (dlg), - GTK_STOCK_OK, - GTK_RESPONSE_OK); - sid = g_signal_lookup ("event", - GTK_TYPE_WIDGET); - g_signal_add_emission_hook (sid, - 0 /* detail */, - gdm_event, - NULL /* data */, - NULL /* destroy_notify */); - - center_window (dlg); - - gtk_widget_grab_focus (button); - - gtk_widget_show_now (dlg); - - gdk_display = gdk_display_get_default (); - - if (dlg->window != NULL) { - gdk_error_trap_push (); - XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display), - GDK_WINDOW_XWINDOW (dlg->window), - RevertToPointerRoot, - CurrentTime); - gdk_flush (); - gdk_error_trap_pop (); - } - - setup_cursor (GDK_LEFT_PTR); - - gtk_dialog_run (GTK_DIALOG (dlg)); - - XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display), - PointerRoot, - RevertToPointerRoot, - CurrentTime); - - _exit (0); - } else if (pid > 0) { - int status; - gdm_wait_for_extra (pid, &status); - - if (dialog_failed (status)) { - if ( ! inhibit_gtk_themes) { - /* on failure try again, this time without any themes - which may be causing a crash */ - inhibit_gtk_themes = TRUE; - gdm_errorgui_error_box_full (d, type, error, details_label, details_file, uid, gid); - inhibit_gtk_themes = FALSE; - } else if ( ! inhibit_gtk_modules) { - /* on failure try again, this time without any modules - which may be causing a crash */ - inhibit_gtk_modules = TRUE; - gdm_errorgui_error_box_full (d, type, error, details_label, details_file, uid, gid); - inhibit_gtk_modules = FALSE; - } - } - } else { - gdm_error (_("%s: Cannot fork to display error/info box"), - "gdm_errorgui_error_box"); - } -} - -static void -press_ok (GtkWidget *entry, gpointer data) -{ - GtkWidget *dlg = data; - gtk_dialog_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK); -} - -void -gdm_errorgui_error_box (GdmDisplay *d, GtkMessageType type, const char *error) -{ - char *msg; - int id = 0; - - msg = g_strdup_printf ("type=%d$$error=%s$$details_label=%s$$details_file=%s$$uid=%d$$gid=%d", type, error, "NIL", "NIL", id, id); - - gdm_slave_send_string (GDM_SOP_SHOW_ERROR_DIALOG, msg); - - g_free (msg); -} - -char * -gdm_errorgui_failsafe_question (GdmDisplay *d, - const char *question, - gboolean echo) -{ - GdkDisplay *gdk_display; - pid_t pid; - int p[2]; - - if G_UNLIKELY (pipe (p) < 0) - return NULL; - - g_debug ("Forking extra process: failsafe question"); - - pid = gdm_fork_extra (); - if (pid == 0) { - guint sid; - GtkWidget *dlg, *label, *entry; - char *loc; - - setup_dialog (d, "gtk-failsafe-question", p[1], TRUE /* set_gdm_ids */, 0); - - loc = g_locale_to_utf8 (question, -1, NULL, NULL, NULL); - - dlg = gtk_dialog_new_with_buttons (loc, - NULL /* parent */, - 0 /* flags */, - GTK_STOCK_OK, - GTK_RESPONSE_OK, - NULL); - gtk_widget_set_events (dlg, GDK_ALL_EVENTS_MASK); - gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); - g_signal_connect (G_OBJECT (dlg), "delete_event", - G_CALLBACK (gtk_true), NULL); - - label = gtk_label_new (loc); - gtk_widget_show_all (label); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), - label, FALSE, FALSE, 0); - entry = gtk_entry_new (); - gtk_widget_show_all (entry); - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), - entry, FALSE, FALSE, 0); - if ( ! echo) - gtk_entry_set_visibility (GTK_ENTRY (entry), - FALSE /* visible */); - g_signal_connect (G_OBJECT (entry), "activate", - G_CALLBACK (press_ok), dlg); - - sid = g_signal_lookup ("event", - GTK_TYPE_WIDGET); - g_signal_add_emission_hook (sid, - 0 /* detail */, - gdm_event, - NULL /* data */, - NULL /* destroy_notify */); - - center_window (dlg); - - gtk_widget_show_now (dlg); - - gdk_display = gdk_display_get_default (); - - if (dlg->window != NULL) { - gdk_error_trap_push (); - XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display), - GDK_WINDOW_XWINDOW (dlg->window), - RevertToPointerRoot, - CurrentTime); - gdk_flush (); - gdk_error_trap_pop (); - } - - gtk_widget_grab_focus (entry); - - setup_cursor (GDK_LEFT_PTR); - - gtk_dialog_run (GTK_DIALOG (dlg)); - - loc = g_locale_from_utf8 (ve_sure_string (gtk_entry_get_text (GTK_ENTRY (entry))), -1, NULL, NULL, NULL); - - gdm_fdprintf (p[1], "%s", ve_sure_string (loc)); - - XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display), - PointerRoot, - RevertToPointerRoot, - CurrentTime); - - _exit (0); - } else if (pid > 0) { - int status; - char buf[BUFSIZ]; - int bytes; - - VE_IGNORE_EINTR (close (p[1])); - - gdm_wait_for_extra (pid, &status); - - if (dialog_failed (status)) { - char *ret = NULL; - VE_IGNORE_EINTR (close (p[0])); - if ( ! inhibit_gtk_themes) { - /* on failure try again, this time without any themes - which may be causing a crash */ - inhibit_gtk_themes = TRUE; - ret = gdm_errorgui_failsafe_question (d, question, echo); - inhibit_gtk_themes = FALSE; - } else if ( ! inhibit_gtk_modules) { - /* on failure try again, this time without any modules - which may be causing a crash */ - inhibit_gtk_modules = TRUE; - ret = gdm_errorgui_failsafe_question (d, question, echo); - inhibit_gtk_modules = FALSE; - } - return ret; - } - - VE_IGNORE_EINTR (bytes = read (p[0], buf, BUFSIZ-1)); - if (bytes > 0) { - VE_IGNORE_EINTR (close (p[0])); - buf[bytes] = '\0'; - return g_strdup (buf); - } - VE_IGNORE_EINTR (close (p[0])); - } else { - gdm_error (_("%s: Cannot fork to display error/info box"), - "gdm_errorgui_failsafe_question"); - } - return NULL; -} - -gboolean -gdm_errorgui_failsafe_yesno (GdmDisplay *d, - const char *question) -{ - GdkDisplay *gdk_display; - pid_t pid; - int p[2]; - - if G_UNLIKELY (pipe (p) < 0) - return FALSE; - - g_debug ("Forking extra process: failsafe yes/no"); - - pid = gdm_fork_extra (); - if (pid == 0) { - guint sid; - GtkWidget *dlg; - char *loc; - - setup_dialog (d, "gtk-failsafe-yesno", p[1], TRUE /* set_gdm_ids */, 0); - - loc = g_locale_to_utf8 (question, -1, NULL, NULL, NULL); - - dlg = gtk_message_dialog_new (NULL /* parent */, - 0 /* flags */, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - "%s", - loc); - gtk_widget_set_events (dlg, GDK_ALL_EVENTS_MASK); - gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); - - sid = g_signal_lookup ("event", - GTK_TYPE_WIDGET); - g_signal_add_emission_hook (sid, - 0 /* detail */, - gdm_event, - NULL /* data */, - NULL /* destroy_notify */); - - center_window (dlg); - - gtk_widget_show_now (dlg); - - gdk_display = gdk_display_get_default (); - - if (dlg->window != NULL) { - gdk_error_trap_push (); - XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display), - GDK_WINDOW_XWINDOW (dlg->window), - RevertToPointerRoot, - CurrentTime); - gdk_flush (); - gdk_error_trap_pop (); - } - - setup_cursor (GDK_LEFT_PTR); - - if (gtk_dialog_run (GTK_DIALOG (dlg)) == GTK_RESPONSE_YES) - gdm_fdprintf (p[1], "yes\n"); - else - gdm_fdprintf (p[1], "no\n"); - - XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display), - PointerRoot, - RevertToPointerRoot, - CurrentTime); - - _exit (0); - } else if (pid > 0) { - int status; - char buf[BUFSIZ]; - int bytes; - - VE_IGNORE_EINTR (close (p[1])); - - gdm_wait_for_extra (pid, &status); - - if (dialog_failed (status)) { - gboolean ret = FALSE; - VE_IGNORE_EINTR (close (p[0])); - if ( ! inhibit_gtk_themes) { - /* on failure try again, this time without any themes - which may be causing a crash */ - inhibit_gtk_themes = TRUE; - ret = gdm_errorgui_failsafe_yesno (d, question); - inhibit_gtk_themes = FALSE; - } else if ( ! inhibit_gtk_modules) { - /* on failure try again, this time without any modules - which may be causing a crash */ - inhibit_gtk_modules = TRUE; - ret = gdm_errorgui_failsafe_yesno (d, question); - inhibit_gtk_modules = FALSE; - } - return ret; - } - - VE_IGNORE_EINTR (bytes = read (p[0], buf, BUFSIZ-1)); - if (bytes > 0) { - VE_IGNORE_EINTR (close (p[0])); - if (buf[0] == 'y') - return TRUE; - else - return FALSE; - } - VE_IGNORE_EINTR (close (p[0])); - } else { - gdm_error (_("%s: Cannot fork to display error/info box"), - "gdm_errorgui_failsafe_yesno"); - } - return FALSE; -} - -int -gdm_errorgui_failsafe_ask_buttons (GdmDisplay *d, - const char *question, - char **but) -{ - GdkDisplay *gdk_display; - pid_t pid; - int p[2]; - - if G_UNLIKELY (pipe (p) < 0) - return -1; - - g_debug ("Forking extra process: failsafe ask buttons"); - - pid = gdm_fork_extra (); - if (pid == 0) { - int i; - guint sid; - GtkWidget *dlg; - char *loc; - - setup_dialog (d, "gtk-failsafe-ask-buttons", p[1], TRUE /* set_gdm_ids */, 0); - - loc = g_locale_to_utf8 (question, -1, NULL, NULL, NULL); - - dlg = gtk_message_dialog_new (NULL /* parent */, - 0 /* flags */, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_NONE, - "%s", - loc); - g_free (loc); - gtk_widget_set_events (dlg, GDK_ALL_EVENTS_MASK); - for (i = 0; but[i] != NULL && strcmp (but[i], "NIL"); i++) { - loc = g_locale_to_utf8 (but[i], -1, NULL, NULL, NULL); - gtk_dialog_add_button (GTK_DIALOG (dlg), - loc, i); - g_free (loc); - - } - gtk_dialog_set_has_separator (GTK_DIALOG (dlg), FALSE); - - sid = g_signal_lookup ("event", - GTK_TYPE_WIDGET); - g_signal_add_emission_hook (sid, - 0 /* detail */, - gdm_event, - NULL /* data */, - NULL /* destroy_notify */); - - center_window (dlg); - - gtk_widget_show_now (dlg); - - gdk_display = gdk_display_get_default (); - - if (dlg->window != NULL) { - gdk_error_trap_push (); - XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display), - GDK_WINDOW_XWINDOW (dlg->window), - RevertToPointerRoot, - CurrentTime); - gdk_flush (); - gdk_error_trap_pop (); - } - - setup_cursor (GDK_LEFT_PTR); - - i = gtk_dialog_run (GTK_DIALOG (dlg)); - gdm_fdprintf (p[1], "%d\n", i); - - XSetInputFocus (GDK_DISPLAY_XDISPLAY (gdk_display), - PointerRoot, - RevertToPointerRoot, - CurrentTime); - - _exit (0); - } else if (pid > 0) { - int status; - char buf[BUFSIZ]; - int bytes; - - VE_IGNORE_EINTR (close (p[1])); - - gdm_wait_for_extra (pid, &status); - - if (dialog_failed (status)) { - int ret = -1; - VE_IGNORE_EINTR (close (p[0])); - if ( ! inhibit_gtk_themes) { - /* on failure try again, this time without any themes - which may be causing a crash */ - inhibit_gtk_themes = TRUE; - ret = gdm_errorgui_failsafe_ask_buttons (d, question, but); - inhibit_gtk_themes = FALSE; - } else if ( ! inhibit_gtk_modules) { - /* on failure try again, this time without any modules - which may be causing a crash */ - inhibit_gtk_modules = TRUE; - ret = gdm_errorgui_failsafe_ask_buttons (d, question, but); - inhibit_gtk_modules = FALSE; - } - return ret; - } - - VE_IGNORE_EINTR (bytes = read (p[0], buf, BUFSIZ-1)); - if (bytes > 0) { - int i; - VE_IGNORE_EINTR (close (p[0])); - buf[bytes] = '\0'; - if (sscanf (buf, "%d", &i) == 1) - return i; - else - return -1; - } - VE_IGNORE_EINTR (close (p[0])); - } else { - gdm_error (_("%s: Cannot fork to display error/info box"), - "gdm_errorgui_failsafe_ask_buttons"); - } - return -1; -} diff --git a/daemon/errorgui.h b/daemon/errorgui.h deleted file mode 100644 index 15d245cd..00000000 --- a/daemon/errorgui.h +++ /dev/null @@ -1,53 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_ERRORGUI_H -#define GDM_ERRORGUI_H - -#include "gdm.h" -#include <gtk/gtkmessagedialog.h> - -void gdm_errorgui_error_box_full (GdmDisplay *d, - GtkMessageType type, - const char *error, - const char *details_label, - const char *details_file, - /* zero doesn't mean root, - we never wish to run as root, - zero means use the gdm user */ - uid_t uid, - gid_t gid); - -void gdm_errorgui_error_box (GdmDisplay *d, - GtkMessageType type, - const char *error); - -char * gdm_errorgui_failsafe_question (GdmDisplay *d, - const char *question, - gboolean echo); - -gboolean gdm_errorgui_failsafe_yesno (GdmDisplay *d, - const char *question); -int gdm_errorgui_failsafe_ask_buttons (GdmDisplay *d, - const char *question, - char **but); - -#endif /* GDM_ERRORGUI_H */ - -/* EOF */ - diff --git a/daemon/filecheck.c b/daemon/filecheck.c deleted file mode 100644 index b08ae94d..00000000 --- a/daemon/filecheck.c +++ /dev/null @@ -1,222 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <glib/gi18n.h> -#include <sys/stat.h> - -#include "gdm.h" -#include "filecheck.h" - -#include "gdm-common.h" -#include "gdm-daemon-config.h" - -/** - * gdm_file_check: - * @caller: String to be prepended to error messages. - * @user: User id for the user owning the file/dir. - * @dir: Directory to be examined. - * @file: File to be examined. - * @absentok: Accept absent files if TRUE. - * @absentdirok: Absent directory returns FALSE but without complaining - * @maxsize: Maximum acceptable filesize in KB. 0 to disable. - * @perms: 0 to allow user writable file/dir only. 1 to allow group and 2 to allow global writable file/dir. - * - * Examines a file to determine whether it is safe for the daemon to write to it. - */ - -/* we should be euid the user BTW */ -gboolean -gdm_file_check (const gchar *caller, - uid_t user, - const gchar *dir, - const gchar *file, - gboolean absentok, - gboolean absentdirok, - gint maxsize, - gint perms) -{ - struct stat statbuf; - gchar *fullpath; - gchar *dirautofs; - int r; - - if (ve_string_empty (dir) || - ve_string_empty (file)) - return FALSE; - - /* Stat on automounted directory - append the '/.' to dereference mount point. - Do this only if GdmSupportAutomount is true (default is false) - 2006-09-22, Jerzy Borkowski, CAMK */ - if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_SUPPORT_AUTOMOUNT)) { - dirautofs = g_strconcat(dir, "/.", NULL); - VE_IGNORE_EINTR (r = stat (dirautofs, &statbuf)); - g_free(dirautofs); - } - /* Stat directory */ - else { - VE_IGNORE_EINTR (r = stat (dir, &statbuf)); - } - - if (r < 0) { - if ( ! absentdirok) - g_warning (_("%s: Directory %s does not exist."), - caller, dir); - return FALSE; - } - - /* Check if dir is owned by the user ... - Only, if GDM_KEY_CHECK_DIR_OWNER is true (default) - This is a "hack" for directories not owned by - the user. - 2004-06-22, Andreas Schubert, MATHEMA Software GmbH */ - - if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_CHECK_DIR_OWNER) && (statbuf.st_uid != user)) { - g_warning (_("%s: %s is not owned by uid %d."), caller, dir, user); - return FALSE; - } - - /* ... if group has write permission ... */ - if G_UNLIKELY (perms < 1 && (statbuf.st_mode & S_IWGRP) == S_IWGRP) { - g_warning (_("%s: %s is writable by group."), caller, dir); - return FALSE; - } - - /* ... and if others have write permission. */ - if G_UNLIKELY (perms < 2 && (statbuf.st_mode & S_IWOTH) == S_IWOTH) { - g_warning (_("%s: %s is writable by other."), caller, dir); - return FALSE; - } - - fullpath = g_build_filename (dir, file, NULL); - - /* Stat file */ - VE_IGNORE_EINTR (r = g_stat (fullpath, &statbuf)); - if (r < 0) { - /* Return true if file does not exist and that is ok */ - if (absentok) { - g_free (fullpath); - return TRUE; - } - else { - g_warning (_("%s: %s does not exist but must exist."), caller, fullpath); - g_free (fullpath); - return FALSE; - } - } - - /* Check that it is a regular file ... */ - if G_UNLIKELY (! S_ISREG (statbuf.st_mode)) { - g_warning (_("%s: %s is not a regular file."), caller, fullpath); - g_free (fullpath); - return FALSE; - } - - /* ... owned by the user ... */ - if G_UNLIKELY (statbuf.st_uid != user) { - g_warning (_("%s: %s is not owned by uid %d."), caller, fullpath, user); - g_free (fullpath); - return FALSE; - } - - /* ... unwritable by group ... */ - if G_UNLIKELY (perms < 1 && (statbuf.st_mode & S_IWGRP) == S_IWGRP) { - g_warning (_("%s: %s is writable by group."), caller, fullpath); - g_free (fullpath); - return FALSE; - } - - /* ... unwritable by others ... */ - if G_UNLIKELY (perms < 2 && (statbuf.st_mode & S_IWOTH) == S_IWOTH) { - g_warning (_("%s: %s is writable by group/other."), caller, fullpath); - g_free (fullpath); - return FALSE; - } - - /* ... and smaller than sysadmin specified limit. */ - if G_UNLIKELY (maxsize && statbuf.st_size > maxsize) { - g_warning (_("%s: %s is bigger than sysadmin specified maximum file size."), - caller, fullpath); - g_free (fullpath); - return FALSE; - } - - g_free (fullpath); - - /* Yeap, this file is ok */ - return TRUE; -} - -/* we should be euid the user BTW */ -gboolean -gdm_auth_file_check (const gchar *caller, - uid_t user, - const gchar *authfile, - gboolean absentok, - struct stat *s) -{ - struct stat statbuf; - gint usermaxfile; - int r; - - if (ve_string_empty (authfile)) - return FALSE; - - /* Stat file */ - VE_IGNORE_EINTR (r = g_lstat (authfile, &statbuf)); - if (s != NULL) - *s = statbuf; - if (r < 0) { - if (absentok) - return TRUE; - g_warning (_("%s: %s does not exist but must exist."), caller, authfile); - return FALSE; - } - - /* Check that it is a regular file ... */ - if G_UNLIKELY (! S_ISREG (statbuf.st_mode)) { - g_warning (_("%s: %s is not a regular file."), caller, authfile); - return FALSE; - } - - /* ... owned by the user ... */ - if G_UNLIKELY (statbuf.st_uid != user) { - g_warning (_("%s: %s is not owned by uid %d."), caller, authfile, user); - return FALSE; - } - - /* ... has right permissions ... */ - if G_UNLIKELY (statbuf.st_mode & 0077) { - g_warning ("%s: %s has wrong permissions (should be 0600)", caller, authfile); - return FALSE; - } - - usermaxfile = gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE); - /* ... and smaller than sysadmin specified limit. */ - if G_UNLIKELY (usermaxfile && statbuf.st_size > usermaxfile) { - g_warning (_("%s: %s is bigger than sysadmin specified maximum file size."), - caller, authfile); - return FALSE; - } - - /* Yeap, this file is ok */ - return TRUE; -} diff --git a/daemon/filecheck.h b/daemon/filecheck.h deleted file mode 100644 index 7d71a691..00000000 --- a/daemon/filecheck.h +++ /dev/null @@ -1,33 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_FILECHECK_H -#define GDM_FILECHECK_H - -gboolean gdm_file_check (const gchar *caller, uid_t user, const gchar *dir, - const gchar *file, gboolean absentok, - gboolean absentdirok, gint maxsize, - gint perms); - -/* more paranoid on the file itself, doesn't check directory (for all we know - it could be /tmp) */ -gboolean gdm_auth_file_check (const gchar *caller, uid_t user, const gchar *authfile, gboolean absentok, struct stat *s); - -#endif /* GDM_FILECHECK_H */ - -/* EOF */ diff --git a/daemon/fstype.c b/daemon/fstype.c deleted file mode 100644 index 84936ab1..00000000 --- a/daemon/fstype.c +++ /dev/null @@ -1,423 +0,0 @@ -/* fstype.c -- determine type of filesystems that files are on - Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc. - - 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 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* This code was relicensed by the FSF on May 1 2002 - - This file is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - this file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with the Gnome Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - */ -/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ - -#include "config.h" - -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#ifdef STDC_HEADERS -#include <stdlib.h> -#else -extern int errno; -#endif -#include <string.h> -#ifdef HAVE_LIBGEN_H -#include <libgen.h> -#endif - -#if __STDC__ -# define P_(s) s -#else -# define P_(s) () -#endif - -static char *filesystem_type_uncached P_((char *path, char *relpath, struct stat *statp)); - -void fstype_internal_error (int level, int num, char const *fmt, ...); - -#ifdef FSTYPE_MNTENT /* 4.3BSD etc. */ -static int xatoi P_((char *cp)); -#endif - -#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ -#include <mntent.h> -#if !defined(MOUNTED) -# if defined(MNT_MNTTAB) /* HP-UX. */ -# define MOUNTED MNT_MNTTAB -# endif -# if defined(MNTTABNAME) /* Dynix. */ -# define MOUNTED MNTTABNAME -# endif -#endif -#endif - -#ifdef FSTYPE_GETMNT /* Ultrix. */ -#include <sys/param.h> -#include <sys/mount.h> -#include <sys/fs_types.h> -#endif - -#ifdef FSTYPE_USG_STATFS /* SVR3. */ -#include <sys/statfs.h> -#include <sys/fstyp.h> -#endif - -#ifdef FSTYPE_STATVFS /* SVR4. */ -#include <sys/statvfs.h> -#include <sys/fstyp.h> -#endif - -#ifdef FSTYPE_STATFS /* 4.4BSD. */ -#include <sys/param.h> /* NetBSD needs this. */ -#include <sys/mount.h> - -#ifndef MFSNAMELEN /* NetBSD defines this. */ -static char * -fstype_to_string (t) - short t; -{ -#ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */ - static char *mn[] = INITMOUNTNAMES; - if (t >= 0 && t <= MOUNT_MAXTYPE) - return mn[t]; - else - return "?"; -#else /* !INITMOUNTNAMES */ - switch (t) - { - case MOUNT_UFS: - return "ufs"; - case MOUNT_NFS: - return "nfs"; -#ifdef MOUNT_PC - case MOUNT_PC: - return "pc"; -#endif -#ifdef MOUNT_MFS - case MOUNT_MFS: - return "mfs"; -#endif -#ifdef MOUNT_LO - case MOUNT_LO: - return "lofs"; -#endif -#ifdef MOUNT_TFS - case MOUNT_TFS: - return "tfs"; -#endif -#ifdef MOUNT_TMP - case MOUNT_TMP: - return "tmp"; -#endif -#ifdef MOUNT_MSDOS - case MOUNT_MSDOS: - return "msdos"; -#endif -#ifdef MOUNT_ISO9660 - case MOUNT_ISO9660: - return "iso9660fs"; -#endif - default: - return "?"; - } -#endif /* !INITMOUNTNAMES */ -} -#endif /* !MFSNAMELEN */ -#endif /* FSTYPE_STATFS */ - -#ifdef FSTYPE_AIX_STATFS /* AIX. */ -#include <sys/vmount.h> -#include <sys/statfs.h> - -#define FSTYPE_STATFS /* Otherwise like 4.4BSD. */ -#define f_type f_vfstype - -static char * -fstype_to_string (t) - short t; -{ - switch (t) - { - case MNT_AIX: -#if 0 /* NFS filesystems are actually MNT_AIX. */ - return "aix"; -#endif - case MNT_NFS: - return "nfs"; - case MNT_JFS: - return "jfs"; - case MNT_CDROM: - return "cdrom"; - default: - return "?"; - } -} -#endif /* FSTYPE_AIX_STATFS */ - -#ifdef AFS -#include <netinet/in.h> -#include <afs/venus.h> -#if __STDC__ -/* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */ -#undef _VICEIOCTL -#define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl)) -#endif -#ifndef _IOW -/* AFS on Solaris 2.3 doesn't get this definition. */ -#include <sys/ioccom.h> -#endif - -static int -in_afs (path) - char *path; -{ - static char space[2048]; - struct ViceIoctl vi; - - vi.in_size = 0; - vi.out_size = sizeof (space); - vi.out = space; - - if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1) - && (errno == EINVAL || errno == ENOENT)) - return 0; - return 1; -} -#endif /* AFS */ - -#include <glib.h> -#include <glib/gstdio.h> - -/* Nonzero if the current filesystem's type is known. */ -static int fstype_known = 0; - -char *filesystem_type (char *path, char *relpath, struct stat *statp); -/* Return a static string naming the type of filesystem that the file PATH, - described by STATP, is on. - RELPATH is the file name relative to the current directory. - Return "unknown" if its filesystem type is unknown. */ - -char * -filesystem_type (char *path, char *relpath, struct stat *statp) -{ - static char *current_fstype = NULL; - static dev_t current_dev; - - if (current_fstype != NULL) - { - if (fstype_known && statp->st_dev == current_dev) - return current_fstype; /* Cached value. */ - g_free (current_fstype); - } - current_dev = statp->st_dev; - current_fstype = filesystem_type_uncached (path, relpath, statp); - return current_fstype; -} - -void -fstype_internal_error (int level, int num, char const *fmt, ...) -{ -} - -/* Return a newly allocated string naming the type of filesystem that the - file PATH, described by STATP, is on. - RELPATH is the file name relative to the current directory. - Return "unknown" if its filesystem type is unknown. */ - -static char * -filesystem_type_uncached (char *path, char *relpath, struct stat *statp) -{ - char *type = NULL; - -#ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ - char *table = MOUNTED; - FILE *mfp; - struct mntent *mnt; - - mfp = setmntent (table, "r"); - if (mfp == NULL) { - fstype_internal_error (1, errno, "%s", table); - goto no_mtab; - } - - /* Find the entry with the same device number as STATP, and return - that entry's fstype. */ - while (type == NULL && (mnt = getmntent (mfp))) - { - char *devopt; - dev_t dev; - struct stat disk_stats; - -#ifdef MNTTYPE_IGNORE - if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE)) - continue; -#endif - - /* Newer systems like SunOS 4.1 keep the dev number in the mtab, - in the options string. For older systems, we need to stat the - directory that the filesystem is mounted on to get it. - - Unfortunately, the HPUX 9.x mnttab entries created by automountq - contain a dev= option but the option value does not match the - st_dev value of the file (maybe the lower 16 bits match?). */ - -#if !defined(hpux) && !defined(__hpux__) - devopt = strstr (mnt->mnt_opts, "dev="); - if (devopt) - { - if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X')) - dev = xatoi (devopt + 6); - else - dev = xatoi (devopt + 4); - } - else -#endif /* not hpux */ - { - if (g_stat (mnt->mnt_dir, &disk_stats) == -1) { - if (errno == EACCES) - continue; - else - fstype_internal_error (1, errno, "error in %s: %s", table, mnt->mnt_dir); - } - dev = disk_stats.st_dev; - } - - if (dev == statp->st_dev) - type = mnt->mnt_type; - } - - if (endmntent (mfp) == 0) - fstype_internal_error (0, errno, "%s", table); - no_mtab: -#endif - -#ifdef FSTYPE_GETMNT /* Ultrix. */ - int offset = 0; - struct fs_data fsd; - - while (type == NULL - && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0) - { - if (fsd.fd_req.dev == statp->st_dev) - type = gt_names[fsd.fd_req.fstype]; - } -#endif - -#ifdef FSTYPE_USG_STATFS /* SVR3. */ - struct statfs fss; - char typebuf[FSTYPSZ]; - - if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1) - { - /* Don't die if a file was just removed. */ - if (errno != ENOENT) - fstype_internal_error (1, errno, "%s", path); - } - else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf)) - type = typebuf; -#endif - -#ifdef FSTYPE_STATVFS /* SVR4. */ - struct statvfs fss; - - if (statvfs (relpath, &fss) == -1) - { - /* Don't die if a file was just removed. */ - if (errno != ENOENT) - fstype_internal_error (1, errno, "%s", path); - } - else - type = fss.f_basetype; -#endif - -#ifdef FSTYPE_STATFS /* 4.4BSD. */ - struct statfs fss; - char *p; - - if (S_ISLNK (statp->st_mode)) - p = dirname (relpath); - else - p = relpath; - - if (statfs (p, &fss) == -1) - { - /* Don't die if symlink to nonexisting file, or a file that was - just removed. */ - if (errno != ENOENT) - fstype_internal_error (1, errno, "%s", path); - } - else - { -#ifdef MFSNAMELEN /* NetBSD. */ - type = fss.f_fstypename; -#else - type = fstype_to_string (fss.f_type); -#endif - } - if (p != relpath) - free (p); -#endif - -#ifdef AFS - if ((!type || !strcmp (type, "xx")) && in_afs (relpath)) - type = "afs"; -#endif - - /* An unknown value can be caused by an ENOENT error condition. - Don't cache those values. */ - fstype_known = (type != NULL); - - return g_strdup (type ? type : "unknown"); -} - -#ifdef FSTYPE_MNTENT /* 4.3BSD etc. */ -/* Return the value of the hexadecimal number represented by CP. - No prefix (like '0x') or suffix (like 'h') is expected to be - part of CP. */ - -static int -xatoi (char *cp) -{ - int val; - - val = 0; - while (*cp) - { - if (*cp >= 'a' && *cp <= 'f') - val = val * 16 + *cp - 'a' + 10; - else if (*cp >= 'A' && *cp <= 'F') - val = val * 16 + *cp - 'A' + 10; - else if (*cp >= '0' && *cp <= '9') - val = val * 16 + *cp - '0'; - else - break; - cp++; - } - return val; -} -#endif diff --git a/daemon/gdm-daemon-config-entries.h b/daemon/gdm-daemon-config-entries.h deleted file mode 100644 index f335ed17..00000000 --- a/daemon/gdm-daemon-config-entries.h +++ /dev/null @@ -1,569 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _GDM_DAEMON_CONFIG_ENTRIES_H -#define _GDM_DAEMON_CONFIG_ENTRIES_H - -#include <glib.h> - -#include "gdm-config.h" - -G_BEGIN_DECLS - -#define GDM_CONFIG_GROUP_NONE NULL -#define GDM_CONFIG_GROUP_DAEMON "daemon" -#define GDM_CONFIG_GROUP_SECURITY "security" -#define GDM_CONFIG_GROUP_XDMCP "xdmcp" -#define GDM_CONFIG_GROUP_GREETER "greeter" -#define GDM_CONFIG_GROUP_GUI "gui" -#define GDM_CONFIG_GROUP_CUSTOM_CMD "customcommand" -#define GDM_CONFIG_GROUP_CHOOSER "chooser" -#define GDM_CONFIG_GROUP_SERVERS "servers" -#define GDM_CONFIG_GROUP_DEBUG "debug" - -#define GDM_CONFIG_GROUP_SERVER_PREFIX "server-" - -#include "gdm-daemon-config-keys.h" - -typedef enum { - GDM_ID_NONE, - GDM_ID_DEBUG, - GDM_ID_DEBUG_GESTURES, - GDM_ID_CHOOSER, - GDM_ID_AUTOMATIC_LOGIN_ENABLE, - GDM_ID_AUTOMATIC_LOGIN, - GDM_ID_GREETER, - GDM_ID_REMOTE_GREETER, - GDM_ID_ADD_GTK_MODULES, - GDM_ID_GTK_MODULES_LIST, - GDM_ID_GROUP, - GDM_ID_HALT, - GDM_ID_DISPLAY_INIT_DIR, - GDM_ID_KILL_INIT_CLIENTS, - GDM_ID_LOG_DIR, - GDM_ID_PATH, - GDM_ID_POSTSESSION, - GDM_ID_PRESESSION, - GDM_ID_POSTLOGIN, - GDM_ID_FAILSAFE_XSERVER, - GDM_ID_X_KEEPS_CRASHING, - GDM_ID_REBOOT , - GDM_ID_CUSTOM_CMD_TEMPLATE, - GDM_ID_CUSTOM_CMD_LABEL_TEMPLATE, - GDM_ID_CUSTOM_CMD_LR_LABEL_TEMPLATE, - GDM_ID_CUSTOM_CMD_TEXT_TEMPLATE, - GDM_ID_CUSTOM_CMD_TOOLTIP_TEMPLATE, - GDM_ID_CUSTOM_CMD_NO_RESTART_TEMPLATE, - GDM_ID_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, - GDM_ID_ROOT_PATH, - GDM_ID_SERV_AUTHDIR, - GDM_ID_SESSION_DESKTOP_DIR, - GDM_ID_BASE_XSESSION, - GDM_ID_DEFAULT_SESSION, - GDM_ID_SUSPEND, - GDM_ID_USER_AUTHDIR, - GDM_ID_USER_AUTHDIR_FALLBACK, - GDM_ID_USER_AUTHFILE, - GDM_ID_USER, - GDM_ID_CONSOLE_NOTIFY, - GDM_ID_DOUBLE_LOGIN_WARNING, - GDM_ID_ALWAYS_LOGIN_CURRENT_SESSION, - GDM_ID_DISPLAY_LAST_LOGIN, - GDM_ID_TIMED_LOGIN_ENABLE, - GDM_ID_TIMED_LOGIN, - GDM_ID_TIMED_LOGIN_DELAY, - GDM_ID_FLEXI_REAP_DELAY_MINUTES, - GDM_ID_STANDARD_XSERVER, - GDM_ID_FLEXIBLE_XSERVERS, - GDM_ID_DYNAMIC_XSERVERS, - GDM_ID_XNEST, - GDM_ID_XNEST_UNSCALED_FONT_PATH, - GDM_ID_FIRST_VT, - GDM_ID_VT_ALLOCATION, - GDM_ID_CONSOLE_CANNOT_HANDLE, - GDM_ID_XSERVER_TIMEOUT, - GDM_ID_SERVER_PREFIX, - GDM_ID_SERVER_NAME, - GDM_ID_SERVER_COMMAND, - GDM_ID_SERVER_FLEXIBLE, - GDM_ID_SERVER_CHOOSABLE, - GDM_ID_SERVER_HANDLED, - GDM_ID_SERVER_CHOOSER, - GDM_ID_SERVER_PRIORITY, - GDM_ID_ALLOW_ROOT, - GDM_ID_ALLOW_REMOTE_ROOT, - GDM_ID_ALLOW_REMOTE_AUTOLOGIN, - GDM_ID_USER_MAX_FILE, - GDM_ID_RELAX_PERM, - GDM_ID_CHECK_DIR_OWNER, - GDM_ID_SUPPORT_AUTOMOUNT, - GDM_ID_RETRY_DELAY, - GDM_ID_DISALLOW_TCP, - GDM_ID_PAM_STACK, - GDM_ID_NEVER_PLACE_COOKIES_ON_NFS, - GDM_ID_PASSWORD_REQUIRED, - GDM_ID_XDMCP, - GDM_ID_MAX_PENDING, - GDM_ID_MAX_SESSIONS, - GDM_ID_MAX_WAIT, - GDM_ID_DISPLAYS_PER_HOST, - GDM_ID_UDP_PORT, - GDM_ID_INDIRECT, - GDM_ID_MAX_INDIRECT, - GDM_ID_MAX_WAIT_INDIRECT, - GDM_ID_PING_INTERVAL, - GDM_ID_WILLING, - GDM_ID_XDMCP_PROXY, - GDM_ID_XDMCP_PROXY_XSERVER, - GDM_ID_XDMCP_PROXY_RECONNECT, - GDM_ID_GTK_THEME, - GDM_ID_GTKRC, - GDM_ID_MAX_ICON_WIDTH, - GDM_ID_MAX_ICON_HEIGHT, - GDM_ID_ALLOW_GTK_THEME_CHANGE, - GDM_ID_GTK_THEMES_TO_ALLOW, - GDM_ID_BROWSER, - GDM_ID_INCLUDE, - GDM_ID_EXCLUDE, - GDM_ID_INCLUDE_ALL, - GDM_ID_MINIMAL_UID, - GDM_ID_DEFAULT_FACE, - GDM_ID_GLOBAL_FACE_DIR, - GDM_ID_LOCALE_FILE, - GDM_ID_LOGO, - GDM_ID_CHOOSER_BUTTON_LOGO, - GDM_ID_QUIVER, - GDM_ID_SYSTEM_MENU, - GDM_ID_CONFIGURATOR, - GDM_ID_CONFIG_AVAILABLE, - GDM_ID_CHOOSER_BUTTON, - GDM_ID_TITLE_BAR, - GDM_ID_DEFAULT_WELCOME, - GDM_ID_DEFAULT_REMOTE_WELCOME, - GDM_ID_WELCOME, - GDM_ID_REMOTE_WELCOME, - GDM_ID_XINERAMA_SCREEN, - GDM_ID_BACKGROUND_PROGRAM, - GDM_ID_RUN_BACKGROUND_PROGRAM_ALWAYS, - GDM_ID_BACKGROUND_PROGRAM_INITIAL_DELAY, - GDM_ID_RESTART_BACKGROUND_PROGRAM, - GDM_ID_BACKGROUND_PROGRAM_RESTART_DELAY, - GDM_ID_BACKGROUND_IMAGE, - GDM_ID_BACKGROUND_COLOR, - GDM_ID_BACKGROUND_TYPE, - GDM_ID_BACKGROUND_SCALE_TO_FIT, - GDM_ID_BACKGROUND_REMOTE_ONLY_COLOR, - GDM_ID_LOCK_POSITION, - GDM_ID_SET_POSITION, - GDM_ID_POSITION_X, - GDM_ID_POSITION_Y, - GDM_ID_USE_24_CLOCK, - GDM_ID_ENTRY_CIRCLES, - GDM_ID_ENTRY_INVISIBLE, - GDM_ID_GRAPHICAL_THEME, - GDM_ID_GRAPHICAL_THEMES, - GDM_ID_GRAPHICAL_THEME_RAND, - GDM_ID_GRAPHICAL_THEME_DIR, - GDM_ID_GRAPHICAL_THEMED_COLOR, - GDM_ID_INFO_MSG_FILE, - GDM_ID_INFO_MSG_FONT, - GDM_ID_PRE_FETCH_PROGRAM, - GDM_ID_SOUND_ON_LOGIN, - GDM_ID_SOUND_ON_LOGIN_SUCCESS, - GDM_ID_SOUND_ON_LOGIN_FAILURE, - GDM_ID_SOUND_ON_LOGIN_FILE, - GDM_ID_SOUND_ON_LOGIN_SUCCESS_FILE, - GDM_ID_SOUND_ON_LOGIN_FAILURE_FILE, - GDM_ID_SOUND_PROGRAM, - GDM_ID_SCAN_TIME, - GDM_ID_DEFAULT_HOST_IMG, - GDM_ID_HOST_IMAGE_DIR, - GDM_ID_HOSTS, - GDM_ID_MULTICAST, - GDM_ID_MULTICAST_ADDR, - GDM_ID_BROADCAST, - GDM_ID_ALLOW_ADD, - GDM_ID_SECTION_GREETER, - GDM_ID_SECTION_SERVERS, - GDM_ID_SHOW_GNOME_FAILSAFE, - GDM_ID_SHOW_XTERM_FAILSAFE, - GDM_ID_SHOW_LAST_SESSION, - GDM_ID_SYSTEM_COMMANDS_IN_MENU, - GDM_ID_ALLOW_LOGOUT_ACTIONS, - GDM_ID_RBAC_SYSTEM_COMMAND_KEYS, - GDK_ID_LAST -} GdmConfigKey; - - -/* - * The following section contains keys used by the GDM configuration files. - * The key/value pairs defined in the GDM configuration files are considered - * "stable" interface and should only change in ways that are backwards - * compatible. Please keep this in mind when changing GDM configuration. - * - * Developers who add new configuration options should ensure that they do the - * following: - * - * + Add the key to config/gdm.conf.in file and specify the default value. - * Include comments explaining what the key does. - * - * + Add the key as a #define to daemon/gdm-daemon-config-keys.h with - * the same default value. - * - * + Update the GdmConfigKey enumeration and gdm_daemon_config_entries[] to - * add the new key. Include some documentation about the new key, - * following the style of existing comments. - * - * + Add any validation to the validate_cb function in - * gdm-daemon-config.c, if validation is needed. - * - * + If GDM_UPDATE_CONFIG should not respond to this configuration setting, - * update the gdm_daemon_config_update_key function in gdmconfig.c to - * return FALSE for this key. Examples include changing the ServAuthDir - * or other values that GDM should not change until it is restarted. If - * this is true, the next bullet can be ignored. - * - * + If the option should cause the greeter (gdmlogin/gdmgreeter) program to - * be updated immediately, update the notify_cb and lookup_notify_key - * functions to handle this key. - * - * + Add the key to the gdm_read_config and gdm_reread_config functions in - * gui/gdmlogin.c, gui/gdmchooser.c, and gui/greeter/greeter.c - * if the key is used by those programs. Note that all GDM slaves load - * all their configuration data between calls to gdmcomm_comm_bulk_start() - * and gdmcomm_comm_bulk_stop(). This makes sure that the slave only uses - * a single sockets connection to get all configuration data. If a new - * config value is read by a slave, make sure to load the key in this - * code section for best performance. - * - * + The gui/gdmsetup.c program should be updated to support the new option - * unless there's a good reason not to. - * - * + Currently GDM treats any key in the "gui" and "greeter" categories, - * and security/PamStack as available for per-display configuration. - * If a key is appropriate for per-display configuration, and is not - * in the "gui" or "greeter" categories, then it will need to be added - * to the gdm_config_key_to_string_per_display function. It may make - * sense for some keys used by the daemon to be per-display so this - * will need to be coded (refer to GDM_ID_PAM_STACK for an example). - * - * + Update the docs/C/gdm.xml file to include information about the new - * option. Include information about any other interfaces (such as - * ENVIRONMENT variables) that may affect the configuration option. - * Patches without documentation will not be accepted. - * - * Please do this work *before* submitting an patch. Patches that are not - * complete will not likely be accepted. - */ - -#define GDM_DEFAULT_WELCOME_MSG "Welcome" -#define GDM_DEFAULT_REMOTE_WELCOME_MSG "Welcome to %n" - -/* These are processed in order so debug should always be first */ -static const GdmConfigEntry gdm_daemon_config_entries [] = { - { GDM_CONFIG_GROUP_DEBUG, "Enable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_DEBUG }, - { GDM_CONFIG_GROUP_DEBUG, "Gestures", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_DEBUG_GESTURES }, - - - { GDM_CONFIG_GROUP_DAEMON, "Chooser", GDM_CONFIG_VALUE_STRING, LIBEXECDIR "/gdmchooser", GDM_ID_CHOOSER }, - { GDM_CONFIG_GROUP_DAEMON, "AutomaticLoginEnable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_AUTOMATIC_LOGIN_ENABLE }, - { GDM_CONFIG_GROUP_DAEMON, "AutomaticLogin", GDM_CONFIG_VALUE_STRING, "", GDM_ID_AUTOMATIC_LOGIN }, - - /* The SDTLOGIN feature is Solaris specific, and causes the Xserver to be - * run with user permissionsinstead of as root, which adds security but, - * disables the AlwaysRestartServer option as highlighted in the gdm - * documentation */ - - { GDM_CONFIG_GROUP_DAEMON, "Greeter", GDM_CONFIG_VALUE_STRING, LIBEXECDIR "/gdmlogin", GDM_ID_GREETER }, - { GDM_CONFIG_GROUP_DAEMON, "RemoteGreeter", GDM_CONFIG_VALUE_STRING, LIBEXECDIR "/gdmlogin", GDM_ID_REMOTE_GREETER }, - { GDM_CONFIG_GROUP_DAEMON, "AddGtkModules", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ADD_GTK_MODULES }, - { GDM_CONFIG_GROUP_DAEMON, "GtkModulesList", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_GTK_MODULES_LIST }, - - { GDM_CONFIG_GROUP_DAEMON, "User", GDM_CONFIG_VALUE_STRING, "gdm", GDM_ID_USER }, - { GDM_CONFIG_GROUP_DAEMON, "Group", GDM_CONFIG_VALUE_STRING, "gdm", GDM_ID_GROUP }, - - { GDM_CONFIG_GROUP_DAEMON, "HaltCommand", GDM_CONFIG_VALUE_STRING_ARRAY, HALT_COMMAND, GDM_ID_HALT }, - { GDM_CONFIG_GROUP_DAEMON, "RebootCommand", GDM_CONFIG_VALUE_STRING_ARRAY, REBOOT_COMMAND, GDM_ID_REBOOT }, - { GDM_CONFIG_GROUP_DAEMON, "SuspendCommand", GDM_CONFIG_VALUE_STRING_ARRAY, SUSPEND_COMMAND, GDM_ID_SUSPEND }, - - { GDM_CONFIG_GROUP_DAEMON, "DisplayInitDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/Init", GDM_ID_DISPLAY_INIT_DIR }, - { GDM_CONFIG_GROUP_DAEMON, "KillInitClients", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_KILL_INIT_CLIENTS }, - { GDM_CONFIG_GROUP_DAEMON, "LogDir", GDM_CONFIG_VALUE_STRING, LOGDIR, GDM_ID_LOG_DIR }, - { GDM_CONFIG_GROUP_DAEMON, "DefaultPath", GDM_CONFIG_VALUE_STRING, GDM_USER_PATH, GDM_ID_PATH }, - { GDM_CONFIG_GROUP_DAEMON, "PostSessionScriptDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/PostSession/", GDM_ID_POSTSESSION }, - { GDM_CONFIG_GROUP_DAEMON, "PreSessionScriptDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/PreSession/", GDM_ID_PRESESSION }, - { GDM_CONFIG_GROUP_DAEMON, "PostLoginScriptDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/PreSession/", GDM_ID_POSTLOGIN }, - { GDM_CONFIG_GROUP_DAEMON, "FailsafeXServer", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_FAILSAFE_XSERVER }, - { GDM_CONFIG_GROUP_DAEMON, "XKeepsCrashing", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/XKeepsCrashing", GDM_ID_X_KEEPS_CRASHING }, - { GDM_CONFIG_GROUP_DAEMON, "RootPath", GDM_CONFIG_VALUE_STRING, "/sbin:/usr/sbin:" GDM_USER_PATH, GDM_ID_ROOT_PATH }, - { GDM_CONFIG_GROUP_DAEMON, "ServAuthDir", GDM_CONFIG_VALUE_STRING, AUTHDIR, GDM_ID_SERV_AUTHDIR }, - { GDM_CONFIG_GROUP_DAEMON, "SessionDesktopDir", GDM_CONFIG_VALUE_STRING, "/etc/X11/sessions/:" DMCONFDIR "/Sessions/:" DATADIR "/gdm/BuiltInSessions/:" DATADIR "/xsessions/", GDM_ID_SESSION_DESKTOP_DIR }, - { GDM_CONFIG_GROUP_DAEMON, "BaseXsession", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/Xsession", GDM_ID_BASE_XSESSION }, - { GDM_CONFIG_GROUP_DAEMON, "DefaultSession", GDM_CONFIG_VALUE_STRING, "gnome.desktop", GDM_ID_DEFAULT_SESSION }, - - { GDM_CONFIG_GROUP_DAEMON, "UserAuthDir", GDM_CONFIG_VALUE_STRING, "", GDM_ID_USER_AUTHDIR }, - { GDM_CONFIG_GROUP_DAEMON, "UserAuthFBDir", GDM_CONFIG_VALUE_STRING, "/tmp", GDM_ID_USER_AUTHDIR_FALLBACK }, - { GDM_CONFIG_GROUP_DAEMON, "UserAuthFile", GDM_CONFIG_VALUE_STRING, ".Xauthority", GDM_ID_USER_AUTHFILE }, - { GDM_CONFIG_GROUP_DAEMON, "ConsoleNotify", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_CONSOLE_NOTIFY }, - - { GDM_CONFIG_GROUP_DAEMON, "DoubleLoginWarning", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_DOUBLE_LOGIN_WARNING }, - { GDM_CONFIG_GROUP_DAEMON, "AlwaysLoginCurrentSession", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALWAYS_LOGIN_CURRENT_SESSION }, - - { GDM_CONFIG_GROUP_DAEMON, "DisplayLastLogin", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_DISPLAY_LAST_LOGIN }, - - { GDM_CONFIG_GROUP_DAEMON, "TimedLoginEnable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_TIMED_LOGIN_ENABLE }, - { GDM_CONFIG_GROUP_DAEMON, "TimedLogin", GDM_CONFIG_VALUE_STRING, "", GDM_ID_TIMED_LOGIN }, - { GDM_CONFIG_GROUP_DAEMON, "TimedLoginDelay", GDM_CONFIG_VALUE_INT, "30", GDM_ID_TIMED_LOGIN_DELAY }, - - { GDM_CONFIG_GROUP_DAEMON, "FlexiReapDelayMinutes", GDM_CONFIG_VALUE_INT, "5", GDM_ID_FLEXI_REAP_DELAY_MINUTES }, - - { GDM_CONFIG_GROUP_DAEMON, "StandardXServer", GDM_CONFIG_VALUE_STRING, X_SERVER, GDM_ID_STANDARD_XSERVER }, - { GDM_CONFIG_GROUP_DAEMON, "FlexibleXServers", GDM_CONFIG_VALUE_INT, "5", GDM_ID_FLEXIBLE_XSERVERS }, - { GDM_CONFIG_GROUP_DAEMON, "DynamicXServers", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_DYNAMIC_XSERVERS }, - { GDM_CONFIG_GROUP_DAEMON, "Xnest", GDM_CONFIG_VALUE_STRING, X_XNEST_CMD ", " X_XNEST_CONFIG_OPTIONS, GDM_ID_XNEST }, - { GDM_CONFIG_GROUP_DAEMON, "XnestUnscaledFontPath", GDM_CONFIG_VALUE_BOOL, X_XNEST_UNSCALED_FONTPATH, GDM_ID_XNEST_UNSCALED_FONT_PATH }, - - /* Keys for automatic VT allocation rather then letting it up to the X server */ - { GDM_CONFIG_GROUP_DAEMON, "FirstVT", GDM_CONFIG_VALUE_INT, "7", GDM_ID_FIRST_VT }, - { GDM_CONFIG_GROUP_DAEMON, "VTAllocation", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_VT_ALLOCATION }, - - { GDM_CONFIG_GROUP_DAEMON, "ConsoleCannotHandle", GDM_CONFIG_VALUE_STRING, "am,ar,az,bn,el,fa,gu,hi,ja,ko,ml,mr,pa,ta,zh", GDM_ID_CONSOLE_CANNOT_HANDLE }, - - /* How long to wait before assuming an Xserver has timed out */ - { GDM_CONFIG_GROUP_DAEMON, "GdmXserverTimeout", GDM_CONFIG_VALUE_INT, "10", GDM_ID_XSERVER_TIMEOUT }, - - { GDM_CONFIG_GROUP_DAEMON, "SystemCommandsInMenu", GDM_CONFIG_VALUE_STRING_ARRAY, "HALT;REBOOT;SUSPEND;CUSTOM_CMD", GDM_ID_SYSTEM_COMMANDS_IN_MENU }, - { GDM_CONFIG_GROUP_DAEMON, "AllowLogoutActions", GDM_CONFIG_VALUE_STRING_ARRAY, "HALT;REBOOT;SUSPEND;CUSTOM_CMD", GDM_ID_ALLOW_LOGOUT_ACTIONS }, - { GDM_CONFIG_GROUP_DAEMON, "RBACSystemCommandKeys", GDM_CONFIG_VALUE_STRING_ARRAY, GDM_RBAC_SYSCMD_KEYS, GDM_ID_RBAC_SYSTEM_COMMAND_KEYS }, - - { GDM_CONFIG_GROUP_SECURITY, "AllowRoot", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALLOW_ROOT }, - { GDM_CONFIG_GROUP_SECURITY, "AllowRemoteRoot", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ALLOW_REMOTE_ROOT }, - { GDM_CONFIG_GROUP_SECURITY, "AllowRemoteAutoLogin", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ALLOW_REMOTE_AUTOLOGIN }, - { GDM_CONFIG_GROUP_SECURITY, "UserMaxFile", GDM_CONFIG_VALUE_INT, "65536", GDM_ID_USER_MAX_FILE }, - { GDM_CONFIG_GROUP_SECURITY, "RelaxPermissions", GDM_CONFIG_VALUE_INT, "0", GDM_ID_RELAX_PERM }, - { GDM_CONFIG_GROUP_SECURITY, "CheckDirOwner", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_CHECK_DIR_OWNER }, - { GDM_CONFIG_GROUP_SECURITY, "SupportAutomount", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SUPPORT_AUTOMOUNT }, - { GDM_CONFIG_GROUP_SECURITY, "RetryDelay", GDM_CONFIG_VALUE_INT, "1", GDM_ID_RETRY_DELAY }, - { GDM_CONFIG_GROUP_SECURITY, "DisallowTCP", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_DISALLOW_TCP }, - { GDM_CONFIG_GROUP_SECURITY, "PamStack", GDM_CONFIG_VALUE_STRING, "gdm", GDM_ID_PAM_STACK }, - - { GDM_CONFIG_GROUP_SECURITY, "NeverPlaceCookiesOnNFS", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_NEVER_PLACE_COOKIES_ON_NFS }, - { GDM_CONFIG_GROUP_SECURITY, "PasswordRequired", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_PASSWORD_REQUIRED }, - - { GDM_CONFIG_GROUP_XDMCP, "Enable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_XDMCP }, - { GDM_CONFIG_GROUP_XDMCP, "MaxPending", GDM_CONFIG_VALUE_INT, "4", GDM_ID_MAX_PENDING }, - { GDM_CONFIG_GROUP_XDMCP, "MaxSessions", GDM_CONFIG_VALUE_INT, "16", GDM_ID_MAX_SESSIONS }, - { GDM_CONFIG_GROUP_XDMCP, "MaxWait", GDM_CONFIG_VALUE_INT, "15", GDM_ID_MAX_WAIT }, - { GDM_CONFIG_GROUP_XDMCP, "DisplaysPerHost", GDM_CONFIG_VALUE_INT, "2", GDM_ID_DISPLAYS_PER_HOST }, - { GDM_CONFIG_GROUP_XDMCP, "Port", GDM_CONFIG_VALUE_INT, "177", GDM_ID_UDP_PORT }, - { GDM_CONFIG_GROUP_XDMCP, "HonorIndirect", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_INDIRECT }, - { GDM_CONFIG_GROUP_XDMCP, "MaxPendingIndirect", GDM_CONFIG_VALUE_INT, "4", GDM_ID_MAX_INDIRECT }, - { GDM_CONFIG_GROUP_XDMCP, "MaxWaitIndirect", GDM_CONFIG_VALUE_INT, "15", GDM_ID_MAX_WAIT_INDIRECT }, - { GDM_CONFIG_GROUP_XDMCP, "PingIntervalSeconds", GDM_CONFIG_VALUE_INT, "15", GDM_ID_PING_INTERVAL }, - { GDM_CONFIG_GROUP_XDMCP, "Willing", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/Xwilling", GDM_ID_WILLING }, - - { GDM_CONFIG_GROUP_XDMCP, "EnableProxy", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_XDMCP_PROXY }, - { GDM_CONFIG_GROUP_XDMCP, "ProxyXServer", GDM_CONFIG_VALUE_STRING, "", GDM_ID_XDMCP_PROXY_XSERVER }, - { GDM_CONFIG_GROUP_XDMCP, "ProxyReconnect", GDM_CONFIG_VALUE_STRING, "", GDM_ID_XDMCP_PROXY_RECONNECT }, - - { GDM_CONFIG_GROUP_GUI, "GtkTheme", GDM_CONFIG_VALUE_STRING, "Default", GDM_ID_GTK_THEME }, - { GDM_CONFIG_GROUP_GUI, "GtkRC", GDM_CONFIG_VALUE_STRING, DATADIR "/themes/Default/gtk-2.0/gtkrc", GDM_ID_GTKRC }, - { GDM_CONFIG_GROUP_GUI, "MaxIconWidth", GDM_CONFIG_VALUE_INT, "128", GDM_ID_MAX_ICON_WIDTH }, - { GDM_CONFIG_GROUP_GUI, "MaxIconHeight", GDM_CONFIG_VALUE_INT, "128", GDM_ID_MAX_ICON_HEIGHT }, - - { GDM_CONFIG_GROUP_GUI, "AllowGtkThemeChange", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALLOW_GTK_THEME_CHANGE }, - { GDM_CONFIG_GROUP_GUI, "GtkThemesToAllow", GDM_CONFIG_VALUE_STRING, "all", GDM_ID_GTK_THEMES_TO_ALLOW }, - - { GDM_CONFIG_GROUP_GREETER, "Browser", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_BROWSER }, - { GDM_CONFIG_GROUP_GREETER, "Include", GDM_CONFIG_VALUE_STRING, "", GDM_ID_INCLUDE }, - { GDM_CONFIG_GROUP_GREETER, "Exclude", GDM_CONFIG_VALUE_STRING, "bin,daemon,adm,lp,sync,shutdown,halt,mail,news,uucp,operator,nobody,gdm,postgres,pvm,rpm,nfsnobody,pcap", GDM_ID_EXCLUDE }, - { GDM_CONFIG_GROUP_GREETER, "IncludeAll", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_INCLUDE_ALL }, - { GDM_CONFIG_GROUP_GREETER, "MinimalUID", GDM_CONFIG_VALUE_INT, "100", GDM_ID_MINIMAL_UID }, - { GDM_CONFIG_GROUP_GREETER, "DefaultFace", GDM_CONFIG_VALUE_STRING, PIXMAPDIR "/nobody.png", GDM_ID_DEFAULT_FACE }, - { GDM_CONFIG_GROUP_GREETER, "GlobalFaceDir", GDM_CONFIG_VALUE_STRING, DATADIR "/pixmaps/faces/", GDM_ID_GLOBAL_FACE_DIR }, - { GDM_CONFIG_GROUP_GREETER, "LocaleFile", GDM_CONFIG_VALUE_STRING, GDMLOCALEDIR "/locale.alias", GDM_ID_LOCALE_FILE }, - { GDM_CONFIG_GROUP_GREETER, "Logo", GDM_CONFIG_VALUE_STRING, PIXMAPDIR "/gdm-foot-logo.png", GDM_ID_LOGO }, - { GDM_CONFIG_GROUP_GREETER, "ChooserButtonLogo", GDM_CONFIG_VALUE_STRING, PIXMAPDIR "/gdm-foot-logo.png", GDM_ID_CHOOSER_BUTTON_LOGO }, - { GDM_CONFIG_GROUP_GREETER, "Quiver", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_QUIVER }, - { GDM_CONFIG_GROUP_GREETER, "SystemMenu", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SYSTEM_MENU }, - { GDM_CONFIG_GROUP_DAEMON, "Configurator", GDM_CONFIG_VALUE_STRING, SBINDIR "/gdmsetup --disable-sound --disable-crash-dialog", GDM_ID_CONFIGURATOR }, - { GDM_CONFIG_GROUP_GREETER, "ConfigAvailable", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_CONFIG_AVAILABLE }, - { GDM_CONFIG_GROUP_GREETER, "ChooserButton", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_CHOOSER_BUTTON }, - { GDM_CONFIG_GROUP_GREETER, "TitleBar", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_TITLE_BAR }, - - /* - * For backwards compatibility, do not set values for DEFAULT_WELCOME or - * DEFAULT_REMOTEWELCOME. This will cause these values to always be - * read from the config file, and will cause them to return FALSE if - * no value is set in the config file. We want the value, "FALSE" if - * the values don't exist in the config file. The daemon will compare - * the Welcome/RemoveWelcome value with the default string and - * automatically translate the text if the string is the same as the - * default string. We set the default values of GDM_ID_WELCOME and - * GDM_ID_REMOTEWELCOME so that the default value is returned when - * you run GET_CONFIG on these keys. - */ - { GDM_CONFIG_GROUP_GREETER, "DefaultWelcome", GDM_CONFIG_VALUE_BOOL, "", GDM_ID_DEFAULT_WELCOME }, - { GDM_CONFIG_GROUP_GREETER, "DefaultRemoteWelcome", GDM_CONFIG_VALUE_BOOL, "", GDM_ID_DEFAULT_REMOTE_WELCOME }, - { GDM_CONFIG_GROUP_GREETER, "Welcome", GDM_CONFIG_VALUE_LOCALE_STRING, GDM_DEFAULT_WELCOME_MSG, GDM_ID_WELCOME }, - { GDM_CONFIG_GROUP_GREETER, "RemoteWelcome", GDM_CONFIG_VALUE_LOCALE_STRING, GDM_DEFAULT_REMOTE_WELCOME_MSG, GDM_ID_REMOTE_WELCOME }, - { GDM_CONFIG_GROUP_GREETER, "XineramaScreen", GDM_CONFIG_VALUE_INT, "0", GDM_ID_XINERAMA_SCREEN }, - { GDM_CONFIG_GROUP_GREETER, "BackgroundProgram", GDM_CONFIG_VALUE_STRING, "", GDM_ID_BACKGROUND_PROGRAM }, - { GDM_CONFIG_GROUP_GREETER, "RunBackgroundProgramAlways", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_RUN_BACKGROUND_PROGRAM_ALWAYS }, - { GDM_CONFIG_GROUP_GREETER, "BackgroundProgramInitialDelay", GDM_CONFIG_VALUE_INT, "30", GDM_ID_BACKGROUND_PROGRAM_INITIAL_DELAY }, - { GDM_CONFIG_GROUP_GREETER, "RestartBackgroundProgram", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_RESTART_BACKGROUND_PROGRAM }, - { GDM_CONFIG_GROUP_GREETER, "BackgroundProgramRestartDelay", GDM_CONFIG_VALUE_INT, "30", GDM_ID_BACKGROUND_PROGRAM_RESTART_DELAY }, - { GDM_CONFIG_GROUP_GREETER, "BackgroundImage", GDM_CONFIG_VALUE_STRING, "", GDM_ID_BACKGROUND_IMAGE }, - { GDM_CONFIG_GROUP_GREETER, "BackgroundColor", GDM_CONFIG_VALUE_STRING, "#76848F", GDM_ID_BACKGROUND_COLOR }, - { GDM_CONFIG_GROUP_GREETER, "BackgroundType", GDM_CONFIG_VALUE_INT, "2", GDM_ID_BACKGROUND_TYPE }, - { GDM_CONFIG_GROUP_GREETER, "BackgroundScaleToFit", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_BACKGROUND_SCALE_TO_FIT }, - { GDM_CONFIG_GROUP_GREETER, "BackgroundRemoteOnlyColor", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_BACKGROUND_REMOTE_ONLY_COLOR }, - { GDM_CONFIG_GROUP_GREETER, "LockPosition", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_LOCK_POSITION }, - { GDM_CONFIG_GROUP_GREETER, "SetPosition", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SET_POSITION }, - { GDM_CONFIG_GROUP_GREETER, "PositionX", GDM_CONFIG_VALUE_INT, "0", GDM_ID_POSITION_X }, - { GDM_CONFIG_GROUP_GREETER, "PositionY", GDM_CONFIG_VALUE_INT, "0", GDM_ID_POSITION_Y }, - { GDM_CONFIG_GROUP_GREETER, "Use24Clock", GDM_CONFIG_VALUE_STRING, "auto", GDM_ID_USE_24_CLOCK }, - { GDM_CONFIG_GROUP_GREETER, "UseCirclesInEntry", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ENTRY_CIRCLES }, - { GDM_CONFIG_GROUP_GREETER, "UseInvisibleInEntry", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ENTRY_INVISIBLE }, - { GDM_CONFIG_GROUP_GREETER, "GraphicalTheme", GDM_CONFIG_VALUE_STRING, "circles", GDM_ID_GRAPHICAL_THEME }, - { GDM_CONFIG_GROUP_GREETER, "GraphicalThemes", GDM_CONFIG_VALUE_STRING, "circles/:happygnome", GDM_ID_GRAPHICAL_THEMES }, - { GDM_CONFIG_GROUP_GREETER, "GraphicalThemeRand", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_GRAPHICAL_THEME_RAND }, - { GDM_CONFIG_GROUP_GREETER, "GraphicalThemeDir", GDM_CONFIG_VALUE_STRING, DATADIR "/gdm/themes/", GDM_ID_GRAPHICAL_THEME_DIR }, - { GDM_CONFIG_GROUP_GREETER, "GraphicalThemedColor", GDM_CONFIG_VALUE_STRING, "#76848F", GDM_ID_GRAPHICAL_THEMED_COLOR }, - - { GDM_CONFIG_GROUP_GREETER, "InfoMsgFile", GDM_CONFIG_VALUE_STRING, "", GDM_ID_INFO_MSG_FILE }, - { GDM_CONFIG_GROUP_GREETER, "InfoMsgFont", GDM_CONFIG_VALUE_STRING, "", GDM_ID_INFO_MSG_FONT }, - - { GDM_CONFIG_GROUP_GREETER, "PreFetchProgram", GDM_CONFIG_VALUE_STRING, "", GDM_ID_PRE_FETCH_PROGRAM }, - - { GDM_CONFIG_GROUP_GREETER, "SoundOnLogin", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SOUND_ON_LOGIN }, - { GDM_CONFIG_GROUP_GREETER, "SoundOnLoginSuccess", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SOUND_ON_LOGIN_SUCCESS }, - { GDM_CONFIG_GROUP_GREETER, "SoundOnLoginFailure", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SOUND_ON_LOGIN_FAILURE }, - { GDM_CONFIG_GROUP_GREETER, "SoundOnLoginFile", GDM_CONFIG_VALUE_STRING, "", GDM_ID_SOUND_ON_LOGIN_FILE }, - { GDM_CONFIG_GROUP_GREETER, "SoundOnLoginSuccessFile", GDM_CONFIG_VALUE_STRING, "", GDM_ID_SOUND_ON_LOGIN_SUCCESS_FILE }, - { GDM_CONFIG_GROUP_GREETER, "SoundOnLoginFailureFile", GDM_CONFIG_VALUE_STRING, "", GDM_ID_SOUND_ON_LOGIN_FAILURE_FILE }, - { GDM_CONFIG_GROUP_DAEMON, "SoundProgram", GDM_CONFIG_VALUE_STRING, SOUND_PROGRAM, GDM_ID_SOUND_PROGRAM }, - - { GDM_CONFIG_GROUP_CHOOSER, "ScanTime", GDM_CONFIG_VALUE_INT, "4", GDM_ID_SCAN_TIME }, - { GDM_CONFIG_GROUP_CHOOSER, "DefaultHostImg", GDM_CONFIG_VALUE_STRING, PIXMAPDIR "/nohost.png", GDM_ID_DEFAULT_HOST_IMG }, - { GDM_CONFIG_GROUP_CHOOSER, "HostImageDir", GDM_CONFIG_VALUE_STRING, DATADIR "/hosts/", GDM_ID_HOST_IMAGE_DIR }, - { GDM_CONFIG_GROUP_CHOOSER, "Hosts", GDM_CONFIG_VALUE_STRING, "", GDM_ID_HOSTS }, - { GDM_CONFIG_GROUP_CHOOSER, "Multicast", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_MULTICAST }, - { GDM_CONFIG_GROUP_CHOOSER, "MulticastAddr", GDM_CONFIG_VALUE_STRING, "ff02::1", GDM_ID_MULTICAST_ADDR }, - { GDM_CONFIG_GROUP_CHOOSER, "Broadcast", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_BROADCAST }, - { GDM_CONFIG_GROUP_CHOOSER, "AllowAdd", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALLOW_ADD }, - - { GDM_CONFIG_GROUP_GREETER, "ShowGnomeFailsafeSession", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SHOW_GNOME_FAILSAFE }, - { GDM_CONFIG_GROUP_GREETER, "ShowXtermFailsafeSession", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SHOW_XTERM_FAILSAFE }, - { GDM_CONFIG_GROUP_GREETER, "ShowLastSession", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SHOW_LAST_SESSION }, - - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand0", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel0", GDM_CONFIG_VALUE_STRING, "Custom_0", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel0", GDM_CONFIG_VALUE_STRING, "Execute custom command _0", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText0", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip0", GDM_CONFIG_VALUE_STRING, "Execute custom command 0", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart0", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent0", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand1", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel1", GDM_CONFIG_VALUE_STRING, "Custom_1", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel1", GDM_CONFIG_VALUE_STRING, "Execute custom command _1", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText1", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip1", GDM_CONFIG_VALUE_STRING, "Execute custom command 1", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart1", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent1", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand2", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel2", GDM_CONFIG_VALUE_STRING, "Custom_2", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel2", GDM_CONFIG_VALUE_STRING, "Execute custom command _2", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText2", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip2", GDM_CONFIG_VALUE_STRING, "Execute custom command 2", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart2", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent2", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand3", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel3", GDM_CONFIG_VALUE_STRING, "Custom_3", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel3", GDM_CONFIG_VALUE_STRING, "Execute custom command _3", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText3", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip3", GDM_CONFIG_VALUE_STRING, "Execute custom command 3", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart3", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent3", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand4", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel4", GDM_CONFIG_VALUE_STRING, "Custom_4", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel4", GDM_CONFIG_VALUE_STRING, "Execute custom command _4", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText4", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip4", GDM_CONFIG_VALUE_STRING, "Execute custom command 4", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart4", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent4", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand5", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel5", GDM_CONFIG_VALUE_STRING, "Custom_5", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel5", GDM_CONFIG_VALUE_STRING, "Execute custom command _5", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText5", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip5", GDM_CONFIG_VALUE_STRING, "Execute custom command 5", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart5", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent5", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand6", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel6", GDM_CONFIG_VALUE_STRING, "Custom_6", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel6", GDM_CONFIG_VALUE_STRING, "Execute custom command _6", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText6", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip6", GDM_CONFIG_VALUE_STRING, "Execute custom command 6", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart6", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent6", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand7", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel7", GDM_CONFIG_VALUE_STRING, "Custom_7", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel7", GDM_CONFIG_VALUE_STRING, "Execute custom command _7", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText7", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip7", GDM_CONFIG_VALUE_STRING, "Execute custom command 7", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart7", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent7", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand8", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel8", GDM_CONFIG_VALUE_STRING, "Custom_8", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel8", GDM_CONFIG_VALUE_STRING, "Execute custom command _8", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText8", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip8", GDM_CONFIG_VALUE_STRING, "Execute custom command 8", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart8", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent8", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand9", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel9", GDM_CONFIG_VALUE_STRING, "Custom_9", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel9", GDM_CONFIG_VALUE_STRING, "Execute custom command _9", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText9", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip9", GDM_CONFIG_VALUE_STRING, "Execute custom command 9", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart9", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - { GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent9", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE }, - - { NULL } -}; - -static const GdmConfigEntry gdm_daemon_server_config_entries [] = { - /* Per server definitions */ - { GDM_CONFIG_GROUP_NONE, "name", GDM_CONFIG_VALUE_STRING, "Standard server", GDM_ID_SERVER_NAME }, - { GDM_CONFIG_GROUP_NONE, "command", GDM_CONFIG_VALUE_STRING, X_SERVER, GDM_ID_SERVER_COMMAND }, - /* runnable as flexi server */ - { GDM_CONFIG_GROUP_NONE, "flexible", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SERVER_FLEXIBLE }, - /* choosable from the login screen */ - { GDM_CONFIG_GROUP_NONE, "choosable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SERVER_CHOOSABLE }, - /* Login is handled by gdm, otherwise it's a remote server */ - { GDM_CONFIG_GROUP_NONE, "handled", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SERVER_HANDLED }, - /* Instead of the greeter run the chooser */ - { GDM_CONFIG_GROUP_NONE, "chooser", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SERVER_CHOOSER }, - /* select a nice level to run the X server at */ - { GDM_CONFIG_GROUP_NONE, "priority", GDM_CONFIG_VALUE_INT, "0", GDM_ID_SERVER_PRIORITY }, -}; - -G_END_DECLS - -#endif /* _GDM_DAEMON_CONFIG_ENTRIES_H */ diff --git a/daemon/gdm-daemon-config-keys.h b/daemon/gdm-daemon-config-keys.h deleted file mode 100644 index c34b85cc..00000000 --- a/daemon/gdm-daemon-config-keys.h +++ /dev/null @@ -1,232 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _GDM_DAEMON_CONFIG_KEYS_H -#define _GDM_DAEMON_CONFIG_KEYS_H - -#include <glib.h> - -#include "gdm-config.h" - -G_BEGIN_DECLS - -/* BEGIN LEGACY KEYS */ -#define GDM_KEY_CHOOSER "daemon/Chooser=" LIBEXECDIR "/gdmchooser" -#define GDM_KEY_AUTOMATIC_LOGIN_ENABLE "daemon/AutomaticLoginEnable=false" -#define GDM_KEY_AUTOMATIC_LOGIN "daemon/AutomaticLogin=" -#define GDM_KEY_GREETER "daemon/Greeter=" LIBEXECDIR "/gdmlogin" -#define GDM_KEY_REMOTE_GREETER "daemon/RemoteGreeter=" LIBEXECDIR "/gdmlogin" -#define GDM_KEY_ADD_GTK_MODULES "daemon/AddGtkModules=false" -#define GDM_KEY_GTK_MODULES_LIST "daemon/GtkModulesList=" -#define GDM_KEY_GROUP "daemon/Group=gdm" -#define GDM_KEY_HALT "daemon/HaltCommand=" HALT_COMMAND -#define GDM_KEY_DISPLAY_INIT_DIR "daemon/DisplayInitDir=" GDMCONFDIR "/Init" -#define GDM_KEY_KILL_INIT_CLIENTS "daemon/KillInitClients=true" -#define GDM_KEY_LOG_DIR "daemon/LogDir=" LOGDIR -#define GDM_KEY_PATH "daemon/DefaultPath=" GDM_USER_PATH -#define GDM_KEY_PID_FILE "daemon/PidFile=" GDM_PID_FILE -#define GDM_KEY_POSTSESSION "daemon/PostSessionScriptDir=" GDMCONFDIR "/PostSession/" -#define GDM_KEY_PRESESSION "daemon/PreSessionScriptDir=" GDMCONFDIR "/PreSession/" -#define GDM_KEY_POSTLOGIN "daemon/PostLoginScriptDir=" GDMCONFDIR "/PreSession/" -#define GDM_KEY_FAILSAFE_XSERVER "daemon/FailsafeXServer=" -#define GDM_KEY_X_KEEPS_CRASHING "daemon/XKeepsCrashing=" GDMCONFDIR "/XKeepsCrashing" -#define GDM_KEY_REBOOT "daemon/RebootCommand=" REBOOT_COMMAND -#define GDM_KEY_CUSTOM_CMD_TEMPLATE "customcommand/CustomCommand" -#define GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE "customcommand/CustomCommandLabel" -#define GDM_KEY_CUSTOM_CMD_LR_LABEL_TEMPLATE "customcommand/CustomCommandLRLabel" -#define GDM_KEY_CUSTOM_CMD_TEXT_TEMPLATE "customcommand/CustomCommandText" -#define GDM_KEY_CUSTOM_CMD_TOOLTIP_TEMPLATE "customcommand/CustomCommandTooltip" -#define GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE "customcommand/CustomCommandNoRestart" -#define GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE "customcommand/CustomCommandIsPersistent" -#define GDM_KEY_ROOT_PATH "daemon/RootPath=/sbin:/usr/sbin:" GDM_USER_PATH -#define GDM_KEY_SERV_AUTHDIR "daemon/ServAuthDir=" AUTHDIR -#define GDM_KEY_SESSION_DESKTOP_DIR "daemon/SessionDesktopDir=/etc/X11/sessions/:" DMCONFDIR "/Sessions/:" DATADIR "/gdm/BuiltInSessions/:" DATADIR "/xsessions/" -#define GDM_KEY_BASE_XSESSION "daemon/BaseXsession=" GDMCONFDIR "/Xsession" -#define GDM_KEY_DEFAULT_SESSION "daemon/DefaultSession=gnome.desktop" -#define GDM_KEY_SUSPEND "daemon/SuspendCommand=" SUSPEND_COMMAND -#define GDM_KEY_USER_AUTHDIR "daemon/UserAuthDir=" -#define GDM_KEY_USER_AUTHDIR_FALLBACK "daemon/UserAuthFBDir=/tmp" -#define GDM_KEY_USER_AUTHFILE "daemon/UserAuthFile=.Xauthority" -#define GDM_KEY_USER "daemon/User=gdm" -#define GDM_KEY_CONSOLE_NOTIFY "daemon/ConsoleNotify=true" -#define GDM_KEY_DOUBLE_LOGIN_WARNING "daemon/DoubleLoginWarning=true" -#define GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION "daemon/AlwaysLoginCurrentSession=true" -#define GDM_KEY_DISPLAY_LAST_LOGIN "daemon/DisplayLastLogin=false" -#define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable=false" -#define GDM_KEY_TIMED_LOGIN "daemon/TimedLogin=" -#define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay=30" -#define GDM_KEY_FLEXI_REAP_DELAY_MINUTES "daemon/FlexiReapDelayMinutes=5" -#define GDM_KEY_STANDARD_XSERVER "daemon/StandardXServer=" X_SERVER -#define GDM_KEY_FLEXIBLE_XSERVERS "daemon/FlexibleXServers=5" -#define GDM_KEY_DYNAMIC_XSERVERS "daemon/DynamicXServers=false" -#define GDM_KEY_XNEST "daemon/Xnest=" X_XNEST_CMD " " X_XNEST_CONFIG_OPTIONS -#define GDM_KEY_XNEST_UNSCALED_FONT_PATH "daemon/XnestUnscaledFontPath=" X_XNEST_UNSCALED_FONTPATH -#define GDM_KEY_FIRST_VT "daemon/FirstVT=7" -#define GDM_KEY_VT_ALLOCATION "daemon/VTAllocation=true" -#define GDM_KEY_CONSOLE_CANNOT_HANDLE "daemon/ConsoleCannotHandle=am,ar,az,bn,el,fa,gu,hi,ja,ko,ml,mr,pa,ta,zh" -#define GDM_KEY_XSERVER_TIMEOUT "daemon/GdmXserverTimeout=10" -#define GDM_KEY_SYSTEM_COMMANDS_IN_MENU "daemon/SystemCommandsInMenu=HALT;REBOOT;SUSPEND;CUSTOM_CMD" -#define GDM_KEY_ALLOW_LOGOUT_ACTIONS "daemon/AllowLogoutActions=HALT;REBOOT;SUSPEND;CUSTOM_CMD" -#define GDM_KEY_RBAC_SYSTEM_COMMAND_KEYS "daemon/RBACSystemCommandKeys=" GDM_RBAC_SYSCMD_KEYS - -#define GDM_KEY_SERVER_PREFIX "server-" -#define GDM_KEY_SERVER_NAME "name=Standard server" -#define GDM_KEY_SERVER_COMMAND "command=" X_SERVER -#define GDM_KEY_SERVER_FLEXIBLE "flexible=true" -#define GDM_KEY_SERVER_CHOOSABLE "choosable=false" -#define GDM_KEY_SERVER_HANDLED "handled=true" -#define GDM_KEY_SERVER_CHOOSER "chooser=false" -#define GDM_KEY_SERVER_PRIORITY "priority=0" - -#define GDM_KEY_ALLOW_ROOT "security/AllowRoot=true" -#define GDM_KEY_ALLOW_REMOTE_ROOT "security/AllowRemoteRoot=false" -#define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin=false" -#define GDM_KEY_USER_MAX_FILE "security/UserMaxFile=65536" -#define GDM_KEY_RELAX_PERM "security/RelaxPermissions=0" -#define GDM_KEY_CHECK_DIR_OWNER "security/CheckDirOwner=true" -#define GDM_KEY_SUPPORT_AUTOMOUNT "security/SupportAutomount=false" -#define GDM_KEY_RETRY_DELAY "security/RetryDelay=1" -#define GDM_KEY_DISALLOW_TCP "security/DisallowTCP=true" -#define GDM_KEY_PAM_STACK "security/PamStack=gdm" -#define GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS "security/NeverPlaceCookiesOnNFS=true" -#define GDM_KEY_PASSWORD_REQUIRED "security/PasswordRequired=false" -#define GDM_KEY_XDMCP "xdmcp/Enable=false" -#define GDM_KEY_MAX_PENDING "xdmcp/MaxPending=4" -#define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions=16" -#define GDM_KEY_MAX_WAIT "xdmcp/MaxWait=15" -#define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost=2" -#define GDM_KEY_UDP_PORT "xdmcp/Port=177" -#define GDM_KEY_INDIRECT "xdmcp/HonorIndirect=true" -#define GDM_KEY_MAX_INDIRECT "xdmcp/MaxPendingIndirect=4" -#define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect=15" -#define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds=15" -#define GDM_KEY_WILLING "xdmcp/Willing=" GDMCONFDIR "/Xwilling" -#define GDM_KEY_XDMCP_PROXY "xdmcp/EnableProxy=false" -#define GDM_KEY_XDMCP_PROXY_XSERVER "xdmcp/ProxyXServer=" -#define GDM_KEY_XDMCP_PROXY_RECONNECT "xdmcp/ProxyReconnect=" -#define GDM_KEY_GTK_THEME "gui/GtkTheme=Default" -#define GDM_KEY_GTKRC "gui/GtkRC=" DATADIR "/themes/Default/gtk-2.0/gtkrc" -#define GDM_KEY_MAX_ICON_WIDTH "gui/MaxIconWidth=128" -#define GDM_KEY_MAX_ICON_HEIGHT "gui/MaxIconHeight=128" -#define GDM_KEY_ALLOW_GTK_THEME_CHANGE "gui/AllowGtkThemeChange=true" -#define GDM_KEY_GTK_THEMES_TO_ALLOW "gui/GtkThemesToAllow=all" -#define GDM_KEY_BROWSER "greeter/Browser=false" -#define GDM_KEY_INCLUDE "greeter/Include=" -#define GDM_KEY_EXCLUDE "greeter/Exclude=bin,daemon,adm,lp,sync,shutdown,halt,mail,news,uucp,operator,nobody,gdm,postgres,pvm,rpm,nfsnobody,pcap" -#define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll=false" -#define GDM_KEY_MINIMAL_UID "greeter/MinimalUID=100" -#define GDM_KEY_DEFAULT_FACE "greeter/DefaultFace=" PIXMAPDIR "/nobody.png" -#define GDM_KEY_GLOBAL_FACE_DIR "greeter/GlobalFaceDir=" DATADIR "/pixmaps/faces/" -#define GDM_KEY_LOCALE_FILE "greeter/LocaleFile=" GDMLOCALEDIR "/locale.alias" -#define GDM_KEY_LOGO "greeter/Logo=" PIXMAPDIR "/gdm-foot-logo.png" -#define GDM_KEY_CHOOSER_BUTTON_LOGO "greeter/ChooserButtonLogo=" PIXMAPDIR "/gdm-foot-logo.png" -#define GDM_KEY_QUIVER "greeter/Quiver=true" -#define GDM_KEY_SYSTEM_MENU "greeter/SystemMenu=true" -#define GDM_KEY_CONFIGURATOR "daemon/Configurator=" SBINDIR "/gdmsetup --disable-sound --disable-crash-dialog" -#define GDM_KEY_CONFIG_AVAILABLE "greeter/ConfigAvailable=true" -#define GDM_KEY_CHOOSER_BUTTON "greeter/ChooserButton=true" -#define GDM_KEY_TITLE_BAR "greeter/TitleBar=true" -#define GDM_DEFAULT_WELCOME_MSG "Welcome" -#define GDM_DEFAULT_REMOTE_WELCOME_MSG "Welcome to %n" -#define GDM_KEY_DEFAULT_WELCOME "greeter/DefaultWelcome=" -#define GDM_KEY_DEFAULT_REMOTE_WELCOME "greeter/DefaultRemoteWelcome=" -#define GDM_KEY_WELCOME "greeter/Welcome=" GDM_DEFAULT_WELCOME_MSG -#define GDM_KEY_REMOTE_WELCOME "greeter/RemoteWelcome=" GDM_DEFAULT_REMOTE_WELCOME_MSG -#define GDM_KEY_XINERAMA_SCREEN "greeter/XineramaScreen=0" -#define GDM_KEY_BACKGROUND_PROGRAM "greeter/BackgroundProgram=" -#define GDM_KEY_RUN_BACKGROUND_PROGRAM_ALWAYS "greeter/RunBackgroundProgramAlways=false" -#define GDM_KEY_BACKGROUND_PROGRAM_INITIAL_DELAY "greeter/BackgroundProgramInitialDelay=30" -#define GDM_KEY_RESTART_BACKGROUND_PROGRAM "greeter/RestartBackgroundProgram=true" -#define GDM_KEY_BACKGROUND_PROGRAM_RESTART_DELAY "greeter/BackgroundProgramRestartDelay=30" -#define GDM_KEY_BACKGROUND_IMAGE "greeter/BackgroundImage=" -#define GDM_KEY_BACKGROUND_COLOR "greeter/BackgroundColor=#76848F" -#define GDM_KEY_BACKGROUND_TYPE "greeter/BackgroundType=2" -#define GDM_KEY_BACKGROUND_SCALE_TO_FIT "greeter/BackgroundScaleToFit=true" -#define GDM_KEY_BACKGROUND_REMOTE_ONLY_COLOR "greeter/BackgroundRemoteOnlyColor=true" -#define GDM_KEY_LOCK_POSITION "greeter/LockPosition=false" -#define GDM_KEY_SET_POSITION "greeter/SetPosition=false" -#define GDM_KEY_POSITION_X "greeter/PositionX=0" -#define GDM_KEY_POSITION_Y "greeter/PositionY=0" -#define GDM_KEY_USE_24_CLOCK "greeter/Use24Clock=auto" -#define GDM_KEY_ENTRY_CIRCLES "greeter/UseCirclesInEntry=false" -#define GDM_KEY_ENTRY_INVISIBLE "greeter/UseInvisibleInEntry=false" -#define GDM_KEY_GRAPHICAL_THEME "greeter/GraphicalTheme=circles" -#define GDM_KEY_GRAPHICAL_THEMES "greeter/GraphicalThemes=circles/:happygnome" -#define GDM_KEY_GRAPHICAL_THEME_RAND "greeter/GraphicalThemeRand=false" -#define GDM_KEY_GRAPHICAL_THEME_DIR "greeter/GraphicalThemeDir=" DATADIR "/gdm/themes/" -#define GDM_KEY_GRAPHICAL_THEMED_COLOR "greeter/GraphicalThemedColor=#76848F" -#define GDM_KEY_INFO_MSG_FILE "greeter/InfoMsgFile=" -#define GDM_KEY_INFO_MSG_FONT "greeter/InfoMsgFont=" -#define GDM_KEY_PRE_FETCH_PROGRAM "greeter/PreFetchProgram=" -#define GDM_KEY_SOUND_ON_LOGIN "greeter/SoundOnLogin=true" -#define GDM_KEY_SOUND_ON_LOGIN_SUCCESS "greeter/SoundOnLoginSuccess=false" -#define GDM_KEY_SOUND_ON_LOGIN_FAILURE "greeter/SoundOnLoginFailure=false" -#define GDM_KEY_SOUND_ON_LOGIN_FILE "greeter/SoundOnLoginFile=" -#define GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE "greeter/SoundOnLoginSuccessFile=" -#define GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE "greeter/SoundOnLoginFailureFile=" -#define GDM_KEY_SOUND_PROGRAM "daemon/SoundProgram=" SOUND_PROGRAM -#define GDM_KEY_SCAN_TIME "chooser/ScanTime=4" -#define GDM_KEY_DEFAULT_HOST_IMG "chooser/DefaultHostImg=" PIXMAPDIR "/nohost.png" -#define GDM_KEY_HOST_IMAGE_DIR "chooser/HostImageDir=" DATADIR "/hosts/" -#define GDM_KEY_HOSTS "chooser/Hosts=" -#define GDM_KEY_MULTICAST "chooser/Multicast=false" -#define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr=ff02::1" -#define GDM_KEY_BROADCAST "chooser/Broadcast=true" -#define GDM_KEY_ALLOW_ADD "chooser/AllowAdd=true" -#define GDM_KEY_DEBUG "debug/Enable=false" -#define GDM_KEY_DEBUG_GESTURES "debug/Gestures=false" -#define GDM_KEY_SECTION_GREETER "greeter" -#define GDM_KEY_SECTION_SERVERS "servers" -#define GDM_KEY_SHOW_GNOME_FAILSAFE "greeter/ShowGnomeFailsafeSession=true" -#define GDM_KEY_SHOW_XTERM_FAILSAFE "greeter/ShowXtermFailsafeSession=true" -#define GDM_KEY_SHOW_LAST_SESSION "greeter/ShowLastSession=true" -/* END LEGACY KEYS */ - -/* Notification protocol */ -/* keys */ -#define GDM_NOTIFY_ALLOW_REMOTE_ROOT "AllowRemoteRoot" /* <true/false as int> */ -#define GDM_NOTIFY_ALLOW_ROOT "AllowRoot" /* <true/false as int> */ -#define GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN "AllowRemoteAutoLogin" /* <true/false as int> */ -#define GDM_NOTIFY_SYSTEM_MENU "SystemMenu" /* <true/false as int> */ -#define GDM_NOTIFY_CONFIG_AVAILABLE "ConfigAvailable" /* <true/false as int> */ -#define GDM_NOTIFY_CHOOSER_BUTTON "ChooserButton" /* <true/false as int> */ -#define GDM_NOTIFY_RETRY_DELAY "RetryDelay" /* <seconds> */ -#define GDM_NOTIFY_GREETER "Greeter" /* <greeter binary> */ -#define GDM_NOTIFY_REMOTE_GREETER "RemoteGreeter" /* <greeter binary> */ -#define GDM_NOTIFY_TIMED_LOGIN "TimedLogin" /* <login> */ -#define GDM_NOTIFY_TIMED_LOGIN_DELAY "TimedLoginDelay" /* <seconds> */ -#define GDM_NOTIFY_TIMED_LOGIN_ENABLE "TimedLoginEnable" /* <true/false as int> */ -#define GDM_NOTIFY_DISALLOW_TCP "DisallowTCP" /* <true/false as int> */ -#define GDM_NOTIFY_SOUND_ON_LOGIN_FILE "SoundOnLoginFile" /* <sound file> */ -#define GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE "SoundOnLoginSuccessFile" /* <sound file> */ -#define GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE "SoundOnLoginFailureFile" /* <sound file> */ -#define GDM_NOTIFY_ADD_GTK_MODULES "AddGtkModules" /* <true/false as int> */ -#define GDM_NOTIFY_GTK_MODULES_LIST "GtkModulesList" /* <modules list> */ -#define GDM_NOTIFY_CUSTOM_CMD_TEMPLATE "CustomCommand" /* <custom command path> */ - -/* commands, seel GDM_SLAVE_NOTIFY_COMMAND */ -#define GDM_NOTIFY_DIRTY_SERVERS "DIRTY_SERVERS" -#define GDM_NOTIFY_SOFT_RESTART_SERVERS "SOFT_RESTART_SERVERS" -#define GDM_NOTIFY_GO "GO" -#define GDM_NOTIFY_TWIDDLE_POINTER "TWIDDLE_POINTER" - -G_END_DECLS - -#endif /* _GDM_DAEMON_CONFIG_KEYS_H */ diff --git a/daemon/gdm-daemon-config.c b/daemon/gdm-daemon-config.c deleted file mode 100644 index 3e749994..00000000 --- a/daemon/gdm-daemon-config.c +++ /dev/null @@ -1,2816 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * Copyright (C) 2005 Brian Cameron <brian.cameron@sun.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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * gdm-daemon-config.c isolates most logic that interacts with GDM - * configuration into a single file and provides a mechanism for - * interacting with GDM configuration optins via access functions for - * getting/setting values. This logic also ensures that the same - * configuration validation happens when loading the values initially - * or setting them via the GDM_UPDATE_CONFIG socket command. - * - * When adding a new configuration option, simply add the new option - * to gdm-daemon-config-entries.h. Any validation for the - * configuration option should be placed in the validate_cb function. - */ - -#include "config.h" - -#include <stdlib.h> -#include <unistd.h> -#include <ctype.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/resource.h> -#include <sys/stat.h> -#include <sys/resource.h> -#include <signal.h> -#include <pwd.h> -#include <grp.h> - -#include <glib.h> -#include <glib/gi18n.h> - -#include "gdm.h" -#include "verify.h" -#include "gdm-net.h" -#include "misc.h" -#include "server.h" -#include "filecheck.h" -#include "slave.h" - -#include "gdm-common.h" -#include "gdm-config.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -#include "gdm-socket-protocol.h" - -static GdmConfig *daemon_config = NULL; - -static GSList *displays = NULL; -static GSList *xservers = NULL; - -static gint high_display_num = 0; -static char *custom_config_file = NULL; - -static uid_t GdmUserId; /* Userid under which gdm should run */ -static gid_t GdmGroupId; /* Gruopid under which gdm should run */ - -/** - * is_key - * - * Since GDM keys sometimes have default values defined in the gdm.h header - * file (e.g. key=value), this function strips off the "=value" from both - * keys passed and compares them, returning TRUE if they are the same, - * FALSE otherwise. - */ -static gboolean -is_key (const gchar *key1, const gchar *key2) -{ - gchar *key1d, *key2d, *p; - - key1d = g_strdup (key1); - key2d = g_strdup (key2); - - g_strstrip (key1d); - p = strchr (key1d, '='); - if (p != NULL) - *p = '\0'; - - g_strstrip (key2d); - p = strchr (key2d, '='); - if (p != NULL) - *p = '\0'; - - if (strcmp (ve_sure_string (key1d), ve_sure_string (key2d)) == 0) { - g_free (key1d); - g_free (key2d); - return TRUE; - } else { - g_free (key1d); - g_free (key2d); - return FALSE; - } -} - -/** - * gdm_daemon_config_get_per_display_custom_config_file - * - * Returns the per-display config file for a given display - * This is always the custom config file name with the display - * appended, and never gdm.conf. - */ -static gchar * -gdm_daemon_config_get_per_display_custom_config_file (const gchar *display) -{ - return g_strdup_printf ("%s%s", custom_config_file, display); -} - -/** - * gdm_daemon_config_get_custom_config_file - * - * Returns the custom config file being used. - */ -gchar * -gdm_daemon_config_get_custom_config_file (void) -{ - return custom_config_file; -} - -/** - * gdm_daemon_config_get_display_list - * - * Returns the list of displays being used. - */ -GSList * -gdm_daemon_config_get_display_list (void) -{ - return displays; -} - -GSList * -gdm_daemon_config_display_list_append (GdmDisplay *display) -{ - displays = g_slist_append (displays, display); - return displays; -} - -GSList * -gdm_daemon_config_display_list_insert (GdmDisplay *display) -{ - displays = g_slist_insert_sorted (displays, - display, - gdm_daemon_config_compare_displays); - return displays; -} - -GSList * -gdm_daemon_config_display_list_remove (GdmDisplay *display) -{ - displays = g_slist_remove (displays, display); - - return displays; -} - -/** - * gdm_daemon_config_get_value_int - * - * Gets an integer configuration option by key. The option must - * first be loaded, say, by calling gdm_config_parse. - */ -gint -gdm_daemon_config_get_value_int (const char *keystring) -{ - gboolean res; - GdmConfigValue *value; - char *group; - char *key; - int result; - - result = 0; - - res = gdm_common_config_parse_key_string (keystring, - &group, - &key, - NULL, - NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - goto out; - } - - res = gdm_config_get_value (daemon_config, - group, - key, - &value); - if (! res) { - gdm_error ("Request for invalid configuration key %s", keystring); - goto out; - } - - if (value->type != GDM_CONFIG_VALUE_INT) { - gdm_error ("Request for configuration key %s, but not type INT", keystring); - goto out; - } - - result = gdm_config_value_get_int (value); - out: - g_free (group); - g_free (key); - - return result; -} - -/** - * gdm_daemon_config_get_value_string - * - * Gets a string configuration option by key. The option must - * first be loaded, say, by calling gdm_daemon_config_parse. - */ -const char * -gdm_daemon_config_get_value_string (const char *keystring) -{ - gboolean res; - GdmConfigValue *value; - char *group; - char *key; - const char *result; - - result = NULL; - - res = gdm_common_config_parse_key_string (keystring, - &group, - &key, - NULL, - NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - goto out; - } - - res = gdm_config_get_value (daemon_config, - group, - key, - &value); - if (! res) { - gdm_error ("Request for invalid configuration key %s", keystring); - goto out; - } - - if (value->type != GDM_CONFIG_VALUE_STRING) { - gdm_error ("Request for configuration key %s, but not type STRING", keystring); - goto out; - } - - result = gdm_config_value_get_string (value); - out: - g_free (group); - g_free (key); - - return result; -} - -/** - * gdm_daemon_config_get_value_string_array - * - * Gets a string configuration option by key. The option must - * first be loaded, say, by calling gdm_daemon_config_parse. - */ -const char ** -gdm_daemon_config_get_value_string_array (const char *keystring) -{ - gboolean res; - GdmConfigValue *value; - char *group; - char *key; - const char **result; - - result = NULL; - - res = gdm_common_config_parse_key_string (keystring, - &group, - &key, - NULL, - NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - goto out; - } - - res = gdm_config_get_value (daemon_config, - group, - key, - &value); - if (! res) { - gdm_error ("Request for invalid configuration key %s", keystring); - goto out; - } - - if (value->type != GDM_CONFIG_VALUE_STRING_ARRAY) { - gdm_error ("Request for configuration key %s, but not type STRING-ARRAY", keystring); - goto out; - } - - result = gdm_config_value_get_string_array (value); - out: - g_free (group); - g_free (key); - - return result; -} - -/** - * gdm_daemon_config_get_bool_for_id - * - * Gets a boolean configuration option by ID. The option must - * first be loaded, say, by calling gdm_daemon_config_parse. - */ -gboolean -gdm_daemon_config_get_bool_for_id (int id) -{ - gboolean val; - - val = FALSE; - gdm_config_get_bool_for_id (daemon_config, id, &val); - - return val; -} - -/** - * gdm_daemon_config_get_int_for_id - * - * Gets a integer configuration option by ID. The option must - * first be loaded, say, by calling gdm_daemon_config_parse. - */ -int -gdm_daemon_config_get_int_for_id (int id) -{ - int val; - - val = -1; - gdm_config_get_int_for_id (daemon_config, id, &val); - - return val; -} - -/** - * gdm_daemon_config_get_string_for_id - * - * Gets a string configuration option by ID. The option must - * first be loaded, say, by calling gdm_daemon_config_parse. - */ -const char * -gdm_daemon_config_get_string_for_id (int id) -{ - const char *val; - - val = NULL; - gdm_config_peek_string_for_id (daemon_config, id, &val); - - return val; -} - -/** - * gdm_daemon_config_get_value_bool - * - * Gets a boolean configuration option by key. The option must - * first be loaded, say, by calling gdm_daemon_config_parse. - */ -gboolean -gdm_daemon_config_get_value_bool (const char *keystring) -{ - gboolean res; - GdmConfigValue *value; - char *group; - char *key; - gboolean result; - - result = FALSE; - - res = gdm_common_config_parse_key_string (keystring, - &group, - &key, - NULL, - NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - goto out; - } - - res = gdm_config_get_value (daemon_config, - group, - key, - &value); - if (! res) { - gdm_error ("Request for invalid configuration key %s", keystring); - goto out; - } - - if (value->type != GDM_CONFIG_VALUE_BOOL) { - gdm_error ("Request for configuration key %s, but not type BOOLEAN", keystring); - goto out; - } - - result = gdm_config_value_get_bool (value); - out: - g_free (group); - g_free (key); - - return result; -} - -/** - * Note that some GUI configuration parameters are read by the daemon, - * and in order for them to work, it is necessary for the daemon to - * access a few keys in a per-display fashion. These access functions - * allow the daemon to access these keys properly. - */ - -/** - * gdm_daemon_config_get_value_int_per_display - * - * Gets the per-display version of the configuration, or the default - * value if none exists. - */ -int -gdm_daemon_config_get_value_int_per_display (const char *key, - const char *display) -{ - char *perdispval; - gboolean res; - - res = gdm_daemon_config_key_to_string_per_display (key, display, &perdispval); - - if (res) { - int val; - val = atoi (perdispval); - g_free (perdispval); - return val; - } else { - return gdm_daemon_config_get_value_int (key); - } -} - -/** - * gdm_daemon_config_get_value_bool_per_display - * - * Gets the per-display version of the configuration, or the default - * value if none exists. - */ -gboolean -gdm_daemon_config_get_value_bool_per_display (const char *key, - const char *display) -{ - char *perdispval; - gboolean res; - - res = gdm_daemon_config_key_to_string_per_display (key, display, &perdispval); - - if (res) { - if (perdispval[0] == 'T' || - perdispval[0] == 't' || - perdispval[0] == 'Y' || - perdispval[0] == 'y' || - atoi (perdispval) != 0) { - g_free (perdispval); - return TRUE; - } else { - return FALSE; - } - } else { - return gdm_daemon_config_get_value_bool (key); - } -} - -/** - * gdm_daemon_config_get_value_string_per_display - * - * Gets the per-display version of the configuration, or the default - * value if none exists. Note that this value needs to be freed, - * unlike the non-per-display version. - */ -char * -gdm_daemon_config_get_value_string_per_display (const char *key, - const char *display) -{ - char *perdispval; - gboolean res; - - res = gdm_daemon_config_key_to_string_per_display (key, display, &perdispval); - - if (res) { - return perdispval; - } else { - return g_strdup (gdm_daemon_config_get_value_string (key)); - } -} - -/** - * gdm_daemon_config_key_to_string_per_display - * - * If the key makes sense to be per-display, return the value, - * otherwise return NULL. Keys that only apply to the daemon - * process do not make sense for per-display configuration - * Valid keys include any key in the greeter or gui categories, - * and the GDM_KEY_PAM_STACK key. - * - * If additional keys make sense for per-display usage, make - * sure they are added to the if-test below. - */ -gboolean -gdm_daemon_config_key_to_string_per_display (const char *keystring, - const char *display, - char **retval) -{ - char *file; - char *group; - char *key; - gboolean res; - gboolean ret; - - ret = FALSE; - - *retval = NULL; - group = key = NULL; - - if (display == NULL) { - goto out; - } - - g_debug ("Looking up per display value for %s", keystring); - - res = gdm_common_config_parse_key_string (keystring, - &group, - &key, - NULL, - NULL); - if (! res) { - goto out; - } - - file = gdm_daemon_config_get_per_display_custom_config_file (display); - - if (strcmp (group, "greeter") == 0 || - strcmp (group, "gui") == 0 || - is_key (keystring, GDM_KEY_PAM_STACK)) { - ret = gdm_daemon_config_key_to_string (file, keystring, retval); - } - - g_free (file); - - out: - g_free (group); - g_free (key); - - return ret; -} - -/** - * gdm_daemon_config_key_to_string - * - * Gets a specific key from the config file. - * Note this returns the value in string form, so the caller needs - * to parse it properly if it is a bool or int. - * - * Returns TRUE if successful.. - */ -gboolean -gdm_daemon_config_key_to_string (const char *file, - const char *keystring, - char **retval) -{ - GKeyFile *config; - GdmConfigValueType type; - gboolean res; - gboolean ret; - char *group; - char *key; - char *locale; - char *result; - const GdmConfigEntry *entry; - - if (retval != NULL) { - *retval = NULL; - } - - ret = FALSE; - result = NULL; - - group = key = locale = NULL; - res = gdm_common_config_parse_key_string (keystring, - &group, - &key, - &locale, - NULL); - g_debug ("Requesting group=%s key=%s locale=%s", group, key, locale ? locale : "(null)"); - - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - goto out; - } - - entry = gdm_config_lookup_entry (daemon_config, group, key); - if (entry == NULL) { - gdm_error ("Request for invalid configuration key %s", keystring); - goto out; - } - type = entry->type; - - config = gdm_common_config_load (file, NULL); - /* If file doesn't exist, then just return */ - if (config == NULL) { - goto out; - } - - gdm_debug ("Returning value for key <%s>\n", keystring); - - switch (type) { - case GDM_CONFIG_VALUE_BOOL: - { - gboolean value; - res = gdm_common_config_get_boolean (config, keystring, &value, NULL); - if (res) { - if (value) { - result = g_strdup ("true"); - } else { - result = g_strdup ("false"); - } - } - } - break; - case GDM_CONFIG_VALUE_INT: - { - int value; - res = gdm_common_config_get_int (config, keystring, &value, NULL); - if (res) { - result = g_strdup_printf ("%d", value); - } - } - break; - case GDM_CONFIG_VALUE_STRING: - { - char *value; - res = gdm_common_config_get_string (config, keystring, &value, NULL); - if (res) { - result = value; - } - } - break; - case GDM_CONFIG_VALUE_LOCALE_STRING: - { - char *value; - res = gdm_common_config_get_string (config, keystring, &value, NULL); - if (res) { - result = value; - } - } - break; - default: - break; - } - - if (res) { - if (retval != NULL) { - *retval = g_strdup (result); - } - ret = TRUE; - } - - g_key_file_free (config); - out: - g_free (result); - g_free (group); - g_free (key); - g_free (locale); - - return ret; -} - -/** - * gdm_daemon_config_to_string - * - * Returns a configuration option as a string. Used by GDM's - * GET_CONFIG socket command. - */ -gboolean -gdm_daemon_config_to_string (const char *keystring, - const char *display, - char **retval) -{ - gboolean res; - gboolean ret; - GdmConfigValue *value; - char *group; - char *key; - char *locale; - char *result; - - /* - * See if there is a per-display config file, returning that value - * if it exists. - */ - if (display != NULL) { - res = gdm_daemon_config_key_to_string_per_display (keystring, display, retval); - if (res) { - g_debug ("Using per display value for key: %s", keystring); - return TRUE; - } - } - - ret = FALSE; - result = NULL; - - g_debug ("Looking up key: %s", keystring); - - group = NULL; - key = NULL; - locale = NULL; - res = gdm_common_config_parse_key_string (keystring, - &group, - &key, - &locale, - NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - goto out; - } - - if (group == NULL || key == NULL) { - gdm_error ("Request for invalid configuration key %s", keystring); - goto out; - } - - /* Backward Compatibility */ - if ((strcmp (group, "daemon") == 0) && - (strcmp (key, "PidFile") == 0)) { - result = g_strdup (GDM_PID_FILE); - goto out; - } else if ((strcmp (group, "daemon") == 0) && - (strcmp (key, "AlwaysRestartServer") == 0)) { - result = g_strdup ("true"); - } - - res = gdm_config_get_value (daemon_config, - group, - key, - &value); - - if (! res) { - gdm_error ("Request for invalid configuration key %s", keystring); - goto out; - } - - result = gdm_config_value_to_string (value); - ret = TRUE; - - out: - g_free (group); - g_free (key); - g_free (locale); - - - *retval = result; - - return ret; -} - -/** - * gdm_daemon_config_compare_displays - * - * Support function for loading displays from the configuration - * file - */ -int -gdm_daemon_config_compare_displays (gconstpointer a, gconstpointer b) -{ - const GdmDisplay *d1 = a; - const GdmDisplay *d2 = b; - if (d1->dispnum < d2->dispnum) - return -1; - else if (d1->dispnum > d2->dispnum) - return 1; - else - return 0; -} - -static char * -lookup_notify_key (GdmConfig *config, - const char *group, - const char *key) -{ - char *nkey; - char *keystring; - - keystring = g_strdup_printf ("%s/%s", group, key); - - /* pretty lame but oh well */ - nkey = NULL; - - /* bools */ - if (is_key (keystring, GDM_KEY_ALLOW_ROOT)) - nkey = g_strdup (GDM_NOTIFY_ALLOW_ROOT); - else if (is_key (keystring, GDM_KEY_ALLOW_REMOTE_ROOT)) - nkey = g_strdup (GDM_NOTIFY_ALLOW_REMOTE_ROOT); - else if (is_key (keystring, GDM_KEY_ALLOW_REMOTE_AUTOLOGIN)) - nkey = g_strdup (GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN); - else if (is_key (keystring, GDM_KEY_SYSTEM_MENU)) - nkey = g_strdup (GDM_NOTIFY_SYSTEM_MENU); - else if (is_key (keystring, GDM_KEY_CONFIG_AVAILABLE)) - nkey = g_strdup (GDM_NOTIFY_CONFIG_AVAILABLE); - else if (is_key (keystring, GDM_KEY_CHOOSER_BUTTON)) - nkey = g_strdup (GDM_NOTIFY_CHOOSER_BUTTON); - else if (is_key (keystring, GDM_KEY_DISALLOW_TCP)) - nkey = g_strdup (GDM_NOTIFY_DISALLOW_TCP); - else if (is_key (keystring, GDM_KEY_ADD_GTK_MODULES)) - nkey = g_strdup (GDM_NOTIFY_ADD_GTK_MODULES); - else if (is_key (keystring, GDM_KEY_TIMED_LOGIN_ENABLE)) - nkey = g_strdup (GDM_NOTIFY_TIMED_LOGIN_ENABLE); - /* ints */ - else if (is_key (keystring, GDM_KEY_RETRY_DELAY)) - nkey = g_strdup (GDM_NOTIFY_RETRY_DELAY); - else if (is_key (keystring, GDM_KEY_TIMED_LOGIN_DELAY)) - nkey = g_strdup (GDM_NOTIFY_TIMED_LOGIN_DELAY); - /* strings */ - else if (is_key (keystring, GDM_KEY_GREETER)) - nkey = g_strdup (GDM_NOTIFY_GREETER); - else if (is_key (keystring, GDM_KEY_REMOTE_GREETER)) - nkey = g_strdup (GDM_NOTIFY_REMOTE_GREETER); - else if (is_key (keystring, GDM_KEY_SOUND_ON_LOGIN_FILE)) - nkey = g_strdup (GDM_NOTIFY_SOUND_ON_LOGIN_FILE); - else if (is_key (keystring, GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE)) - nkey = g_strdup (GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE); - else if (is_key (keystring, GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE)) - nkey = g_strdup (GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE); - else if (is_key (keystring, GDM_KEY_GTK_MODULES_LIST)) - nkey = g_strdup (GDM_NOTIFY_GTK_MODULES_LIST); - else if (is_key (keystring, GDM_KEY_TIMED_LOGIN)) - nkey = g_strdup (GDM_NOTIFY_TIMED_LOGIN); - else if (strcmp (group, GDM_CONFIG_GROUP_CUSTOM_CMD) == 0 && - g_str_has_prefix (key, "CustomCommand") && - strlen (key) == 14) { - /* this should match 'CustomCommandN' */ - nkey = g_strdup (key); - } - g_free (keystring); - - return nkey; -} - -/** - * notify_displays_value - * - * This will notify the slave programs - * (gdmgreeter, gdmlogin, etc.) that a configuration option has - * been changed so the slave can update with the new option - * value. GDM does this notify when it receives a - * GDM_CONFIG_UPDATE socket command from gdmsetup or from the - * gdmflexiserver --command option. - */ -static void -notify_displays_value (GdmConfig *config, - const char *group, - const char *key, - GdmConfigValue *value) -{ - GSList *li; - char *valstr; - char *keystr; - - keystr = lookup_notify_key (config, group, key); - - /* unfortunately, can't always gdm_config_value_to_string() - * here because booleans need to be sent as ints - */ - switch (value->type) { - case GDM_CONFIG_VALUE_BOOL: - if (gdm_config_value_get_bool (value)) { - valstr = g_strdup ("1"); - } else { - valstr = g_strdup ("0"); - } - break; - default: - valstr = gdm_config_value_to_string (value); - break; - } - - if (valstr == NULL) { - valstr = g_strdup (" "); - } - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - - if (disp->master_notify_fd < 0) { - /* no point */ - continue; - } - - gdm_fdprintf (disp->master_notify_fd, - "%c%s %s\n", - GDM_SLAVE_NOTIFY_KEY, - keystr, - valstr); - - if (disp != NULL && disp->slavepid > 1) { - kill (disp->slavepid, SIGUSR2); - } - } - - g_free (keystr); - g_free (valstr); -} - -/* The following were used to internally set the - * stored configuration values. Now we'll just - * ask the GdmConfig to store the entry. */ -void -gdm_daemon_config_set_value_string (const gchar *keystring, - const gchar *value_in) -{ - char *group; - char *key; - gboolean res; - GdmConfigValue *value; - - res = gdm_common_config_parse_key_string (keystring, &group, &key, NULL, NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - return; - } - - value = gdm_config_value_new (GDM_CONFIG_VALUE_STRING); - gdm_config_value_set_string (value, value_in); - - res = gdm_config_set_value (daemon_config, group, key, value); - - gdm_config_value_free (value); - g_free (group); - g_free (key); -} - -void -gdm_daemon_config_set_value_bool (const gchar *keystring, - gboolean value_in) -{ - char *group; - char *key; - gboolean res; - GdmConfigValue *value; - - res = gdm_common_config_parse_key_string (keystring, &group, &key, NULL, NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - return; - } - - value = gdm_config_value_new (GDM_CONFIG_VALUE_BOOL); - gdm_config_value_set_bool (value, value_in); - - res = gdm_config_set_value (daemon_config, group, key, value); - - gdm_config_value_free (value); - g_free (group); - g_free (key); -} - -void -gdm_daemon_config_set_value_int (const gchar *keystring, - gint value_in) -{ - char *group; - char *key; - gboolean res; - GdmConfigValue *value; - - res = gdm_common_config_parse_key_string (keystring, &group, &key, NULL, NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - return; - } - - value = gdm_config_value_new (GDM_CONFIG_VALUE_INT); - gdm_config_value_set_int (value, value_in); - - res = gdm_config_set_value (daemon_config, group, key, value); - - gdm_config_value_free (value); - g_free (group); - g_free (key); -} - -/** - * gdm_daemon_config_find_xserver - * - * Return an xserver with a given ID, or NULL if not found. - */ -GdmXserver * -gdm_daemon_config_find_xserver (const gchar *id) -{ - GSList *li; - - if (xservers == NULL) - return NULL; - - if (id == NULL) - return xservers->data; - - for (li = xservers; li != NULL; li = li->next) { - GdmXserver *svr = li->data; - if (strcmp (ve_sure_string (svr->id), ve_sure_string (id)) == 0) - return svr; - } - - return NULL; -} - -/** - * gdm_daemon_config_get_xservers - * - * Prepare a string to be returned for the GET_SERVER_LIST - * sockets command. - */ -gchar * -gdm_daemon_config_get_xservers (void) -{ - GSList *li; - gchar *retval = NULL; - - if (xservers == NULL) - return NULL; - - for (li = xservers; li != NULL; li = li->next) { - GdmXserver *svr = li->data; - if (retval != NULL) - retval = g_strconcat (retval, ";", svr->id, NULL); - else - retval = g_strdup (svr->id); - } - - return retval; -} - -/* PRIO_MIN and PRIO_MAX are not defined on Solaris, but are -20 and 20 */ -#if sun -#ifndef PRIO_MIN -#define PRIO_MIN -20 -#endif -#ifndef PRIO_MAX -#define PRIO_MAX 20 -#endif -#endif - -/** - * gdm_daemon_config_load_xserver - * - * Load [server-foo] sections from a configuration file. - */ -static void -gdm_daemon_config_load_xserver (GdmConfig *config, - const char *key, - const char *name) -{ - GdmXserver *svr; - int n; - char *group; - gboolean res; - GdmConfigValue *value; - - /* - * See if we already loaded a server with this id, skip if - * one already exists. - */ - if (gdm_daemon_config_find_xserver (name) != NULL) { - return; - } - - svr = g_new0 (GdmXserver, 1); - svr->id = g_strdup (name); - - if (isdigit (*key)) { - svr->number = atoi (key); - } - - group = g_strdup_printf ("server-%s", name); - - /* string */ - res = gdm_config_get_value (config, group, "name", &value); - if (res) { - svr->name = g_strdup (gdm_config_value_get_string (value)); - } - res = gdm_config_get_value (config, group, "command", &value); - if (res) { - svr->command = g_strdup (gdm_config_value_get_string (value)); - } - - gdm_debug ("Adding new server id=%s name=%s command=%s", name, svr->name, svr->command); - - - /* bool */ - res = gdm_config_get_value (config, group, "flexible", &value); - if (res) { - svr->flexible = gdm_config_value_get_bool (value); - } - res = gdm_config_get_value (config, group, "choosable", &value); - if (res) { - svr->choosable = gdm_config_value_get_bool (value); - } - res = gdm_config_get_value (config, group, "handled", &value); - if (res) { - svr->handled = gdm_config_value_get_bool (value); - } - res = gdm_config_get_value (config, group, "chooser", &value); - if (res) { - svr->chooser = gdm_config_value_get_bool (value); - } - - /* int */ - res = gdm_config_get_value (config, group, "priority", &value); - if (res) { - svr->priority = gdm_config_value_get_int (value); - } - - /* do some bounds checking */ - n = svr->priority; - if (n < PRIO_MIN) - n = PRIO_MIN; - else if (n > PRIO_MAX) - n = PRIO_MAX; - - if (n != svr->priority) { - gdm_error (_("%s: Priority out of bounds; changed to %d"), - "gdm_config_parse", n); - svr->priority = n; - } - - if (ve_string_empty (svr->command)) { - gdm_error (_("%s: Empty server command; " - "using standard command."), "gdm_config_parse"); - g_free (svr->command); - svr->command = g_strdup (X_SERVER); - } - - xservers = g_slist_append (xservers, svr); -} - -static void -gdm_daemon_config_unload_xservers (GdmConfig *config) -{ - GSList *xli; - - /* Free list if already loaded */ - for (xli = xservers; xli != NULL; xli = xli->next) { - GdmXserver *xsvr = xli->data; - - g_free (xsvr->id); - g_free (xsvr->name); - g_free (xsvr->command); - } - - if (xservers != NULL) { - g_slist_free (xservers); - xservers = NULL; - } -} - -static void -gdm_daemon_config_ensure_one_xserver (GdmConfig *config) -{ - /* If no "Standard" server was created, then add it */ - if (xservers == NULL || gdm_daemon_config_find_xserver (GDM_STANDARD) == NULL) { - GdmXserver *svr = g_new0 (GdmXserver, 1); - - svr->id = g_strdup (GDM_STANDARD); - svr->name = g_strdup ("Standard server"); - svr->command = g_strdup (X_SERVER); - svr->flexible = TRUE; - svr->choosable = TRUE; - svr->handled = TRUE; - svr->priority = 0; - - xservers = g_slist_append (xservers, svr); - } -} - -static void -load_xservers_group (GdmConfig *config) -{ - char **keys; - gsize len; - int i; - - keys = gdm_config_get_keys_for_group (config, GDM_CONFIG_GROUP_SERVERS, &len, NULL); - - /* now construct entries for these groups */ - for (i = 0; i < len; i++) { - GdmConfigEntry entry; - GdmConfigValue *value; - char *new_group; - gboolean res; - int j; - const char *name; - - entry.group = GDM_CONFIG_GROUP_SERVERS; - entry.key = keys[i]; - entry.type = GDM_CONFIG_VALUE_STRING; - entry.default_value = NULL; - entry.id = GDM_CONFIG_INVALID_ID; - - gdm_config_add_entry (config, &entry); - gdm_config_process_entry (config, &entry, NULL); - - res = gdm_config_get_value (config, entry.group, entry.key, &value); - if (! res) { - continue; - } - - name = gdm_config_value_get_string (value); - if (name == NULL || name[0] == '\0') { - gdm_config_value_free (value); - continue; - } - - /* skip servers marked as inactive */ - if (g_ascii_strcasecmp (name, "inactive") == 0) { - gdm_config_value_free (value); - continue; - } - - new_group = g_strdup_printf ("server-%s", name); - for (j = 0; j < G_N_ELEMENTS (gdm_daemon_server_config_entries); j++) { - GdmConfigEntry *srv_entry; - if (gdm_daemon_server_config_entries[j].key == NULL) { - continue; - } - srv_entry = gdm_config_entry_copy (&gdm_daemon_server_config_entries[j]); - g_free (srv_entry->group); - srv_entry->group = g_strdup (new_group); - gdm_config_process_entry (config, srv_entry, NULL); - gdm_config_entry_free (srv_entry); - } - g_free (new_group); - - /* now we can add this server */ - gdm_daemon_config_load_xserver (config, entry.key, gdm_config_value_get_string (value)); - - gdm_config_value_free (value); - } -} - -static void -gdm_daemon_config_load_xservers (GdmConfig *config) -{ - gdm_daemon_config_unload_xservers (config); - load_xservers_group (config); - gdm_daemon_config_ensure_one_xserver (config); -} - -/** - * gdm_daemon_config_update_key - * - * Will cause a the GDM daemon to re-read the key from the configuration - * file and cause notify signal to be sent to the slaves for the - * specified key, if appropriate. - * Obviously notification is not needed for configuration options only - * used by the daemon. This function is called when the UPDDATE_CONFIG - * sockets command is called. - * - * To add a new notification, a GDM_NOTIFY_* argument will need to be - * defined in gdm-daemon-config-keys.h, supporting logic placed in the - * notify_cb function and in the gdm_slave_handle_notify function - * in slave.c. - */ -gboolean -gdm_daemon_config_update_key (const char *keystring) -{ - gboolean rc; - gboolean res; - char *group; - char *key; - char *locale; - const GdmConfigEntry *entry; - - rc = FALSE; - group = key = locale = NULL; - - /* - * Do not allow these keys to be updated, since GDM would need - * additional work, or at least heavy testing, to make these keys - * flexible enough to be changed at runtime. - */ - if (is_key (keystring, GDM_KEY_PID_FILE) || - is_key (keystring, GDM_KEY_CONSOLE_NOTIFY) || - is_key (keystring, GDM_KEY_USER) || - is_key (keystring, GDM_KEY_GROUP) || - is_key (keystring, GDM_KEY_LOG_DIR) || - is_key (keystring, GDM_KEY_SERV_AUTHDIR) || - is_key (keystring, GDM_KEY_USER_AUTHDIR) || - is_key (keystring, GDM_KEY_USER_AUTHFILE) || - is_key (keystring, GDM_KEY_USER_AUTHDIR_FALLBACK)) { - return FALSE; - } - - /* reload backend files if necessary */ - gdm_config_load (daemon_config, NULL); - - /* Shortcut for updating all XDMCP parameters */ - if (is_key (keystring, "xdmcp/PARAMETERS")) { - gdm_daemon_config_update_key (GDM_KEY_DISPLAYS_PER_HOST); - gdm_daemon_config_update_key (GDM_KEY_MAX_PENDING); - gdm_daemon_config_update_key (GDM_KEY_MAX_WAIT); - gdm_daemon_config_update_key (GDM_KEY_MAX_SESSIONS); - gdm_daemon_config_update_key (GDM_KEY_INDIRECT); - gdm_daemon_config_update_key (GDM_KEY_MAX_INDIRECT); - gdm_daemon_config_update_key (GDM_KEY_MAX_WAIT_INDIRECT); - gdm_daemon_config_update_key (GDM_KEY_PING_INTERVAL); - rc = TRUE; - goto out; - } - - /* find the entry for the key */ - res = gdm_common_config_parse_key_string (keystring, - &group, - &key, - &locale, - NULL); - if (! res) { - gdm_error ("Could not parse configuration key %s", keystring); - goto out; - } - - entry = gdm_config_lookup_entry (daemon_config, group, key); - if (entry == NULL) { - gdm_error ("Request for invalid configuration key %s", keystring); - goto out; - } - - gdm_config_process_entry (daemon_config, entry, NULL); - - out: - g_free (group); - g_free (key); - g_free (locale); - - return rc; -} - -/** - * check_logdir - * check_servauthdir - * - * Support functions for gdm_config_parse. - */ -static void -check_logdir (void) -{ - struct stat statbuf; - int r; - char *log_path; - const char *auth_path; - GdmConfigValue *value; - - log_path = NULL; - auth_path = NULL; - - gdm_config_get_string_for_id (daemon_config, GDM_ID_LOG_DIR, &log_path); - - gdm_config_get_value_for_id (daemon_config, GDM_ID_SERV_AUTHDIR, &value); - auth_path = gdm_config_value_get_string (value); - - VE_IGNORE_EINTR (r = g_stat (log_path, &statbuf)); - if (r < 0 || ! S_ISDIR (statbuf.st_mode)) { - gdm_error (_("%s: Logdir %s does not exist or isn't a directory. Using ServAuthDir %s."), - "gdm_config_parse", - log_path, - auth_path); - gdm_config_set_value_for_id (daemon_config, GDM_ID_LOG_DIR, value); - } - - g_free (log_path); - gdm_config_value_free (value); -} - -static void -check_servauthdir (const char *auth_path, - struct stat *statbuf) -{ - int r; - gboolean console_notify; - - console_notify = FALSE; - gdm_config_get_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, &console_notify); - - /* Enter paranoia mode */ - VE_IGNORE_EINTR (r = g_stat (auth_path, statbuf)); - if G_UNLIKELY (r < 0) { - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("Server Authorization directory " - "(daemon/ServAuthDir) is set to %s " - "but this does not exist. Please " - "correct GDM configuration and " - "restart GDM.")), - auth_path); - - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: Authdir %s does not exist. Aborting."), "gdm_config_parse", auth_path); - } - - if G_UNLIKELY (! S_ISDIR (statbuf->st_mode)) { - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("Server Authorization directory " - "(daemon/ServAuthDir) is set to %s " - "but this is not a directory. Please " - "correct GDM configuration and " - "restart GDM.")), - auth_path); - - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: Authdir %s is not a directory. Aborting."), "gdm_config_parse", auth_path); - } -} - -static gboolean -have_display_for_number (int number) -{ - GSList *l; - - for (l = displays; l != NULL; l = l->next) { - GdmDisplay *disp = l->data; - if (disp->dispnum == number) { - return TRUE; - } - } - - return FALSE; -} - -static void -gdm_daemon_config_load_displays (GdmConfig *config) -{ - GSList *l; - - for (l = xservers; l != NULL; l = l->next) { - GdmXserver *xserver; - GdmDisplay *disp; - - xserver = l->data; - - gdm_debug ("Loading display for key '%d'", xserver->number); - - gdm_debug ("Got name for server: %s", xserver->id); - /* Do not add if already in the list */ - if (have_display_for_number (xserver->number)) { - continue; - } - - disp = gdm_server_alloc (xserver->number, xserver->id); - if (disp == NULL) { - continue; - } - - displays = g_slist_insert_sorted (displays, disp, gdm_daemon_config_compare_displays); - if (xserver->number > high_display_num) { - high_display_num = xserver->number; - } - } -} - -static gboolean -validate_path (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - char *str; - - /* If the /etc/default has a PATH use that */ - str = gdm_read_default ("PATH="); - if (str != NULL) { - gdm_config_value_set_string (value, str); - g_free (str); - } - - return TRUE; -} - -static gboolean -validate_root_path (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - char *str; - - /* If the /etc/default has a PATH use that */ - str = gdm_read_default ("SUPATH="); - if (str != NULL) { - gdm_config_value_set_string (value, str); - g_free (str); - } - - return TRUE; -} - -static gboolean -validate_base_xsession (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - const char *str; - - str = gdm_config_value_get_string (value); - if (str == NULL || str[0] == '\0') { - char *path; - path = g_build_filename (GDMCONFDIR, "gdm", "Xsession", NULL); - gdm_info (_("%s: BaseXsession empty; using %s"), "gdm_config_parse", path); - gdm_config_value_set_string (value, path); - g_free (path); - } - - return TRUE; -} - -static gboolean -validate_power_action (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - /* FIXME: should weed out the commands that don't work */ - - return TRUE; -} - -static gboolean -validate_standard_xserver (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - gboolean res; - gboolean is_ok; - const char *str; - char *new; - - is_ok = FALSE; - new = NULL; - str = gdm_config_value_get_string (value); - - if (str != NULL) { - char **argv; - - if (g_shell_parse_argv (str, NULL, &argv, NULL)) { - if (g_access (argv[0], X_OK) == 0) { - is_ok = TRUE; - } - g_strfreev (argv); - } - } - - if G_UNLIKELY (! is_ok) { - gdm_info (_("%s: Standard X server not found; trying alternatives"), "gdm_config_parse"); - if (g_access ("/usr/X11R6/bin/X", X_OK) == 0) { - new = g_strdup ("/usr/X11R6/bin/X"); - } else if (g_access ("/opt/X11R6/bin/X", X_OK) == 0) { - new = g_strdup ("/opt/X11R6/bin/X"); - } else if (g_access ("/usr/bin/X11/X", X_OK) == 0) { - new = g_strdup ("/usr/bin/X11/X"); - } - } - - if (new != NULL) { - gdm_config_value_set_string (value, new); - g_free (new); - } - - res = TRUE; - - return res; -} - -static gboolean -validate_graphical_theme_dir (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - const char *str; - - str = gdm_config_value_get_string (value); - - if (str == NULL || !g_file_test (str, G_FILE_TEST_IS_DIR)) { - gdm_config_value_set_string (value, GREETERTHEMEDIR); - } - - return TRUE; -} - -static gboolean -validate_graphical_theme (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - const char *str; - - str = gdm_config_value_get_string (value); - - if (str == NULL || str[0] == '\0') { - gdm_config_value_set_string (value, "circles"); - } - - return TRUE; -} - -static gboolean -validate_greeter (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - const char *str; - - str = gdm_config_value_get_string (value); - - if (str == NULL || str[0] == '\0') { - gdm_error (_("%s: No greeter specified."), "gdm_config_parse"); - } - - return TRUE; -} - -static gboolean -validate_remote_greeter (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - const char *str; - - str = gdm_config_value_get_string (value); - - if (str == NULL || str[0] == '\0') { - gdm_error (_("%s: No remote greeter specified."), "gdm_config_parse"); - } - - return TRUE; -} - -static gboolean -validate_session_desktop_dir (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - const char *str; - - str = gdm_config_value_get_string (value); - - if (str == NULL || str[0] == '\0') { - gdm_error (_("%s: No sessions directory specified."), "gdm_config_parse"); - } - - return TRUE; -} - -static gboolean -validate_password_required (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - char *str; - - str = gdm_read_default ("PASSREQ="); - if (str != NULL && str[0] == '\0') { - gboolean val; - val = (g_ascii_strcasecmp (str, "YES") == 0); - gdm_config_value_set_bool (value, val); - } - - return TRUE; -} - -static gboolean -validate_allow_remote_root (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - char *str; - - str = gdm_read_default ("CONSOLE="); - if (str != NULL && str[0] == '\0') { - gboolean val; - val = (g_ascii_strcasecmp (str, "/dev/console") != 0); - gdm_config_value_set_bool (value, val); - } - - return TRUE; -} - -static gboolean -validate_xdmcp (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value) -{ - -#ifndef HAVE_LIBXDMCP - if (gdm_config_value_get_bool (value)) { - gdm_info (_("%s: XDMCP was enabled while there is no XDMCP support; turning it off"), "gdm_config_parse"); - gdm_config_value_set_bool (value, FALSE); - } -#endif - - return TRUE; -} - -static gboolean -validate_at_least_int (GdmConfig *config, - GdmConfigSourceType source, - GdmConfigValue *value, - int minval, - int defval) -{ - if (gdm_config_value_get_int (value) < minval) { - gdm_config_value_set_int (value, defval); - } - - return TRUE; -} - -static gboolean -validate_cb (GdmConfig *config, - GdmConfigSourceType source, - const char *group, - const char *key, - GdmConfigValue *value, - int id, - gpointer data) -{ - gboolean res; - - res = TRUE; - - switch (id) { - case GDM_ID_PATH: - res = validate_path (config, source, value); - break; - case GDM_ID_ROOT_PATH: - res = validate_root_path (config, source, value); - break; - case GDM_ID_BASE_XSESSION: - res = validate_base_xsession (config, source, value); - break; - case GDM_ID_HALT: - case GDM_ID_REBOOT: - case GDM_ID_SUSPEND: - res = validate_power_action (config, source, value); - break; - case GDM_ID_STANDARD_XSERVER: - res = validate_standard_xserver (config, source, value); - break; - case GDM_ID_GRAPHICAL_THEME_DIR: - res = validate_graphical_theme_dir (config, source, value); - break; - case GDM_ID_GRAPHICAL_THEME: - res = validate_graphical_theme (config, source, value); - break; - case GDM_ID_GREETER: - res = validate_greeter (config, source, value); - break; - case GDM_ID_REMOTE_GREETER: - res = validate_remote_greeter (config, source, value); - break; - case GDM_ID_SESSION_DESKTOP_DIR: - res = validate_session_desktop_dir (config, source, value); - break; - case GDM_ID_PASSWORD_REQUIRED: - res = validate_password_required (config, source, value); - break; - case GDM_ID_ALLOW_REMOTE_ROOT: - res = validate_allow_remote_root (config, source, value); - break; - case GDM_ID_XDMCP: - res = validate_xdmcp (config, source, value); - break; - case GDM_ID_MAX_INDIRECT: - case GDM_ID_XINERAMA_SCREEN: - res = validate_at_least_int (config, source, value, 0, 0); - break; - case GDM_ID_TIMED_LOGIN_DELAY: - res = validate_at_least_int (config, source, value, 5, 5); - break; - case GDM_ID_MAX_ICON_WIDTH: - case GDM_ID_MAX_ICON_HEIGHT: - res = validate_at_least_int (config, source, value, 0, 128); - break; - case GDM_ID_SCAN_TIME: - res = validate_at_least_int (config, source, value, 1, 1); - break; - case GDM_ID_NONE: - case GDM_CONFIG_INVALID_ID: - break; - default: - break; - } - - return res; -} - -static const char * -source_to_name (GdmConfigSourceType source) -{ - const char *name; - - switch (source) { - case GDM_CONFIG_SOURCE_DEFAULT: - name = "default"; - break; - case GDM_CONFIG_SOURCE_MANDATORY: - name = "mandatory"; - break; - case GDM_CONFIG_SOURCE_CUSTOM: - name = "custom"; - break; - case GDM_CONFIG_SOURCE_BUILT_IN: - name = "built-in"; - break; - case GDM_CONFIG_SOURCE_RUNTIME_USER: - name = "runtime-user"; - break; - case GDM_CONFIG_SOURCE_INVALID: - name = "Invalid"; - break; - default: - name = "Unknown"; - break; - } - - return name; -} - -static gboolean -notify_cb (GdmConfig *config, - GdmConfigSourceType source, - const char *group, - const char *key, - GdmConfigValue *value, - int id, - gpointer data) -{ - char *valstr; - - switch (id) { - case GDM_ID_GREETER: - case GDM_ID_REMOTE_GREETER: - case GDM_ID_SOUND_ON_LOGIN_FILE: - case GDM_ID_SOUND_ON_LOGIN_SUCCESS_FILE: - case GDM_ID_SOUND_ON_LOGIN_FAILURE_FILE: - case GDM_ID_GTK_MODULES_LIST: - case GDM_ID_TIMED_LOGIN: - case GDM_ID_ALLOW_ROOT: - case GDM_ID_ALLOW_REMOTE_ROOT: - case GDM_ID_ALLOW_REMOTE_AUTOLOGIN: - case GDM_ID_SYSTEM_MENU: - case GDM_ID_CONFIG_AVAILABLE: - case GDM_ID_CHOOSER_BUTTON: - case GDM_ID_DISALLOW_TCP: - case GDM_ID_ADD_GTK_MODULES: - case GDM_ID_TIMED_LOGIN_ENABLE: - case GDM_ID_RETRY_DELAY: - case GDM_ID_TIMED_LOGIN_DELAY: - notify_displays_value (config, group, key, value); - break; - case GDM_ID_NONE: - case GDM_CONFIG_INVALID_ID: - { - /* doesn't have an ID : match group/key */ - if (group != NULL) { - if (strcmp (group, GDM_CONFIG_GROUP_SERVERS) == 0) { - /* FIXME: handle this? */ - } else if (strcmp (group, GDM_CONFIG_GROUP_CUSTOM_CMD) == 0) { - notify_displays_value (config, group, key, value); - } - } - } - break; - default: - break; - } - - valstr = gdm_config_value_to_string (value); - gdm_debug ("Got config %s/%s=%s <%s>\n", - group, - key, - valstr, - source_to_name (source)); - g_free (valstr); - - return TRUE; -} - -static void -handle_no_displays (GdmConfig *config, - gboolean no_console) -{ - const char *server; - gboolean console_notify; - - console_notify = FALSE; - gdm_config_get_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, &console_notify); - - /* - * If we requested no static servers (there is no console), - * then don't display errors in console messages - */ - if (no_console) { - gdm_fail (_("%s: XDMCP disabled and no static servers defined. Aborting!"), "gdm_config_parse"); - } - - server = X_SERVER; - if G_LIKELY (g_access (server, X_OK) == 0) { - } else if (g_access ("/usr/bin/X11/X", X_OK) == 0) { - server = "/usr/bin/X11/X"; - } else if (g_access ("/usr/X11R6/bin/X", X_OK) == 0) { - server = "/usr/X11R6/bin/X"; - } else if (g_access ("/opt/X11R6/bin/X", X_OK) == 0) { - server = "/opt/X11R6/bin/X"; - } - - /* yay, we can add a backup emergency server */ - if (server != NULL) { - GdmDisplay *d; - - int num = gdm_get_free_display (0 /* start */, 0 /* server uid */); - - gdm_error (_("%s: XDMCP disabled and no static servers defined. Adding %s on :%d to allow configuration!"), - "gdm_config_parse", server, num); - - d = gdm_server_alloc (num, server); - d->is_emergency_server = TRUE; - - displays = g_slist_append (displays, d); - - /* ALWAYS run the greeter and don't log anyone in, - * this is just an emergency session */ - gdm_config_set_string_for_id (daemon_config, GDM_ID_AUTOMATIC_LOGIN, NULL); - gdm_config_set_string_for_id (daemon_config, GDM_ID_TIMED_LOGIN, NULL); - - } else { - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("XDMCP is disabled and GDM " - "cannot find any static server " - "to start. Aborting! Please " - "correct the configuration " - "and restart GDM."))); - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: XDMCP disabled and no static servers defined. Aborting!"), "gdm_config_parse"); - } -} - -static void -gdm_daemon_change_user (GdmConfig *config, - uid_t *uidp, - gid_t *gidp) -{ - gboolean console_notify; - char *username; - char *groupname; - uid_t uid; - gid_t gid; - struct passwd *pwent; - struct group *grent; - - console_notify = FALSE; - username = NULL; - groupname = NULL; - uid = 0; - gid = 0; - - gdm_config_get_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, &console_notify); - gdm_config_get_string_for_id (daemon_config, GDM_ID_USER, &username); - gdm_config_get_string_for_id (daemon_config, GDM_ID_GROUP, &groupname); - - /* Lookup user and groupid for the GDM user */ - pwent = getpwnam (username); - - /* Set uid and gid */ - if G_UNLIKELY (pwent == NULL) { - - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("The GDM user '%s' does not exist. " - "Please correct GDM configuration " - "and restart GDM.")), - username); - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: Can't find the GDM user '%s'. Aborting!"), "gdm_config_parse", username); - } else { - uid = pwent->pw_uid; - } - - if G_UNLIKELY (uid == 0) { - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("The GDM user is set to be root, but " - "this is not allowed since it can " - "pose a security risk. Please " - "correct GDM configuration and " - "restart GDM."))); - - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: The GDM user should not be root. Aborting!"), "gdm_config_parse"); - } - - grent = getgrnam (groupname); - - if G_UNLIKELY (grent == NULL) { - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("The GDM group '%s' does not exist. " - "Please correct GDM configuration " - "and restart GDM.")), - groupname); - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: Can't find the GDM group '%s'. Aborting!"), "gdm_config_parse", groupname); - } else { - gid = grent->gr_gid; - } - - if G_UNLIKELY (gid == 0) { - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("The GDM group is set to be root, but " - "this is not allowed since it can " - "pose a security risk. Please " - "correct GDM configuration and " - "restart GDM."))); - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: The GDM group should not be root. Aborting!"), "gdm_config_parse"); - } - - /* gid remains `gdm' */ - NEVER_FAILS_root_set_euid_egid (uid, gid); - - if (uidp != NULL) { - *uidp = uid; - } - - if (gidp != NULL) { - *gidp = gid; - } - - g_free (username); - g_free (groupname); -} - -static void -gdm_daemon_check_permissions (GdmConfig *config, - uid_t uid, - gid_t gid) -{ - struct stat statbuf; - char *auth_path; - gboolean console_notify; - - console_notify = FALSE; - gdm_config_get_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, &console_notify); - auth_path = NULL; - gdm_config_get_string_for_id (config, GDM_ID_LOG_DIR, &auth_path); - - /* Enter paranoia mode */ - check_servauthdir (auth_path, &statbuf); - - NEVER_FAILS_root_set_euid_egid (0, 0); - - /* Now set things up for us as */ - chown (auth_path, 0, gid); - g_chmod (auth_path, (S_IRWXU|S_IRWXG|S_ISVTX)); - - NEVER_FAILS_root_set_euid_egid (uid, gid); - - /* Again paranoid */ - check_servauthdir (auth_path, &statbuf); - - if G_UNLIKELY (statbuf.st_uid != 0 || statbuf.st_gid != gid) { - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("Server Authorization directory " - "(daemon/ServAuthDir) is set to %s " - "but is not owned by user %d and group " - "%d. Please correct the ownership or " - "GDM configuration and restart " - "GDM.")), - auth_path, - (int)uid, - (int)gid); - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: Authdir %s is not owned by user %d, group %d. Aborting."), - "gdm_config_parse", - auth_path, - (int)uid, - (int)gid); - } - - if G_UNLIKELY (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX)) { - if (console_notify) { - gchar *s = g_strdup_printf (C_(N_("Server Authorization directory " - "(daemon/ServAuthDir) is set to %s " - "but has the wrong permissions: it " - "should have permissions of %o. " - "Please correct the permissions or " - "the GDM configuration and " - "restart GDM.")), - auth_path, - (S_IRWXU|S_IRWXG|S_ISVTX)); - gdm_text_message_dialog (s); - g_free (s); - } - - gdm_fail (_("%s: Authdir %s has wrong permissions %o. Should be %o. Aborting."), - "gdm_config_parse", - auth_path, - statbuf.st_mode, - (S_IRWXU|S_IRWXG|S_ISVTX)); - } - - g_free (auth_path); -} - -/** - * gdm_daemon_config_parse - * - * Loads initial configuration settings. - */ -void -gdm_daemon_config_parse (const char *config_file, - gboolean no_console) -{ - uid_t uid; - gid_t gid; - GError *error; - gboolean xdmcp_enabled; - gboolean dynamic_enabled; - - displays = NULL; - high_display_num = 0; - - /* Not NULL if config_file was set by command-line option. */ - if (config_file == NULL) { - config_file = GDM_DEFAULTS_CONF; - } - custom_config_file = g_strdup (GDM_CUSTOM_CONF); - - daemon_config = gdm_config_new (); - - gdm_config_set_notify_func (daemon_config, notify_cb, NULL); - gdm_config_set_validate_func (daemon_config, validate_cb, NULL); - - gdm_config_add_static_entries (daemon_config, gdm_daemon_config_entries); - - gdm_config_set_default_file (daemon_config, config_file); - gdm_config_set_custom_file (daemon_config, custom_config_file); - - /* load the data files */ - error = NULL; - gdm_config_load (daemon_config, &error); - if (error != NULL) { - gdm_error ("Unable to load configuration: %s", error->message); - g_error_free (error); - } - - /* populate the database with all specified entries */ - gdm_config_process_all (daemon_config, &error); - - gdm_daemon_config_load_xservers (daemon_config); - - /* Only read the list if no_console is FALSE at this stage */ - if (! no_console) { - gdm_daemon_config_load_displays (daemon_config); - } - - xdmcp_enabled = FALSE; - gdm_config_get_bool_for_id (daemon_config, GDM_ID_XDMCP, &xdmcp_enabled); - dynamic_enabled = FALSE; - gdm_config_get_bool_for_id (daemon_config, GDM_ID_DYNAMIC_XSERVERS, &dynamic_enabled); - if G_UNLIKELY ((displays == NULL) && (! xdmcp_enabled) && (! dynamic_enabled)) { - handle_no_displays (daemon_config, no_console); - } - - /* If no displays were found, then obviously - we're in a no console mode */ - if (displays == NULL) { - no_console = TRUE; - } - - if (no_console) { - gdm_config_set_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, FALSE); - } - - gdm_daemon_change_user (daemon_config, &uid, &gid); - - gdm_daemon_check_permissions (daemon_config, uid, gid); - - NEVER_FAILS_root_set_euid_egid (0, 0); - - check_logdir (); - - GdmUserId = uid; - GdmGroupId = gid; - - /* Check that user authentication is properly configured */ - gdm_verify_check (); -} - -/** - * gdm_daemon_config_get_gdmuid - * gdm_daemon_config_get_gdmgid - * - * Access functions for getting the GDM user ID and group ID. - */ -uid_t -gdm_daemon_config_get_gdmuid (void) -{ - return GdmUserId; -} - -gid_t -gdm_daemon_config_get_gdmgid (void) -{ - return GdmGroupId; -} - -/** - * gdm_daemon_config_get_high_display_num - * gdm_daemon_config_get_high_display_num - * - * Access functions for getting the high display number. - */ -gint -gdm_daemon_config_get_high_display_num (void) -{ - return high_display_num; -} - -void -gdm_daemon_config_set_high_display_num (gint val) -{ - high_display_num = val; -} - -/** - * gdm_is_valid_key - * - * Returns TRUE if the key is a valid key, FALSE otherwise. - */ -gboolean -gdm_daemon_config_is_valid_key (const char *keystring) -{ - char *group; - char *key; - gboolean ret; - const GdmConfigEntry *entry; - - ret = gdm_common_config_parse_key_string (keystring, - &group, - &key, - NULL, - NULL); - if (! ret) { - goto out; - } - - - entry = gdm_config_lookup_entry (daemon_config, group, key); - ret = (entry != NULL); - - g_free (group); - g_free (key); - out: - return ret; -} - -/** - * gdm_signal_terminthup_was_notified - * - * returns TRUE if signal SIGTERM, SIGINT, or SIGHUP was received. - * This just hides these vicious-extensions functions from the - * other files - */ -gboolean -gdm_daemon_config_signal_terminthup_was_notified (void) -{ - if (ve_signal_was_notified (SIGTERM) || - ve_signal_was_notified (SIGINT) || - ve_signal_was_notified (SIGHUP)) { - return TRUE; - } else { - return FALSE; - } -} - -/** - * check_user_file - * check_global_file - * is_in_trusted_pic_dir - * get_facefile_from_gnome2_dir_config - * path_is_local - * gdm_daemon_config_get_facefile_from_home - * gdm_daemon_config_get_facefile_from_global - * - * These functions are used for accessing the user's face image from their - * home directory via vicious-extensions. - */ -static gboolean -check_user_file (const char *path, - guint uid) -{ - char *dir; - char *file; - gboolean is_ok; - - if (path == NULL) - return FALSE; - - if (g_access (path, R_OK) != 0) - return FALSE; - - dir = g_path_get_dirname (path); - file = g_path_get_basename (path); - - is_ok = gdm_file_check ("run_pictures", - uid, - dir, - file, - TRUE, TRUE, - gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE), - gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM)); - g_free (dir); - g_free (file); - - return is_ok; -} - -static gboolean -check_global_file (const char *path, - guint uid) -{ - if (path == NULL) - return FALSE; - - if (g_access (path, R_OK) != 0) - return FALSE; - - return TRUE; -} - -/* If path starts with a "trusted" directory, don't sanity check things */ -/* This is really somewhat "outdated" as we now really want things in - * the picture dir or in ~/.gnome2/photo */ -static gboolean -is_in_trusted_pic_dir (const char *path) -{ - /* our own pixmap dir is trusted */ - if (strncmp (path, PIXMAPDIR, sizeof (PIXMAPDIR)) == 0) - return TRUE; - - return FALSE; -} - -static gchar * -get_facefile_from_gnome2_dir_config (const char *homedir, - guint uid) -{ - char *picfile = NULL; - char *cfgdir; - - /* Sanity check on ~user/.gnome2/gdm */ - cfgdir = g_build_filename (homedir, ".gnome2", "gdm", NULL); - if (G_LIKELY (check_user_file (cfgdir, uid))) { - GKeyFile *cfg; - char *cfgfile; - - cfgfile = g_build_filename (homedir, ".gnome2", "gdm", NULL); - cfg = gdm_common_config_load (cfgfile, NULL); - g_free (cfgfile); - - if (cfg != NULL) { - gdm_common_config_get_string (cfg, "face/picture=", &picfile, NULL); - g_key_file_free (cfg); - } - - /* must exist and be absolute (note that this check - * catches empty strings)*/ - /* Note that these days we just set ~/.face */ - if G_UNLIKELY (picfile != NULL && - (picfile[0] != '/' || - /* this catches readability by user */ - g_access (picfile, R_OK) != 0)) { - g_free (picfile); - picfile = NULL; - } - - if (picfile != NULL) { - char buf[PATH_MAX]; - if (realpath (picfile, buf) == NULL) { - g_free (picfile); - picfile = NULL; - } else { - g_free (picfile); - picfile = g_strdup (buf); - } - } - - if G_UNLIKELY (picfile != NULL) { - if (! is_in_trusted_pic_dir (picfile)) { - /* if not in trusted dir, check it out */ - - /* Note that strict permissions checking is done - * on this file. Even if it may not even be owned by the - * user. This setting should ONLY point to pics in trusted - * dirs. */ - if (! check_user_file (picfile, uid)) { - g_free (picfile); - picfile = NULL; - } - } - } - } - g_free (cfgdir); - - return picfile; -} - -static GHashTable *fstype_hash = NULL; -extern char *filesystem_type (char *path, char *relpath, struct stat *statp); - -static gboolean -path_is_local (const char *path) -{ - gpointer local = NULL; - - if (path == NULL) - return FALSE; - - if (fstype_hash == NULL) - fstype_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - else - local = g_hash_table_lookup (fstype_hash, path); - - if (local == NULL) { - struct stat statbuf; - - if (g_stat (path, &statbuf) == 0) { - char *type = filesystem_type ((char *)path, (char *)path, &statbuf); - gboolean is_local = ((strcmp (ve_sure_string (type), "nfs") != 0) && - (strcmp (ve_sure_string (type), "afs") != 0) && - (strcmp (ve_sure_string (type), "autofs") != 0) && - (strcmp (ve_sure_string (type), "unknown") != 0) && - (strcmp (ve_sure_string (type), "ncpfs") != 0)); - local = GINT_TO_POINTER (is_local ? 1 : -1); - g_hash_table_insert (fstype_hash, g_strdup (path), local); - } - } - - return GPOINTER_TO_INT (local) > 0; -} - -gchar * -gdm_daemon_config_get_facefile_from_home (const char *homedir, - guint uid) -{ - char *picfile = NULL; - char *path; - gboolean is_local; - - /* special case: look at parent of home to detect autofs - this is so we don't try to trigger an automount */ - path = g_path_get_dirname (homedir); - is_local = path_is_local (path); - g_free (path); - - /* now check that home dir itself is local */ - if (is_local) { - is_local = path_is_local (homedir); - } - - /* Only look at local home directories so we don't try to - read from remote (e.g. NFS) volumes */ - if (! is_local) - return NULL; - - picfile = g_build_filename (homedir, ".face", NULL); - - if (check_user_file (picfile, uid)) - return picfile; - else { - g_free (picfile); - picfile = NULL; - } - - picfile = g_build_filename (homedir, ".face.icon", NULL); - - if (check_user_file (picfile, uid)) - return picfile; - else { - g_free (picfile); - picfile = NULL; - } - - picfile = get_facefile_from_gnome2_dir_config (homedir, uid); - if (check_user_file (picfile, uid)) - return picfile; - else { - g_free (picfile); - picfile = NULL; - } - - /* Nothing found yet, try the old locations */ - - picfile = g_build_filename (homedir, ".gnome2", "photo", NULL); - if (check_user_file (picfile, uid)) - return picfile; - else { - g_free (picfile); - picfile = NULL; - } - - picfile = g_build_filename (homedir, ".gnome", "photo", NULL); - if (check_user_file (picfile, uid)) - return picfile; - else { - g_free (picfile); - picfile = NULL; - } - - return NULL; -} - -gchar * -gdm_daemon_config_get_facefile_from_global (const char *username, - guint uid) -{ - char *picfile = NULL; - const char *facedir; - - facedir = gdm_daemon_config_get_value_string (GDM_KEY_GLOBAL_FACE_DIR); - - /* Try the global face directory */ - - picfile = g_build_filename (facedir, username, NULL); - - if (check_global_file (picfile, uid)) - return picfile; - - g_free (picfile); - picfile = gdm_make_filename (facedir, username, ".png"); - - if (check_global_file (picfile, uid)) - return picfile; - - g_free (picfile); - return NULL; -} - -static gboolean -is_prog_in_path (const char *prog) -{ - char *f; - gboolean ret; - - f = g_find_program_in_path (prog); - ret = (f != NULL); - g_free (f); - return ret; -} - -/** - * gdm_daemon_config_get_session_exec - * - * This function accesses the GDM session desktop file, via vicious - * extensions and returns the execution command for starting the - * session. - * - * Must be called with the PATH set correctly to find session exec. - */ -char * -gdm_daemon_config_get_session_exec (const char *session_name, - gboolean check_try_exec) -{ - char *session_filename; - const char *path_str; - char **search_dirs; - GKeyFile *cfg; - static char *exec; - static char *cached = NULL; - gboolean hidden; - char *ret; - - cfg = NULL; - - /* clear cache */ - if (session_name == NULL) { - g_free (exec); - exec = NULL; - g_free (cached); - cached = NULL; - return NULL; - } - - if (cached != NULL && strcmp (ve_sure_string (session_name), ve_sure_string (cached)) == 0) - return g_strdup (exec); - - g_free (exec); - exec = NULL; - g_free (cached); - cached = g_strdup (session_name); - - /* Some ugly special casing for legacy "Default.desktop", oh well, - * we changed to "default.desktop" */ - if (g_ascii_strcasecmp (session_name, "default") == 0 || - g_ascii_strcasecmp (session_name, "default.desktop") == 0) { - session_filename = g_strdup ("default.desktop"); - } else { - session_filename = gdm_ensure_extension (session_name, ".desktop"); - } - - path_str = gdm_daemon_config_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR); - if (path_str == NULL) { - gdm_error ("No session desktop directories defined"); - goto out; - } - - search_dirs = g_strsplit (path_str, ":", -1); - - cfg = gdm_common_config_load_from_dirs (session_filename, - (const char **)search_dirs, - NULL); - g_strfreev (search_dirs); - - if (cfg == NULL) { - if (gdm_is_session_magic (session_name)) { - exec = g_strdup (session_name); - } else { - g_free (exec); - exec = NULL; - } - goto out; - } - - hidden = FALSE; - gdm_common_config_get_boolean (cfg, "Desktop Entry/Hidden=false", &hidden, NULL); - if (hidden) { - g_free (exec); - exec = NULL; - goto out; - } - - if (check_try_exec) { - char *tryexec; - - tryexec = NULL; - gdm_common_config_get_string (cfg, "Desktop Entry/TryExec", &tryexec, NULL); - - if (tryexec != NULL && - tryexec[0] != '\0' && - ! is_prog_in_path (tryexec)) { - g_free (tryexec); - g_free (exec); - exec = NULL; - goto out; - } - g_free (tryexec); - } - - exec = NULL; - gdm_common_config_get_string (cfg, "Desktop Entry/Exec", &exec, NULL); - - out: - - ret = g_strdup (exec); - - g_key_file_free (cfg); - - return ret; -} - -/** - * gdm_daemon_config_get_user_session_lang - * - * These functions get and set the user's language and setting in their - * $HOME/.dmrc file via vicious-extensions. - */ -void -gdm_daemon_config_set_user_session_lang (gboolean savesess, - gboolean savelang, - const char *home_dir, - const char *save_session, - const char *save_language) -{ - GKeyFile *dmrc; - gchar *cfgstr; - - cfgstr = g_build_filename (home_dir, ".dmrc", NULL); - - dmrc = gdm_common_config_load (cfgstr, NULL); - if (dmrc == NULL) { - return; - } - - if (savesess) { - g_key_file_set_string (dmrc, "Desktop", "Session", ve_sure_string (save_session)); - } - - if (savelang) { - if (ve_string_empty (save_language)) { - /* we chose the system default language so wipe the - * lang key */ - g_key_file_remove_key (dmrc, "Desktop", "Language", NULL); - } else { - g_key_file_set_string (dmrc, "Desktop", "Language", save_language); - } - } - - if (dmrc != NULL) { - mode_t oldmode; - oldmode = umask (077); - gdm_common_config_save (dmrc, cfgstr, NULL); - umask (oldmode); - } - - g_free (cfgstr); - g_key_file_free (dmrc); -} - -void -gdm_daemon_config_get_user_session_lang (char **usrsess, - char **usrlang, - const char *home_dir, - gboolean *savesess) -{ - char *p; - char *cfgfile; - GKeyFile *cfg; - char *session; - char *lang; - gboolean save; - - cfgfile = g_build_filename (home_dir, ".dmrc", NULL); - cfg = gdm_common_config_load (cfgfile, NULL); - g_free (cfgfile); - - save = FALSE; - session = NULL; - - gdm_common_config_get_string (cfg, "Desktop/Session", &session, NULL); - if (session == NULL) { - session = g_strdup (""); - } - - /* this is just being truly anal about what users give us, and in case - * it looks like they may have included a path whack it. */ - p = strrchr (session, '/'); - if (p != NULL) { - char *tmp = g_strdup (p + 1); - g_free (session); - session = tmp; - } - - /* ugly workaround for migration */ - if (strcmp (session, "Default") == 0 || - strcmp (session, "Default.desktop") == 0) { - g_free (session); - session = g_strdup ("default"); - save = TRUE; - } - - gdm_common_config_get_string (cfg, "Desktop/Language", &lang, NULL); - if (lang == NULL) { - lang = g_strdup (""); - } - - if (usrsess != NULL) { - *usrsess = g_strdup (session); - } - g_free (session); - - if (savesess != NULL) { - *savesess = save; - } - - if (usrlang != NULL) { - *usrlang = g_strdup (lang); - } - g_free (lang); - - g_key_file_free (cfg); -} diff --git a/daemon/gdm-daemon-config.h b/daemon/gdm-daemon-config.h deleted file mode 100644 index a1e72aef..00000000 --- a/daemon/gdm-daemon-config.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * Copyright (C) 2005 Brian Cameron <brian.cameron@sun.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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _GDM_DAEMON_CONFIG_H -#define _GDM_DAEMON_CONFIG_H - -#include "server.h" -#include "gdm-daemon-config-entries.h" - -G_BEGIN_DECLS - -const char * gdm_daemon_config_get_string_for_id (int id); -gboolean gdm_daemon_config_get_bool_for_id (int id); -int gdm_daemon_config_get_int_for_id (int id); - -void gdm_daemon_config_parse (const char *config_file, - gboolean no_console); -GdmXserver * gdm_daemon_config_find_xserver (const char *id); -char * gdm_daemon_config_get_xservers (void); -GSList * gdm_daemon_config_get_display_list (void); -GSList * gdm_daemon_config_display_list_append (GdmDisplay *display); -GSList * gdm_daemon_config_display_list_insert (GdmDisplay *display); -GSList * gdm_daemon_config_display_list_remove (GdmDisplay *display); -uid_t gdm_daemon_config_get_gdmuid (void); -uid_t gdm_daemon_config_get_gdmgid (void); -gint gdm_daemon_config_get_high_display_num (void); -void gdm_daemon_config_set_high_display_num (gint val); - -/* deprecated */ -char * gdm_daemon_config_get_display_custom_config_file (const char *display); -char * gdm_daemon_config_get_custom_config_file (void); - - -const char * gdm_daemon_config_get_value_string (const char *key); -const char ** gdm_daemon_config_get_value_string_array (const char *key); -gboolean gdm_daemon_config_get_value_bool (const char *key); -gint gdm_daemon_config_get_value_int (const char *key); -char * gdm_daemon_config_get_value_string_per_display (const char *key, - const char *display); -gboolean gdm_daemon_config_get_value_bool_per_display (const char *key, - const char *display); -gint gdm_daemon_config_get_value_int_per_display (const char *key, - const char *display); - -void gdm_daemon_config_set_value_string (const char *key, - const char *value); -void gdm_daemon_config_set_value_bool (const char *key, - gboolean value); -void gdm_daemon_config_set_value_int (const char *key, - gint value); - - -gboolean gdm_daemon_config_key_to_string_per_display (const char *display, - const char *key, - char **retval); -gboolean gdm_daemon_config_key_to_string (const char *file, - const char *key, - char **retval); -gboolean gdm_daemon_config_to_string (const char *key, - const char *display, - char **retval); -gboolean gdm_daemon_config_update_key (const char *key); - - -int gdm_daemon_config_compare_displays (gconstpointer a, - gconstpointer b); -gboolean gdm_daemon_config_is_valid_key (const char *key); -gboolean gdm_daemon_config_signal_terminthup_was_notified (void); - -char * gdm_daemon_config_get_facefile_from_home (const char *homedir, - guint uid); -char * gdm_daemon_config_get_facefile_from_global (const char *username, - guint uid); -void gdm_daemon_config_get_user_session_lang (char **usrsess, - char **usrlang, - const char *homedir, - gboolean *savesess); -void gdm_daemon_config_set_user_session_lang (gboolean savesess, - gboolean savelang, - const char *home_dir, - const char *save_session, - const char *save_language); -char * gdm_daemon_config_get_session_exec (const char *session_name, - gboolean check_try_exec); - - -G_END_DECLS - -#endif /* _GDM_DAEMON_CONFIG_H */ diff --git a/daemon/gdm-net.c b/daemon/gdm-net.c deleted file mode 100644 index 93a48dbe..00000000 --- a/daemon/gdm-net.c +++ /dev/null @@ -1,682 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <strings.h> -#include <unistd.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/un.h> -#include <netdb.h> -#include <ctype.h> -#include <fcntl.h> -#include <errno.h> - -#include <glib/gi18n.h> - -#include "gdm.h" -#include "misc.h" -#include "gdm-net.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -/* - * Kind of a weird setup, new connections whack old connections. - * - * We may want to allow tuning of the max connections, since - * this number means that only a certain number of slaves can - * talk to the daemon at once. Note that since new connections - * whack old connections, this tends to cause traffic problems - * if the daemon is really being hammered. - * - * This is because the slaves retry a failed connection 5 times, - * though they are at least smart enough to sleep 1 second - * between retries if the connection failed on the connect() - * call. But, this means that throwing off a connection causes - * that slave to come back in another second and try to - * connect again. So if the daemon is really being hammered, - * this just causes more traffic problems. It's really faster - * to let each connection finish. - * - * This may cause problems for some setups (perhaps terminal - * servers) where lots of connections may hit the server at once - * and 15 connections may not be enough (especially since the - * console login screen may also be using one of them). Perhaps - * this number should be in configuration file so it can be - * tuned by the end user? - * - * If, when you turn on debug, you notice messages like this - * in the log, "Closing connection, x subconnections reached" - * and some slaves are not working properly, then bumping this - * number up is probably a reasonable fix if you can't simply - * reduce the socket load the daemon must handle. - */ -#define MAX_CONNECTIONS 15 - -struct _GdmConnection { - int fd; - guint source; - gboolean writable; - - GString *buffer; - - int message_count; - - gboolean nonblock; - - int close_level; /* 0 - normal - 1 - no close, when called raise to 2 - 2 - close was requested */ - - char *filename; /* unix socket or fifo filename */ - - guint32 user_flags; - - GdmConnectionHandler handler; - gpointer data; - GDestroyNotify destroy_notify; - - gpointer close_data; - GDestroyNotify close_notify; - - GdmConnection *parent; - - GList *subconnections; - int n_subconnections; - - GdmDisplay *disp; -}; - -int -gdm_connection_is_server_busy (GdmConnection *conn) { - int max_connections = MAX_CONNECTIONS; - - if (conn->n_subconnections >= (max_connections / 2)) { - gdm_debug ("Connections is %d, max is %d, busy TRUE", - conn->n_subconnections, max_connections); - return TRUE; - } else { - gdm_debug ("Connections is %d, max is %d, busy FALSE", - conn->n_subconnections, max_connections); - return FALSE; - } -} - -static gboolean -close_if_needed (GdmConnection *conn, GIOCondition cond, gboolean error) -{ - /* non-subconnections are never closed */ - if (conn->parent == NULL) - return TRUE; - - if (cond & G_IO_ERR || - cond & G_IO_HUP || error) { - if (cond & G_IO_ERR) - gdm_debug ("close_if_needed: Got G_IO_ERR on %d", conn->fd); - if (cond & G_IO_HUP) - gdm_debug ("close_if_needed: Got G_IO_HUP on %d", conn->fd); - if (error) - gdm_debug ("close_if_needed: Got error on %d", conn->fd); - conn->source = 0; - gdm_connection_close (conn); - return FALSE; - } - return TRUE; -} - -static gboolean -gdm_connection_handler (GIOChannel *source, - GIOCondition cond, - gpointer data) -{ - GdmConnection *conn = data; - char buf[PIPE_SIZE]; - char *p; - size_t len; - - if ( ! (cond & G_IO_IN)) - return close_if_needed (conn, cond, FALSE); - - VE_IGNORE_EINTR (len = read (conn->fd, buf, sizeof (buf) -1)); - if (len <= 0) - return close_if_needed (conn, cond, TRUE); - - buf[len] = '\0'; - - if (conn->buffer == NULL) - conn->buffer = g_string_new (NULL); - - for (p = buf; *p != '\0'; p++) { - if (*p == '\r' || - (*p == '\n' && - ve_string_empty (conn->buffer->str))) - /*ignore \r or empty lines*/ - continue; - if (*p == '\n' || - /* cut lines short at 4096 to prevent DoS attacks */ - conn->buffer->len > 4096) { - conn->close_level = 1; - conn->message_count++; - conn->handler (conn, conn->buffer->str, - conn->data); - if (conn->close_level == 2) { - conn->close_level = 0; - conn->source = 0; - gdm_connection_close (conn); - return FALSE; - } - conn->close_level = 0; - g_string_truncate (conn->buffer, 0); - } else { - g_string_append_c (conn->buffer, *p); - } - } - - return close_if_needed (conn, cond, FALSE); -} - -gboolean -gdm_connection_is_writable (GdmConnection *conn) -{ - g_return_val_if_fail (conn != NULL, FALSE); - - return conn->writable; -} - -gboolean -gdm_connection_write (GdmConnection *conn, const char *str) -{ - int ret; - int save_errno; - int flags = 0; -#ifndef MSG_NOSIGNAL - void (*old_handler)(int); -#endif - - g_return_val_if_fail (conn != NULL, FALSE); - g_return_val_if_fail (str != NULL, FALSE); - - if G_UNLIKELY ( ! conn->writable) - return FALSE; - -#ifdef MSG_DONTWAIT - if (conn->nonblock) - flags |= MSG_DONTWAIT; -#endif - -#ifdef MSG_NOSIGNAL - VE_IGNORE_EINTR (ret = send (conn->fd, str, strlen (str), MSG_NOSIGNAL | flags)); - save_errno = errno; -#else - old_handler = signal (SIGPIPE, SIG_IGN); - VE_IGNORE_EINTR (ret = send (conn->fd, str, strlen (str), flags)); - save_errno = errno; - signal (SIGPIPE, old_handler); -#endif - - /* just so that 'signal' doesn't whack it */ - errno = save_errno; - - if G_UNLIKELY (ret < 0) - return FALSE; - else - return TRUE; -} - -static gboolean -gdm_socket_handler (GIOChannel *source, - GIOCondition cond, - gpointer data) -{ - GIOChannel *unixchan; - GdmConnection *conn = data; - GdmConnection *newconn; - struct sockaddr_un addr; - socklen_t addr_size = sizeof (addr); - int fd; - int max_connections; - - if ( ! (cond & G_IO_IN)) - return TRUE; - - VE_IGNORE_EINTR (fd = accept (conn->fd, - (struct sockaddr *)&addr, - &addr_size)); - if G_UNLIKELY (fd < 0) { - gdm_debug ("gdm_socket_handler: Rejecting connection"); - return TRUE; - } - - gdm_debug ("gdm_socket_handler: Accepting new connection fd %d", fd); - - newconn = g_new0 (GdmConnection, 1); - newconn->disp = NULL; - newconn->message_count = 0; - newconn->nonblock = conn->nonblock; - newconn->close_level = 0; - newconn->fd = fd; - newconn->writable = TRUE; - newconn->filename = NULL; - newconn->user_flags = 0; - newconn->buffer = NULL; - newconn->parent = conn; - newconn->subconnections = NULL; - newconn->n_subconnections = 0; - newconn->handler = conn->handler; - newconn->data = conn->data; - newconn->destroy_notify = NULL; /* the data belongs to - parent connection */ - - conn->subconnections = g_list_append (conn->subconnections, newconn); - conn->n_subconnections++; - - /* - * When dynamix servers is turned on, the daemon can be flooded with - * requests and closing a subconnection will typically make the client - * just try and connect again, and worsen the flooding problem. When - * using dynamic servers, allow more clients to connect at once. - */ - max_connections = MAX_CONNECTIONS; - - if (conn->n_subconnections > max_connections) { - GdmConnection *old; - gdm_debug ("Closing connection, %d subconnections reached", - max_connections); - old = conn->subconnections->data; - conn->subconnections = - g_list_remove (conn->subconnections, old); - gdm_connection_close (old); - } - - unixchan = g_io_channel_unix_new (newconn->fd); - g_io_channel_set_encoding (unixchan, NULL, NULL); - g_io_channel_set_buffered (unixchan, FALSE); - - newconn->source = g_io_add_watch_full - (unixchan, G_PRIORITY_DEFAULT, - G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, - gdm_connection_handler, newconn, NULL); - g_io_channel_unref (unixchan); - - return TRUE; -} - -GdmConnection * -gdm_connection_open_unix (const char *sockname, mode_t mode) -{ - GIOChannel *unixchan; - GdmConnection *conn; - struct sockaddr_un addr; - int fd; - int try_again_attempts = 1000; - - fd = socket (AF_UNIX, SOCK_STREAM, 0); - if G_UNLIKELY (fd < 0) { - gdm_error (_("%s: Could not make socket"), - "gdm_connection_open_unix"); - return NULL; - } - -try_again: - /* this is all for creating sockets in /tmp/ safely */ - VE_IGNORE_EINTR (g_unlink (sockname)); - if G_UNLIKELY (errno == EISDIR || - errno == EPERM) { - /* likely a directory, someone's playing tricks on us */ - char *newname = NULL; - do { - g_free (newname); - newname = g_strdup_printf ("%s-renamed-%u", - sockname, - (guint)g_random_int ()); - } while (g_access (newname, F_OK) == 0); - VE_IGNORE_EINTR (g_rename (sockname, newname)); - if G_UNLIKELY (errno != 0) - try_again_attempts = 0; - g_free (newname); - } else if G_UNLIKELY (errno != 0) { - try_again_attempts = 0; - } - - memset (&addr, 0, sizeof (addr)); - strcpy (addr.sun_path, sockname); - addr.sun_family = AF_UNIX; - if G_UNLIKELY (bind (fd, - (struct sockaddr *) &addr, sizeof (addr)) < 0) { - gdm_error (_("%s: Could not bind socket"), - "gdm_connection_open_unix"); - try_again_attempts --; - /* someone is being evil on us */ - if (errno == EADDRINUSE && try_again_attempts >= 0) - goto try_again; - VE_IGNORE_EINTR (close (fd)); - return NULL; - } - - VE_IGNORE_EINTR (g_chmod (sockname, mode)); - - conn = g_new0 (GdmConnection, 1); - conn->disp = NULL; - conn->message_count = 0; - conn->nonblock = FALSE; - conn->close_level = 0; - conn->fd = fd; - conn->writable = FALSE; - conn->buffer = NULL; - conn->filename = g_strdup (sockname); - conn->user_flags = 0; - conn->parent = NULL; - conn->subconnections = NULL; - conn->n_subconnections = 0; - - unixchan = g_io_channel_unix_new (conn->fd); - g_io_channel_set_encoding (unixchan, NULL, NULL); - g_io_channel_set_buffered (unixchan, FALSE); - - conn->source = g_io_add_watch_full - (unixchan, G_PRIORITY_DEFAULT, - G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, - gdm_socket_handler, conn, NULL); - g_io_channel_unref (unixchan); - - listen (fd, 5); - - return conn; -} - -GdmConnection * -gdm_connection_open_fd (int fd) -{ - GIOChannel *unixchan; - GdmConnection *conn; - - g_return_val_if_fail (fd >= 0, NULL); - - conn = g_new0 (GdmConnection, 1); - conn->disp = NULL; - conn->message_count = 0; - conn->nonblock = FALSE; - conn->close_level = 0; - conn->fd = fd; - conn->writable = FALSE; - conn->buffer = NULL; - conn->filename = NULL; - conn->user_flags = 0; - conn->parent = NULL; - conn->subconnections = NULL; - conn->n_subconnections = 0; - - unixchan = g_io_channel_unix_new (conn->fd); - g_io_channel_set_encoding (unixchan, NULL, NULL); - g_io_channel_set_buffered (unixchan, FALSE); - - conn->source = g_io_add_watch_full - (unixchan, G_PRIORITY_DEFAULT, - G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, - gdm_connection_handler, conn, NULL); - g_io_channel_unref (unixchan); - - return conn; -} - -GdmConnection * -gdm_connection_open_fifo (const char *fifo, mode_t mode) -{ - GIOChannel *fifochan; - GdmConnection *conn; - int fd; - - VE_IGNORE_EINTR (g_unlink (fifo)); - - if G_UNLIKELY (mkfifo (fifo, 0660) < 0) { - gdm_error (_("%s: Could not make FIFO"), - "gdm_connection_open_fifo"); - return NULL; - } - - fd = open (fifo, O_RDWR); /* Open with write to avoid EOF */ - - if G_UNLIKELY (fd < 0) { - gdm_error (_("%s: Could not open FIFO"), - "gdm_connection_open_fifo"); - return NULL; - } - - VE_IGNORE_EINTR (g_chmod (fifo, mode)); - - conn = g_new0 (GdmConnection, 1); - conn->disp = NULL; - conn->message_count = 0; - conn->nonblock = FALSE; - conn->close_level = 0; - conn->fd = fd; - conn->writable = FALSE; - conn->buffer = NULL; - conn->filename = g_strdup (fifo); - conn->user_flags = 0; - conn->parent = NULL; - conn->subconnections = NULL; - conn->n_subconnections = 0; - - fifochan = g_io_channel_unix_new (conn->fd); - g_io_channel_set_encoding (fifochan, NULL, NULL); - g_io_channel_set_buffered (fifochan, FALSE); - - conn->source = g_io_add_watch_full - (fifochan, G_PRIORITY_DEFAULT, - G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL, - gdm_connection_handler, conn, NULL); - g_io_channel_unref (fifochan); - - return conn; -} - -void -gdm_connection_set_handler (GdmConnection *conn, - GdmConnectionHandler handler, - gpointer data, - GDestroyNotify destroy_notify) -{ - g_return_if_fail (conn != NULL); - - if (conn->destroy_notify != NULL) - conn->destroy_notify (conn->data); - - conn->handler = handler; - conn->data = data; - conn->destroy_notify = destroy_notify; -} - -guint32 -gdm_connection_get_user_flags (GdmConnection *conn) -{ - g_return_val_if_fail (conn != NULL, 0); - - return conn->user_flags; -} - -void -gdm_connection_set_user_flags (GdmConnection *conn, - guint32 flags) -{ - g_return_if_fail (conn != NULL); - - conn->user_flags = flags; -} - -void -gdm_connection_close (GdmConnection *conn) -{ - GList *list; - - g_return_if_fail (conn != NULL); - - if (conn->close_level > 0) { - /* flag that close was requested */ - conn->close_level = 2; - return; - } - - if (conn->close_notify != NULL) { - conn->close_notify (conn->close_data); - conn->close_notify = NULL; - } - conn->close_data = NULL; - - if (conn->buffer != NULL) { - g_string_free (conn->buffer, TRUE); - conn->buffer = NULL; - } - - if (conn->parent != NULL) { - conn->parent->subconnections = - g_list_remove (conn->parent->subconnections, conn); - /* This is evil a bit, but safe, whereas -- would not be */ - conn->parent->n_subconnections = - g_list_length (conn->parent->subconnections); - conn->parent = NULL; - } - - list = conn->subconnections; - conn->subconnections = NULL; - g_list_foreach (list, (GFunc) gdm_connection_close, NULL); - g_list_free (list); - - if (conn->destroy_notify != NULL) { - conn->destroy_notify (conn->data); - conn->destroy_notify = NULL; - } - conn->data = NULL; - - if (conn->source > 0) { - g_source_remove (conn->source); - conn->source = 0; - } - - if (conn->fd > 0) { - VE_IGNORE_EINTR (close (conn->fd)); - conn->fd = -1; - } - - g_free (conn->filename); - conn->filename = NULL; - - g_free (conn); -} - -void -gdm_connection_set_close_notify (GdmConnection *conn, - gpointer close_data, - GDestroyNotify close_notify) -{ - g_return_if_fail (conn != NULL); - - if (conn->close_notify != NULL) - conn->close_notify (conn->close_data); - - conn->close_data = close_data; - conn->close_notify = close_notify; -} - -gboolean -gdm_connection_printf (GdmConnection *conn, const gchar *format, ...) -{ - va_list args; - gboolean ret; - gchar *s; - - va_start (args, format); - s = g_strdup_vprintf (format, args); - va_end (args); - - ret = gdm_connection_write (conn, s); - - g_free (s); - - return ret; -} - -int -gdm_connection_get_message_count (GdmConnection *conn) -{ - g_return_val_if_fail (conn != NULL, -1); - return conn->message_count; -} - -gboolean -gdm_connection_get_nonblock (GdmConnection *conn) -{ - g_return_val_if_fail (conn != NULL, FALSE); - return conn->nonblock; -} - -void -gdm_connection_set_nonblock (GdmConnection *conn, - gboolean nonblock) -{ - g_return_if_fail (conn != NULL); - conn->nonblock = nonblock; -} - -GdmDisplay * -gdm_connection_get_display (GdmConnection *conn) -{ - g_return_val_if_fail (conn != NULL, NULL); - return conn->disp; -} - -void -gdm_connection_set_display (GdmConnection *conn, - GdmDisplay *disp) -{ - g_return_if_fail (conn != NULL); - conn->disp = disp; -} - -void -gdm_kill_subconnections_with_display (GdmConnection *conn, - GdmDisplay *disp) -{ - GList *subs; - - g_return_if_fail (conn != NULL); - g_return_if_fail (disp != NULL); - - subs = conn->subconnections; - while (subs != NULL) { - GdmConnection *subcon = subs->data; - if (subcon->disp == disp) { - subcon->disp = NULL; - conn->subconnections = - g_list_remove (conn->subconnections, subcon); - gdm_connection_close (subcon); - subs = conn->subconnections; - } else { - subs = subs->next; - } - } -} - -/* EOF */ diff --git a/daemon/gdm-net.h b/daemon/gdm-net.h deleted file mode 100644 index 901c9762..00000000 --- a/daemon/gdm-net.h +++ /dev/null @@ -1,96 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_NET_H -#define GDM_NET_H - -#include <glib.h> - -typedef struct _GdmConnection GdmConnection; - -#include "display.h" - -/* Macros to check authentication level */ -#define GDM_CONN_AUTHENTICATED(conn) \ - ((gdm_connection_get_user_flags (conn) & GDM_SUP_FLAG_AUTHENTICATED) || \ - (gdm_connection_get_user_flags (conn) & GDM_SUP_FLAG_AUTH_GLOBAL)) - -#define GDM_CONN_AUTH_GLOBAL(conn) \ - (gdm_connection_get_user_flags (conn) & GDM_SUP_FLAG_AUTH_GLOBAL) - - -/* Something that will get stuff line by line */ -typedef void (* GdmConnectionHandler) (GdmConnection *conn, - const char *str, - gpointer data); - -gboolean gdm_connection_is_writable (GdmConnection *conn); -gboolean gdm_connection_write (GdmConnection *conn, - const char *str); -gboolean gdm_connection_printf (GdmConnection *conn, - const gchar *format, ...) - G_GNUC_PRINTF (2, 3); - -GdmConnection * gdm_connection_open_unix (const char *sockname, - mode_t mode); -GdmConnection * gdm_connection_open_fd (int fd); -GdmConnection * gdm_connection_open_fifo (const char *fifo, - mode_t mode); - -void gdm_connection_set_close_notify (GdmConnection *conn, - gpointer close_data, - GDestroyNotify close_notify); - -void gdm_connection_set_handler (GdmConnection *conn, - GdmConnectionHandler handler, - gpointer data, - GDestroyNotify destroy_notify); - -gboolean gdm_connection_get_nonblock (GdmConnection *conn); -void gdm_connection_set_nonblock (GdmConnection *conn, - gboolean nonblock); - -guint32 gdm_connection_get_user_flags (GdmConnection *conn); -void gdm_connection_set_user_flags (GdmConnection *conn, - guint32 flags); -#define GDM_CONNECTION_SET_USER_FLAG(conn,flag) { \ - guint32 _flags = gdm_connection_get_user_flags (conn); \ - _flags |= flag; \ - gdm_connection_set_user_flags (conn, _flags); \ - } -#define GDM_CONNECTION_UNSET_USER_FLAG(conn,flag) { \ - guint32 _flags = gdm_connection_get_user_flags (conn); \ - _flags &= ~flag; \ - gdm_connection_set_user_flags (conn, _flags); \ - } - -GdmDisplay * gdm_connection_get_display (GdmConnection *conn); -void gdm_connection_set_display (GdmConnection *conn, - GdmDisplay *disp); -int gdm_connection_is_server_busy (GdmConnection *conn); -void gdm_kill_subconnections_with_display (GdmConnection *conn, - GdmDisplay *disp); - -int gdm_connection_get_message_count (GdmConnection *conn); - - -void gdm_connection_close (GdmConnection *conn); - -#endif /* GDM_NET_H */ - -/* EOF */ diff --git a/daemon/gdm-socket-protocol.h b/daemon/gdm-socket-protocol.h deleted file mode 100644 index d1ea3b68..00000000 --- a/daemon/gdm-socket-protocol.h +++ /dev/null @@ -1,247 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _GDM_SOCKET_PROTOCOL_H -#define _GDM_SOCKET_PROTOCOL_H - -#include <glib.h> - -#define STX 0x2 /* Start of txt */ -#define BEL 0x7 /* Bell, used to interrupt login for - * say timed login or something similar */ - -/* - * Opcodes for the highly sophisticated protocol used for - * daemon<->greeter communications - */ - -/* This will change if there are incompatible - * protocol changes */ -#define GDM_GREETER_PROTOCOL_VERSION "3" - -#define GDM_MSG 'D' -#define GDM_NOECHO 'U' -#define GDM_PROMPT 'N' -#define GDM_SESS 'G' -#define GDM_LANG '&' -#define GDM_SSESS 'C' -#define GDM_SLANG 'R' -#define GDM_SETLANG 'L' -#define GDM_RESET 'A' -#define GDM_QUIT 'P' -/* Well these aren't as nice as above, oh well */ -#define GDM_STARTTIMER 's' -#define GDM_STOPTIMER 'S' -#define GDM_SETLOGIN 'l' /* this just sets the login to be this, just for - the greeters knowledge */ -#define GDM_DISABLE '-' /* disable the login screen */ -#define GDM_ENABLE '+' /* enable the login screen */ -#define GDM_RESETOK 'r' /* reset but don't shake */ -#define GDM_NEEDPIC '#' /* need a user picture?, sent after greeter - * is started */ -#define GDM_READPIC '%' /* Send a user picture in a temp file */ -#define GDM_ERRBOX 'e' /* Puts string in the error box */ -#define GDM_ERRDLG 'E' /* Puts string up in an error dialog */ -#define GDM_NOFOCUS 'f' /* Don't focus the login window (optional) */ -#define GDM_FOCUS 'F' /* Allow focus on the login window again (optional) */ -#define GDM_SAVEDIE '!' /* Save wm order and die (and set busy cursor) */ -#define GDM_QUERY_CAPSLOCK 'Q' /* Is capslock on? */ -#define GDM_ALWAYS_RESTART 'W' /* Retart greeter when the user accepts restarts */ - -/* Different login interruptions */ -#define GDM_INTERRUPT_TIMED_LOGIN 'T' -#define GDM_INTERRUPT_CONFIGURE 'C' -#define GDM_INTERRUPT_SUSPEND 'S' -#define GDM_INTERRUPT_SELECT_USER 'U' -#define GDM_INTERRUPT_LOGIN_SOUND 'L' -#define GDM_INTERRUPT_THEME 'H' -#define GDM_INTERRUPT_CUSTOM_CMD 'M' -#define GDM_INTERRUPT_CANCEL 'X' -#define GDM_INTERRUPT_SELECT_LANG 'O' - -/* List delimiter for config file lists */ -#define GDM_DELIMITER_MODULES ":" -#define GDM_DELIMITER_THEMES "/:" - - -/* - * primitive protocol for controlling the daemon from slave - * or gdmconfig or whatnot - */ - -/* The ones that pass a <slave pid> must be from a valid slave, and - * the slave will be sent a SIGUSR2. Nowdays there is a pipe that is - * used from inside slaves, so those messages may stop being processed - * by the fifo at some point perhaps. */ -/* The fifo protocol, used only by gdm internally */ -#define GDM_SOP_CHOSEN "CHOSEN" /* <indirect id> <ip addr> */ -#define GDM_SOP_CHOSEN_LOCAL "CHOSEN_LOCAL" /* <slave pid> <hostname> */ -#define GDM_SOP_XPID "XPID" /* <slave pid> <xpid> */ -#define GDM_SOP_SESSPID "SESSPID" /* <slave pid> <sesspid> */ -#define GDM_SOP_GREETPID "GREETPID" /* <slave pid> <greetpid> */ -#define GDM_SOP_CHOOSERPID "CHOOSERPID" /* <slave pid> <chooserpid> */ -#define GDM_SOP_LOGGED_IN "LOGGED_IN" /* <slave pid> <logged_in as int> */ -#define GDM_SOP_LOGIN "LOGIN" /* <slave pid> <username> */ -#define GDM_SOP_COOKIE "COOKIE" /* <slave pid> <cookie> */ -#define GDM_SOP_AUTHFILE "AUTHFILE" /* <slave pid> <authfile> */ -#define GDM_SOP_QUERYLOGIN "QUERYLOGIN" /* <slave pid> <username> */ -/* if user already logged in somewhere, the ack response will be - <display>,<migratable>,<display>,<migratable>,... */ -#define GDM_SOP_MIGRATE "MIGRATE" /* <slave pid> <display> */ -#define GDM_SOP_DISP_NUM "DISP_NUM" /* <slave pid> <display as int> */ -/* For Linux only currently */ -#define GDM_SOP_VT_NUM "VT_NUM" /* <slave pid> <vt as int> */ -#define GDM_SOP_FLEXI_ERR "FLEXI_ERR" /* <slave pid> <error num> */ - /* 3 = X failed */ - /* 4 = X too busy */ - /* 5 = Nest display can't connect */ -#define GDM_SOP_FLEXI_OK "FLEXI_OK" /* <slave pid> */ -#define GDM_SOP_SOFT_RESTART "SOFT_RESTART" /* no arguments */ -#define GDM_SOP_START_NEXT_LOCAL "START_NEXT_LOCAL" /* no arguments */ -#define GDM_SOP_HUP_ALL_GREETERS "HUP_ALL_GREETERS" /* no arguments */ - -/* stop waiting for this and go on with your life, useful with - the --wait-for-go command line option */ -#define GDM_SOP_GO "GO" /* no arguments */ - -/* sometimes we can't do a syslog so we tell the main daemon */ -#define GDM_SOP_SYSLOG "SYSLOG" /* <pid> <type> <message> */ - -/* write out a sessreg (xdm) compatible Xservers file - * in the ServAuthDir as <name>.Xservers */ -#define GDM_SOP_WRITE_X_SERVERS "WRITE_X_SERVERS" /* <slave pid> */ - -/* All X servers should be restarted rather then regenerated. Useful - * if you have updated the X configuration. Note that this happens - * only when the user logs out or when we otherwise would have restarted - * a server, nothing is done by this command. */ -#define GDM_SOP_DIRTY_SERVERS "DIRTY_SERVERS" /* no arguments */ - -/* restart all servers that people aren't logged in on. Maybe you may not - * want to do this on every change of X server config since this may cause - * flicker on screen and jumping around on the vt. Perhaps useful to do - * by asking the user if they want to do that. Note that this will not - * kill any logged in sessions. */ -#define GDM_SOP_SOFT_RESTART_SERVERS "SOFT_RESTART_SERVERS" /* no arguments */ -/* Suspend the machine if it is even allowed */ -#define GDM_SOP_SUSPEND_MACHINE "SUSPEND_MACHINE" /* no arguments */ -#define GDM_SOP_CHOSEN_THEME "CHOSEN_THEME" /* <slave pid> <theme name> */ - -/*Execute custom cmd*/ -#define GDM_SOP_CUSTOM_CMD "CUSTOM_CMD" /* <slave pid> <cmd id> */ - -/* Start a new standard X flexible server */ -#define GDM_SOP_FLEXI_XSERVER "FLEXI_XSERVER" /* no arguments */ - -#define GDM_SOP_SHOW_ERROR_DIALOG "SHOW_ERROR_DIALOG" /* show the error dialog from daemon */ -#define GDM_SOP_SHOW_YESNO_DIALOG "SHOW_YESNO_DIALOG" /* show the yesno dialog from daemon */ -#define GDM_SOP_SHOW_QUESTION_DIALOG "SHOW_QUESTION_DIALOG" /* show the question dialog from daemon */ -#define GDM_SOP_SHOW_ASKBUTTONS_DIALOG "SHOW_ASKBUTTON_DIALOG" /* show the askbutton dialog from daemon */ - - -/* Ack for a slave message */ -/* Note that an extra response can follow an 'ack' */ -#define GDM_SLAVE_NOTIFY_ACK 'A' -/* Update this key */ -#define GDM_SLAVE_NOTIFY_KEY '!' -/* notify a command */ -#define GDM_SLAVE_NOTIFY_COMMAND '#' -/* send the response */ -#define GDM_SLAVE_NOTIFY_RESPONSE 'R' -/* send the error dialog response */ -#define GDM_SLAVE_NOTIFY_ERROR_RESPONSE 'E' -/* send the yesno dialog response */ -#define GDM_SLAVE_NOTIFY_YESNO_RESPONSE 'Y' -/* send the askbuttons dialog response */ -#define GDM_SLAVE_NOTIFY_ASKBUTTONS_RESPONSE 'B' -/* send the question dialog response */ -#define GDM_SLAVE_NOTIFY_QUESTION_RESPONSE 'Q' - -/* - * Maximum number of messages allowed over the sockets protocol. This - * is set to 80 since the gdmlogin/gdmgreeter programs have ~60 config - * values that are pulled over the socket connection so it allows them - * all to be grabbed in one pull. - */ -#define GDM_SUP_MAX_MESSAGES 80 -#define GDM_SUP_SOCKET "/tmp/.gdm_socket" - -/* - * The user socket protocol. Each command is given on a separate line - * - * A user should first send a VERSION\n after connecting and only do - * anything else if gdm responds with the correct response. The version - * is the gdm version and not a "protocol" revision, so you can't check - * against a single version but check if the version is higher then some - * value. - * - * You can only send a few commands at a time, so if you keep getting error - * 200 try opening a new socket for every command you send. - * - * For a descriptions of the commands see: - * http://www.gnome.org/projects/gdm/docs/2.18/controlling.htlm - * - */ -/* The user protocol, using /tmp/.gdm_socket */ - - -#define GDM_SUP_VERSION "VERSION" -#define GDM_SUP_AUTH_LOCAL "AUTH_LOCAL" -#define GDM_SUP_FLEXI_XSERVER "FLEXI_XSERVER" -#define GDM_SUP_FLEXI_XSERVER_USER "FLEXI_XSERVER_USER" -#define GDM_SUP_FLEXI_XNEST "FLEXI_XNEST" -#define GDM_SUP_FLEXI_XNEST_USER "FLEXI_XNEST_USER" -#define GDM_SUP_ADD_DYNAMIC_DISPLAY "ADD_DYNAMIC_DISPLAY" -#define GDM_SUP_RELEASE_DYNAMIC_DISPLAYS "RELEASE_DYNAMIC_DISPLAYS" -#define GDM_SUP_REMOVE_DYNAMIC_DISPLAY "REMOVE_DYNAMIC_DISPLAY" -#define GDM_SUP_ATTACHED_SERVERS "ATTACHED_SERVERS" -#define GDM_SUP_CONSOLE_SERVERS "CONSOLE_SERVERS" -#define GDM_SUP_ALL_SERVERS "ALL_SERVERS" -#define GDM_SUP_GET_SERVER_LIST "GET_SERVER_LIST" -#define GDM_SUP_GET_SERVER_DETAILS "GET_SERVER_DETAILS" -#define GDM_SUP_GET_CONFIG "GET_CONFIG" -#define GDM_SUP_GET_CONFIG_FILE "GET_CONFIG_FILE" -#define GDM_SUP_GET_CUSTOM_CONFIG_FILE "GET_CUSTOM_CONFIG_FILE" -#define GDM_SUP_UPDATE_CONFIG "UPDATE_CONFIG" -#define GDM_SUP_GREETERPIDS "GREETERPIDS" -#define GDM_SUP_QUERY_LOGOUT_ACTION "QUERY_LOGOUT_ACTION" -#define GDM_SUP_QUERY_CUSTOM_CMD_LABELS "QUERY_CUSTOM_CMD_LABELS" -#define GDM_SUP_QUERY_CUSTOM_CMD_NO_RESTART_STATUS "QUERY_CUSTOM_CMD_NO_RESTART_STATUS" -#define GDM_SUP_SET_LOGOUT_ACTION "SET_LOGOUT_ACTION" -#define GDM_SUP_SET_SAFE_LOGOUT_ACTION "SET_SAFE_LOGOUT_ACTION" -#define GDM_SUP_LOGOUT_ACTION_NONE "NONE" -#define GDM_SUP_LOGOUT_ACTION_HALT "HALT" -#define GDM_SUP_LOGOUT_ACTION_REBOOT "REBOOT" -#define GDM_SUP_LOGOUT_ACTION_SUSPEND "SUSPEND" -#define GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "CUSTOM_CMD" -#define GDM_SUP_QUERY_VT "QUERY_VT" -#define GDM_SUP_SET_VT "SET_VT" -#define GDM_SUP_SERVER_BUSY "SERVER_BUSY" -#define GDM_SUP_GET_SERVER_DETAILS "GET_SERVER_DETAILS" -#define GDM_SUP_CLOSE "CLOSE" - -/* User flags for the SUP protocol */ -enum { - GDM_SUP_FLAG_AUTHENTICATED = 0x1, /* authenticated as a local user, - * from a local display we started */ - GDM_SUP_FLAG_AUTH_GLOBAL = 0x2 /* authenticated with global cookie */ -}; - -#endif /* _GDM_SOCKET_PROTOCOL_H */ diff --git a/daemon/gdm-xdmcp-manager.c b/daemon/gdm-xdmcp-manager.c deleted file mode 100644 index f5b21d6a..00000000 --- a/daemon/gdm-xdmcp-manager.c +++ /dev/null @@ -1,2931 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/utsname.h> - -#include <sys/socket.h> -#include <netdb.h> -#include <arpa/inet.h> -#include <net/if.h> -#ifdef HAVE_SYS_SOCKIO_H -#include <sys/sockio.h> -#endif - -#include <errno.h> - -#include <glib.h> -#include <glib/gi18n.h> -#include <glib-object.h> - -#include <X11/Xlib.h> -#include <X11/Xmd.h> -#include <X11/Xdmcp.h> - -#include "gdm-common.h" -#include "gdm-xdmcp-manager.h" - -#include "misc.h" -#include "auth.h" -#include "cookie.h" -#include "choose.h" -#include "gdm-daemon-config.h" - -/* - * On Sun, we need to define allow_severity and deny_severity to link - * against libwrap. - */ -#ifdef __sun -#include <syslog.h> -int allow_severity = LOG_INFO; -int deny_severity = LOG_WARNING; -#endif - -#define GDM_XDMCP_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_XDMCP_MANAGER, GdmXdmcpManagerPrivate)) - -#define DEFAULT_PORT 177 -#define DEFAULT_USE_MULTICAST FALSE -#define DEFAULT_MULTICAST_ADDRESS "ff02::1" -#define DEFAULT_HONOR_INDIRECT TRUE -#define DEFAULT_MAX_DISPLAYS_PER_HOST 2 -#define DEFAULT_MAX_DISPLAYS 16 -#define DEFAULT_MAX_PENDING_DISPLAYS 4 -#define DEFAULT_MAX_WAIT 15 - -#define GDM_MAX_FORWARD_QUERIES 10 -#define GDM_FORWARD_QUERY_TIMEOUT 30 -#define MANAGED_FORWARD_INTERVAL 1500 /* 1.5 seconds */ - -/* some extra XDMCP opcodes that xdm will happily ignore since they'll be - * the wrong XDMCP version anyway */ -#define GDM_XDMCP_PROTOCOL_VERSION 1001 -enum { - GDM_XDMCP_FIRST_OPCODE = 1000, /*just a marker, not an opcode */ - - GDM_XDMCP_MANAGED_FORWARD = 1000, - /* manager (master) -> manager - * A packet with MANAGED_FORWARD is sent to the - * manager that sent the forward query from the manager to - * which forward query was sent. It indicates that the forward - * was fully processed and that the client now has either - * a managed session, or has been sent denial, refuse or failed. - * (if the denial gets lost then client gets dumped into the - * chooser again). This should be resent a few times - * until some (short) timeout or until GOT_MANAGED_FORWARD - * is sent. GDM sends at most 3 packates with 1.5 seconds - * between each. - * - * Argument is ARRAY8 with the address of the originating host */ - GDM_XDMCP_GOT_MANAGED_FORWARD, - /* manager -> manager (master) - * A single packet with GOT_MANAGED_FORWARD is sent to indicate - * that we did receive the MANAGED_FORWARD packet. The argument - * must match the MANAGED_FORWARD one or it will just be ignored. - * - * Argument is ARRAY8 with the address of the originating host */ - GDM_XDMCP_LAST_OPCODE /*just a marker, not an opcode */ -}; - -/* - * We don't support XDM-AUTHENTICATION-1 and XDM-AUTHORIZATION-1. - * - * The latter would be quite useful to avoid sending unencrypted - * cookies over the wire. Unfortunately it isn't supported without - * XDM-AUTHENTICATION-1 which requires a key database with private - * keys from all X terminals on your LAN. Fun, fun, fun. - * - * Furthermore user passwords go over the wire in cleartext anyway, - * so protecting cookies is not that important. - */ - -typedef struct _XdmAuth { - ARRAY8 authentication; - ARRAY8 authorization; -} XdmAuthRec, *XdmAuthPtr; - -static XdmAuthRec serv_authlist = { - { (CARD16) 0, (CARD8 *) 0 }, - { (CARD16) 0, (CARD8 *) 0 } -}; - -/* NOTE: Timeout and max are hardcoded */ -typedef struct _GdmForwardQuery { - time_t acctime; - struct sockaddr_storage *dsp_sa; - struct sockaddr_storage *from_sa; -} GdmForwardQuery; - -typedef struct { - int times; - guint handler; - struct sockaddr_storage manager; - struct sockaddr_storage origin; - GdmXdmcpManager *xdmcp_manager; -} ManagedForward; - -struct GdmXdmcpManagerPrivate -{ - GSList *forward_queries; - GSList *managed_forwards; - - int socket_fd; - gint32 session_serial; - guint socket_watch_id; - XdmcpBuffer buf; - - guint num_sessions; - guint num_pending_sessions; - - char *sysid; - char *hostname; - ARRAY8 servhost; - - /* configuration */ - guint port; - gboolean use_multicast; - char *multicast_address; - gboolean honor_indirect; - char *willing_script; - guint max_displays_per_host; - guint max_displays; - guint max_pending_displays; - guint max_wait; -}; - -enum { - DISPLAY_ADDED, - DISPLAY_REMOVED, - LAST_SIGNAL -}; - -enum { - PROP_0, - PROP_PORT, - PROP_USE_MULTICAST, - PROP_MULTICAST_ADDRESS, - PROP_HONOR_INDIRECT, - PROP_WILLING_SCRIPT, - PROP_MAX_DISPLAYS_PER_HOST, - PROP_MAX_DISPLAYS, - PROP_MAX_PENDING_DISPLAYS, - PROP_MAX_WAIT, -}; - -static guint signals [LAST_SIGNAL] = { 0, }; - -static void gdm_xdmcp_manager_class_init (GdmXdmcpManagerClass *klass); -static void gdm_xdmcp_manager_init (GdmXdmcpManager *manager); -static void gdm_xdmcp_manager_finalize (GObject *object); - -static gpointer xdmcp_manager_object = NULL; - -G_DEFINE_TYPE (GdmXdmcpManager, gdm_xdmcp_manager, G_TYPE_OBJECT) - -/* Theory of operation: - * - * Process idles waiting for UDP packets on port 177. - * Incoming packets are decoded and checked against tcp_wrapper. - * - * A typical session looks like this: - * - * Display sends Query/BroadcastQuery to Manager. - * - * Manager selects an appropriate authentication scheme from the - * display's list of supported ones and sends Willing/Unwilling. - * - * Assuming the display accepts the auth. scheme it sends back a - * Request. - * - * If the manager accepts to service the display (i.e. loadavg is low) - * it sends back an Accept containing a unique SessionID. The - * SessionID is stored in an accept queue by the Manager. Should the - * manager refuse to start a session a Decline is sent to the display. - * - * The display returns a Manage request containing the supplied - * SessionID. The manager will then start a session on the display. In - * case the SessionID is not on the accept queue the manager returns - * Refuse. If the manager fails to open the display for connections - * Failed is returned. - * - * During the session the display periodically sends KeepAlive packets - * to the manager. The manager responds with Alive. - * - * Similarly the manager xpings the display once in a while and shuts - * down the connection on failure. - * - */ - -GQuark -gdm_xdmcp_manager_error_quark (void) -{ - static GQuark ret = 0; - if (ret == 0) { - ret = g_quark_from_static_string ("gdm_xdmcp_manager_error"); - } - - return ret; -} - -static gint32 -get_next_session_serial (GdmXdmcpManager *manager) -{ - gint32 serial; - - again: - if (manager->priv->session_serial != G_MAXINT32) { - serial = manager->priv->session_serial++; - } else { - serial = g_random_int (); - } - - if (serial == 0) { - goto again; - } - - return serial; -} - -/* for debugging */ -static const char * -ai_family_str (struct addrinfo *ai) -{ - const char *str; - switch (ai->ai_family) { - case AF_INET: - str = "inet"; - break; - case AF_INET6: - str = "inet6"; - break; - case AF_UNIX: - str = "unix"; - break; - case AF_UNSPEC: - str = "unspecified"; - break; - default: - str = "unknown"; - break; - } - return str; -} - -/* for debugging */ -static const char * -ai_type_str (struct addrinfo *ai) -{ - const char *str; - switch (ai->ai_socktype) { - case SOCK_STREAM: - str = "stream"; - break; - case SOCK_DGRAM: - str = "datagram"; - break; - case SOCK_SEQPACKET: - str = "seqpacket"; - break; - case SOCK_RAW: - str = "raw"; - break; - default: - str = "unknown"; - break; - } - return str; -} - -/* for debugging */ -static const char * -ai_protocol_str (struct addrinfo *ai) -{ - const char *str; - switch (ai->ai_protocol) { - case 0: - str = "default"; - break; - case IPPROTO_TCP: - str = "TCP"; - break; - case IPPROTO_UDP: - str = "UDP"; - break; - case IPPROTO_RAW: - str = "raw"; - break; - default: - str = "unknown"; - break; - } - - return str; -} - -/* for debugging */ -static char * -ai_flags_str (struct addrinfo *ai) -{ - GString *str; - - str = g_string_new (""); - if (ai->ai_flags == 0) { - g_string_append (str, "none"); - } else { - if (ai->ai_flags & AI_PASSIVE) { - g_string_append (str, "passive "); - } - if (ai->ai_flags & AI_CANONNAME) { - g_string_append (str, "canon "); - } - if (ai->ai_flags & AI_NUMERICHOST) { - g_string_append (str, "numhost "); - } - if (ai->ai_flags & AI_NUMERICSERV) { - g_string_append (str, "numserv "); - } - if (ai->ai_flags & AI_V4MAPPED) { - g_string_append (str, "v4mapped "); - } - if (ai->ai_flags & AI_ALL) { - g_string_append (str, "all "); - } - } - return g_string_free (str, FALSE); -} - -/* for debugging */ -static void -debug_addrinfo (struct addrinfo *ai) -{ - char *str; - str = ai_flags_str (ai); - g_debug ("XDMCP: addrinfo family=%s type=%s proto=%s flags=%s", - ai_family_str (ai), - ai_type_str (ai), - ai_protocol_str (ai), - str); - g_free (str); -} - -static int -create_socket (struct addrinfo *ai) -{ - int sock; - - sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock < 0) { - g_warning ("socket: %s", g_strerror (errno)); - return sock; - } - - if (bind (sock, ai->ai_addr, ai->ai_addrlen) < 0) { - g_warning ("bind: %s", g_strerror (errno)); - close (sock); - return -1; - } - - return sock; -} - -static int -do_bind (guint port, - int family, - struct sockaddr_storage * hostaddr) -{ - struct addrinfo hints; - struct addrinfo *ai_list; - struct addrinfo *ai; - char strport[NI_MAXSERV]; - int gaierr; - int sock; - - sock = -1; - - memset (&hints, 0, sizeof (hints)); - hints.ai_family = family; - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_PASSIVE; - - snprintf (strport, sizeof (strport), "%u", port); - if ((gaierr = getaddrinfo (NULL, strport, &hints, &ai_list)) != 0) { - g_error ("Unable to connect to socket: %s", gai_strerror (gaierr)); - return -1; - } - - /* should only be one but.. */ - for (ai = ai_list; ai != NULL; ai = ai->ai_next) { - if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { - continue; - } - - debug_addrinfo (ai); - - if (sock < 0) { - char *host; - char *serv; - - gdm_address_get_info ((struct sockaddr_storage *)ai->ai_addr, &host, &serv); - g_debug ("XDMCP: Attempting to bind to host %s port %s", host, serv); - g_free (host); - g_free (serv); - sock = create_socket (ai); - if (sock >= 0) { - if (hostaddr != NULL) { - memcpy (hostaddr, ai->ai_addr, ai->ai_addrlen); - } - } - } - } - - freeaddrinfo (ai_list); - - return sock; -} - -static void -setup_multicast (GdmXdmcpManager *manager) -{ -#ifdef ENABLE_IPV6 - /* Checking and Setting Multicast options */ - { - /* - * socktemp is a temporary socket for getting info about - * available interfaces - */ - int socktemp; - int i; - int num; - char *buf; - struct ipv6_mreq mreq; - - /* For interfaces' list */ - struct ifconf ifc; - struct ifreq *ifr; - - socktemp = socket (AF_INET, SOCK_DGRAM, 0); -#ifdef SIOCGIFNUM - if (ioctl (socktemp, SIOCGIFNUM, &num) < 0) { - num = 64; - } -#else - num = 64; -#endif /* SIOCGIFNUM */ - ifc.ifc_len = sizeof (struct ifreq) * num; - ifc.ifc_buf = buf = malloc (ifc.ifc_len); - - if (ioctl (socktemp, SIOCGIFCONF, &ifc) >= 0) { - ifr = ifc.ifc_req; - num = ifc.ifc_len / sizeof (struct ifreq); /* No of interfaces */ - - /* Joining multicast group with all interfaces */ - for (i = 0 ; i < num ; i++) { - struct ifreq ifreq; - int ifindex; - - memset (&ifreq, 0, sizeof (ifreq)); - strncpy (ifreq.ifr_name, ifr[i].ifr_name, sizeof (ifreq.ifr_name)); - /* paranoia */ - ifreq.ifr_name[sizeof (ifreq.ifr_name) - 1] = '\0'; - - if (ioctl (socktemp, SIOCGIFFLAGS, &ifreq) < 0) { - g_debug ("XDMCP: Could not get SIOCGIFFLAGS for %s", - ifr[i].ifr_name); - } - - ifindex = if_nametoindex (ifr[i].ifr_name); - - if ((!(ifreq.ifr_flags & IFF_UP) || - (ifreq.ifr_flags & IFF_LOOPBACK)) || - ((ifindex == 0 ) && (errno == ENXIO))) { - /* Not a valid interface or loopback interface*/ - continue; - } - - mreq.ipv6mr_interface = ifindex; - inet_pton (AF_INET6, - manager->priv->multicast_address, - &mreq.ipv6mr_multiaddr); - - setsockopt (manager->priv->socket_fd, - IPPROTO_IPV6, - IPV6_JOIN_GROUP, - &mreq, - sizeof (mreq)); - } - } - g_free (buf); - close (socktemp); - } -#endif /* ENABLE_IPV6 */ -} - -static gboolean -open_port (GdmXdmcpManager *manager) -{ - struct sockaddr_storage serv_sa = { 0 }; - - g_debug ("XDMCP: Start up on host %s, port %d", - manager->priv->hostname, - manager->priv->port); - - /* Open socket for communications */ -#ifdef ENABLE_IPV6 - manager->priv->socket_fd = do_bind (manager->priv->port, AF_INET6, &serv_sa); - if (manager->priv->socket_fd < 0) -#endif - manager->priv->socket_fd = do_bind (manager->priv->port, AF_INET, &serv_sa); - - if G_UNLIKELY (manager->priv->socket_fd < 0) { - g_warning (_("Could not create socket!")); - return FALSE; - } - - if (manager->priv->use_multicast) { - setup_multicast (manager); - } - - return TRUE; -} - -static gboolean -gdm_xdmcp_host_allow (struct sockaddr_storage *clnt_sa) -{ -#ifdef HAVE_TCPWRAPPERS - - /* - * Avoids a warning, my tcpd.h file doesn't include this prototype, even - * though the library does include the function and the manpage mentions it - */ - extern int hosts_ctl (char *daemon, - char *client_name, - char *client_addr, - char *client_user); - - GdmHostent *client_he; - char *client; - gboolean ret; - char *host; - - /* Find client hostname */ - client_he = gdm_gethostbyaddr (clnt_sa); - - if (client_he->not_found) { - client = "unknown"; - } else { - g_debug ("gdm_xdmcp_host_allow: client->hostname is %s\n", - client_he->hostname); - client = client_he->hostname; - } - - /* Check with tcp_wrappers if client is allowed to access */ - host = NULL; - gdm_address_get_info (clnt_sa, &host, NULL); - ret = hosts_ctl ("gdm", client, host, ""); - g_free (host); - - gdm_hostent_free (client_he); - - return ret; -#else /* HAVE_TCPWRAPPERS */ - return (TRUE); -#endif /* HAVE_TCPWRAPPERS */ -} - -static int -gdm_xdmcp_num_displays_from_host (GdmXdmcpManager *manager, - struct sockaddr_storage *addr) -{ - GSList *li; - int count = 0; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (SERVER_IS_XDMCP (disp)) { - if (gdm_address_equal (&disp->addr, addr)) { - count++; - } - } - } - return count; -} - -static GdmDisplay * -gdm_xdmcp_display_lookup_by_host (GdmXdmcpManager *manager, - struct sockaddr_storage *addr, - int dspnum) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (SERVER_IS_XDMCP (disp)) { - - if (gdm_address_equal (&disp->addr, addr) - && disp->xdmcp_dispnum == dspnum) { - return disp; - } - } - } - - return NULL; -} - -static char * -get_willing_output (GdmXdmcpManager *manager) -{ - char *output; - char **argv; - FILE *fd; - char buf[256]; - - output = NULL; - buf[0] = '\0'; - - if (manager->priv->willing_script == NULL) { - goto out; - } - - argv = NULL; - if (! g_shell_parse_argv (manager->priv->willing_script, NULL, &argv, NULL)) { - goto out; - } - - if (argv == NULL || - argv[0] == NULL || - g_access (argv[0], X_OK) != 0) { - goto out; - } - - fd = popen (manager->priv->willing_script, "r"); - if (fd == NULL) { - goto out; - } - - if (fgets (buf, sizeof (buf), fd) == NULL) { - pclose (fd); - goto out; - } - - pclose (fd); - - output = g_strdup (buf); - - out: - return output; -} - -static void -gdm_xdmcp_send_willing (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa) -{ - ARRAY8 status; - XdmcpHeader header; - static char *last_status = NULL; - static time_t last_willing = 0; - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("XDMCP: Sending WILLING to %s", host); - g_free (host); - - if (last_willing == 0 || time (NULL) - 3 > last_willing) { - char *s; - - g_free (last_status); - - s = get_willing_output (manager); - if (s != NULL) { - g_free (last_status); - last_status = s; - } else { - last_status = g_strdup (manager->priv->sysid); - } - } - - if (! gdm_address_is_local (clnt_sa) && - gdm_xdmcp_num_displays_from_host (manager, clnt_sa) >= manager->priv->max_displays_per_host) { - /* - * Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii - */ - status.data = (CARD8 *) g_strdup_printf ("%s (Server is busy)", - last_status); - } else { - status.data = (CARD8 *) g_strdup (last_status); - } - - status.length = strlen ((char *) status.data); - - header.opcode = (CARD16) WILLING; - header.length = 6 + serv_authlist.authentication.length; - header.length += manager->priv->servhost.length + status.length; - header.version = XDM_PROTOCOL_VERSION; - XdmcpWriteHeader (&manager->priv->buf, &header); - - /* Hardcoded authentication */ - XdmcpWriteARRAY8 (&manager->priv->buf, &serv_authlist.authentication); - XdmcpWriteARRAY8 (&manager->priv->buf, &manager->priv->servhost); - XdmcpWriteARRAY8 (&manager->priv->buf, &status); - - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); - - g_free (status.data); -} - -static void -gdm_xdmcp_send_unwilling (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int type) -{ - ARRAY8 status; - XdmcpHeader header; - static time_t last_time = 0; - char *host; - - /* only send at most one packet per second, - no harm done if we don't send it at all */ - if (last_time + 1 >= time (NULL)) { - return; - } - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("XDMCP: Sending UNWILLING to %s", host); - g_warning (_("Denied XDMCP query from host %s"), host); - g_free (host); - - /* - * Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii - */ - status.data = (CARD8 *) "Display not authorized to connect"; - status.length = strlen ((char *) status.data); - - header.opcode = (CARD16) UNWILLING; - header.length = 4 + manager->priv->servhost.length + status.length; - header.version = XDM_PROTOCOL_VERSION; - XdmcpWriteHeader (&manager->priv->buf, &header); - - XdmcpWriteARRAY8 (&manager->priv->buf, &manager->priv->servhost); - XdmcpWriteARRAY8 (&manager->priv->buf, &status); - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); - - last_time = time (NULL); -} - -#define SIN(__s) ((struct sockaddr_in *) __s) -#define SIN6(__s) ((struct sockaddr_in6 *) __s) - -static void -set_port_for_request (struct sockaddr_storage *ss, - ARRAY8 *port) -{ - /* we depend on this being 2 elsewhere as well */ - port->length = 2; - - switch (ss->ss_family) { - case AF_INET: - port->data = (CARD8 *)g_memdup (&(SIN (ss)->sin_port), port->length); - break; - case AF_INET6: - port->data = (CARD8 *)g_memdup (&(SIN6 (ss)->sin6_port), port->length); - break; - default: - port->data = NULL; - break; - } -} - -static void -set_address_for_request (struct sockaddr_storage *ss, - ARRAY8 *address) -{ - - switch (ss->ss_family) { - case AF_INET: - address->length = sizeof (struct in_addr); - address->data = g_memdup (&SIN (ss)->sin_addr, address->length); - break; - case AF_INET6: - address->length = sizeof (struct in6_addr); - address->data = g_memdup (&SIN6 (ss)->sin6_addr, address->length); - break; - default: - address->length = 0; - address->data = NULL; - break; - } - -} - -static void -gdm_xdmcp_send_forward_query (GdmXdmcpManager *manager, - GdmIndirectDisplay *id, - struct sockaddr_storage *clnt_sa, - struct sockaddr_storage *display_addr, - ARRAYofARRAY8Ptr authlist) -{ - struct sockaddr_storage *sa; - XdmcpHeader header; - int i; - ARRAY8 address; - ARRAY8 port; - char *host; - char *serv; - - g_assert (id != NULL); - g_assert (id->chosen_host != NULL); - - gdm_address_get_info (id->chosen_host, &host, NULL); - g_debug ("XDMCP: Sending forward query to %s", - host); - g_free (host); - - gdm_address_get_info (display_addr, &host, &serv); - g_debug ("gdm_xdmcp_send_forward_query: Query contains %s:%s", - host, serv); - g_free (host); - g_free (serv); - - set_port_for_request (clnt_sa, &port); - set_address_for_request (display_addr, &address); - - sa = g_memdup (id->chosen_host, sizeof (id->chosen_host)); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) FORWARD_QUERY; - header.length = 0; - header.length += 2 + address.length; - header.length += 2 + port.length; - header.length += 1; - for (i = 0; i < authlist->length; i++) { - header.length += 2 + authlist->data[i].length; - } - - XdmcpWriteHeader (&manager->priv->buf, &header); - XdmcpWriteARRAY8 (&manager->priv->buf, &address); - XdmcpWriteARRAY8 (&manager->priv->buf, &port); - XdmcpWriteARRAYofARRAY8 (&manager->priv->buf, authlist); - - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr) sa, - (int)sizeof (struct sockaddr_storage)); - - g_free (port.data); - g_free (address.data); - g_free (sa); -} - -static void -handle_any_query (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - ARRAYofARRAY8Ptr authentication_names, - int type) -{ - gdm_xdmcp_send_willing (manager, clnt_sa); -} - -static void -handle_direct_query (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len, - int type) -{ - ARRAYofARRAY8 clnt_authlist; - int expected_len; - int i; - int res; - - res = XdmcpReadARRAYofARRAY8 (&manager->priv->buf, &clnt_authlist); - if G_UNLIKELY (! res) { - g_warning (_("Could not extract authlist from packet")); - return; - } - - expected_len = 1; - - for (i = 0 ; i < clnt_authlist.length ; i++) { - expected_len += 2 + clnt_authlist.data[i].length; - } - - if (len == expected_len) { - handle_any_query (manager, clnt_sa, &clnt_authlist, type); - } else { - g_warning (_("Error in checksum")); - } - - XdmcpDisposeARRAYofARRAY8 (&clnt_authlist); -} - -static void -gdm_xdmcp_handle_broadcast_query (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - if (gdm_xdmcp_host_allow (clnt_sa)) { - handle_direct_query (manager, clnt_sa, len, BROADCAST_QUERY); - } else { - /* just ignore it */ - } -} - -static void -gdm_xdmcp_handle_query (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - if (gdm_xdmcp_host_allow (clnt_sa)) { - handle_direct_query (manager, clnt_sa, len, QUERY); - } else { - gdm_xdmcp_send_unwilling (manager, clnt_sa, QUERY); - } -} - -static void -gdm_xdmcp_handle_indirect_query (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - ARRAYofARRAY8 clnt_authlist; - int expected_len; - int i; - int res; - - if (! gdm_xdmcp_host_allow (clnt_sa)) { - /* ignore the request */ - return; - } - - if (! manager->priv->honor_indirect) { - /* ignore it */ - return; - } - - res = XdmcpReadARRAYofARRAY8 (&manager->priv->buf, &clnt_authlist); - if G_UNLIKELY (! res) { - g_warning (_("Could not extract authlist from packet")); - return; - } - - expected_len = 1; - - for (i = 0 ; i < clnt_authlist.length ; i++) { - expected_len += 2 + clnt_authlist.data[i].length; - } - - /* Try to look up the display in - * the pending list. If found send a FORWARD_QUERY to the - * chosen manager. Otherwise alloc a new indirect display. */ - - if (len == expected_len) { - GdmIndirectDisplay *id; - - id = gdm_choose_indirect_lookup (clnt_sa); - - if (id != NULL && id->chosen_host != NULL) { - /* if user chose us, then just send willing */ - if (gdm_address_is_local (id->chosen_host)) { - /* get rid of indirect, so that we don't get - * the chooser */ - gdm_choose_indirect_dispose (id); - gdm_xdmcp_send_willing (manager, clnt_sa); - } else if (gdm_address_is_loopback (clnt_sa)) { - /* woohoo! fun, I have no clue how to get - * the correct ip, SO I just send forward - * queries with all the different IPs */ - const GList *list = gdm_address_peek_local_list (); - - while (list != NULL) { - struct sockaddr_storage *saddr = list->data; - - if (! gdm_address_is_loopback (saddr)) { - /* forward query to * chosen host */ - gdm_xdmcp_send_forward_query (manager, - id, - clnt_sa, - saddr, - &clnt_authlist); - } - - list = list->next; - } - } else { - /* or send forward query to chosen host */ - gdm_xdmcp_send_forward_query (manager, - id, - clnt_sa, - clnt_sa, - &clnt_authlist); - } - } else if (id == NULL) { - id = gdm_choose_indirect_alloc (clnt_sa); - if (id != NULL) { - gdm_xdmcp_send_willing (manager, clnt_sa); - } - } else { - gdm_xdmcp_send_willing (manager, clnt_sa); - } - - } else { - g_warning (_("Error in checksum")); - } - - XdmcpDisposeARRAYofARRAY8 (&clnt_authlist); -} - -static void -gdm_forward_query_dispose (GdmXdmcpManager *manager, - GdmForwardQuery *q) -{ - if (q == NULL) { - return; - } - - manager->priv->forward_queries = g_slist_remove (manager->priv->forward_queries, q); - - q->acctime = 0; - - { - char *host; - - gdm_address_get_info (q->dsp_sa, &host, NULL); - g_debug ("gdm_forward_query_dispose: Disposing %s", host); - g_free (host); - } - - g_free (q->dsp_sa); - q->dsp_sa = NULL; - g_free (q->from_sa); - q->from_sa = NULL; - - g_free (q); -} - -static gboolean -remove_oldest_forward (GdmXdmcpManager *manager) -{ - GSList *li; - GdmForwardQuery *oldest = NULL; - - for (li = manager->priv->forward_queries; li != NULL; li = li->next) { - GdmForwardQuery *query = li->data; - - if (oldest == NULL || query->acctime < oldest->acctime) { - oldest = query; - } - } - - if (oldest != NULL) { - gdm_forward_query_dispose (manager, oldest); - return TRUE; - } else { - return FALSE; - } -} - -static GdmForwardQuery * -gdm_forward_query_alloc (GdmXdmcpManager *manager, - struct sockaddr_storage *mgr_sa, - struct sockaddr_storage *dsp_sa) -{ - GdmForwardQuery *q; - int count; - - count = g_slist_length (manager->priv->forward_queries); - - while (count > GDM_MAX_FORWARD_QUERIES && remove_oldest_forward (manager)) { - count--; - } - - q = g_new0 (GdmForwardQuery, 1); - q->dsp_sa = g_memdup (dsp_sa, sizeof (struct sockaddr_storage)); - q->from_sa = g_memdup (mgr_sa, sizeof (struct sockaddr_storage)); - - manager->priv->forward_queries = g_slist_prepend (manager->priv->forward_queries, q); - - return q; -} - -static GdmForwardQuery * -gdm_forward_query_lookup (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa) -{ - GSList *li; - GSList *qlist; - GdmForwardQuery *q; - time_t curtime; - - curtime = time (NULL); - - qlist = g_slist_copy (manager->priv->forward_queries); - - for (li = qlist; li != NULL; li = li->next) { - q = (GdmForwardQuery *) li->data; - - if (q == NULL) - continue; - - if (gdm_address_equal (q->dsp_sa, clnt_sa)) { - g_slist_free (qlist); - return q; - } - - if (q->acctime > 0 && curtime > q->acctime + GDM_FORWARD_QUERY_TIMEOUT) { - char *host; - char *serv; - - gdm_address_get_info (q->dsp_sa, &host, &serv); - - g_debug ("gdm_forward_query_lookup: Disposing stale forward query from %s:%s", - host, serv); - g_free (host); - g_free (serv); - - gdm_forward_query_dispose (manager, q); - continue; - } - } - - g_slist_free (qlist); - - { - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("gdm_forward_query_lookup: Host %s not found", - host); - g_free (host); - } - - return NULL; -} - -static gboolean -create_sa_from_request (ARRAY8 *req_addr, - ARRAY8 *req_port, - int family, - struct sockaddr_storage **sap) -{ - uint16_t port; - char host_buf [NI_MAXHOST]; - char serv_buf [NI_MAXSERV]; - char *serv; - const char *host; - struct addrinfo hints; - struct addrinfo *ai_list; - struct addrinfo *ai; - int gaierr; - gboolean found; - - if (sap != NULL) { - *sap = NULL; - } - - if (req_addr == NULL) { - return FALSE; - } - - serv = NULL; - if (req_port != NULL) { - /* port must always be length 2 */ - if (req_port->length != 2) { - return FALSE; - } - - memcpy (&port, req_port->data, 2); - snprintf (serv_buf, sizeof (serv_buf), "%d", ntohs (port)); - serv = serv_buf; - } else { - /* assume XDM_UDP_PORT */ - snprintf (serv_buf, sizeof (serv_buf), "%d", XDM_UDP_PORT); - serv = serv_buf; - } - - host = NULL; - if (req_addr->length == 4) { - host = inet_ntop (AF_INET, - (const void *)req_addr->data, - host_buf, - sizeof (host_buf)); - } else if (req_addr->length == 16) { - host = inet_ntop (AF_INET6, - (const void *)req_addr->data, - host_buf, - sizeof (host_buf)); - } - - if (host == NULL) { - g_warning (_("Bad address")); - return FALSE; - } - - memset (&hints, 0, sizeof (hints)); - hints.ai_family = family; - hints.ai_flags = AI_V4MAPPED; /* this should convert IPv4 address to IPv6 if needed */ - if ((gaierr = getaddrinfo (host, serv, &hints, &ai_list)) != 0) { - g_warning ("Unable get address: %s", gai_strerror (gaierr)); - return FALSE; - } - - /* just take the first one */ - ai = ai_list; - - found = FALSE; - if (ai != NULL) { - found = TRUE; - if (sap != NULL) { - *sap = g_memdup (ai->ai_addr, ai->ai_addrlen); - } - } - - freeaddrinfo (ai_list); - - return found; -} - -static void -gdm_xdmcp_whack_queued_managed_forwards (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - struct sockaddr_storage *origin) -{ - GSList *li; - - for (li = manager->priv->managed_forwards; li != NULL; li = li->next) { - ManagedForward *mf = li->data; - - if (gdm_address_equal (&mf->manager, clnt_sa) && - gdm_address_equal (&mf->origin, origin)) { - manager->priv->managed_forwards = g_slist_remove_link (manager->priv->managed_forwards, li); - g_slist_free_1 (li); - g_source_remove (mf->handler); - /* mf freed by glib */ - return; - } - } -} - -static void -gdm_xdmcp_handle_forward_query (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - ARRAY8 clnt_addr; - ARRAY8 clnt_port; - ARRAYofARRAY8 clnt_authlist; - int i; - int explen; - struct sockaddr_storage *disp_sa; - char *host; - char *serv; - - disp_sa = NULL; - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - - g_warning ("%s: Got FORWARD_QUERY from banned host %s", - "gdm_xdmcp_handle_forward query", - host); - g_free (host); - return; - } - - /* Read display address */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&manager->priv->buf, &clnt_addr)) { - g_warning (_("%s: Could not read display address"), - "gdm_xdmcp_handle_forward_query"); - return; - } - - /* Read display port */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&manager->priv->buf, &clnt_port)) { - XdmcpDisposeARRAY8 (&clnt_addr); - g_warning (_("%s: Could not read display port number"), - "gdm_xdmcp_handle_forward_query"); - return; - } - - /* Extract array of authentication names from Xdmcp packet */ - if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&manager->priv->buf, &clnt_authlist)) { - XdmcpDisposeARRAY8 (&clnt_addr); - XdmcpDisposeARRAY8 (&clnt_port); - g_warning (_("%s: Could not extract authlist from packet"), - "gdm_xdmcp_handle_forward_query"); - return; - } - - /* Crude checksumming */ - explen = 1; - explen += 2 + clnt_addr.length; - explen += 2 + clnt_port.length; - - for (i = 0 ; i < clnt_authlist.length ; i++) { - char *s = g_strndup ((char *) clnt_authlist.data[i].data, - clnt_authlist.length); - g_debug ("gdm_xdmcp_handle_forward_query: authlist: %s", s); - g_free (s); - - explen += 2 + clnt_authlist.data[i].length; - } - - if G_UNLIKELY (len != explen) { - g_warning (_("%s: Error in checksum"), - "gdm_xdmcp_handle_forward_query"); - goto out; - } - - if (! create_sa_from_request (&clnt_addr, &clnt_port, clnt_sa->ss_family, &disp_sa)) { - g_warning ("Unable to parse address for request"); - goto out; - } - - gdm_xdmcp_whack_queued_managed_forwards (manager, - clnt_sa, - disp_sa); - - gdm_address_get_info (disp_sa, &host, &serv); - g_debug ("gdm_xdmcp_handle_forward_query: Got FORWARD_QUERY for display: %s, port %s", - host, serv); - g_free (host); - g_free (serv); - - /* Check with tcp_wrappers if display is allowed to access */ - if (gdm_xdmcp_host_allow (disp_sa)) { - GdmForwardQuery *q; - - q = gdm_forward_query_lookup (manager, disp_sa); - if (q != NULL) - gdm_forward_query_dispose (manager, q); - - gdm_forward_query_alloc (manager, clnt_sa, disp_sa); - - gdm_xdmcp_send_willing (manager, disp_sa); - } - - out: - - g_free (disp_sa); - XdmcpDisposeARRAYofARRAY8 (&clnt_authlist); - XdmcpDisposeARRAY8 (&clnt_port); - XdmcpDisposeARRAY8 (&clnt_addr); -} - -static void -gdm_xdmcp_really_send_managed_forward (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - struct sockaddr_storage *origin) -{ - ARRAY8 address; - XdmcpHeader header; - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("XDMCP: Sending MANAGED_FORWARD to %s", host); - g_free (host); - - set_address_for_request (origin, &address); - - header.opcode = (CARD16) GDM_XDMCP_MANAGED_FORWARD; - header.length = 4 + address.length; - header.version = GDM_XDMCP_PROTOCOL_VERSION; - XdmcpWriteHeader (&manager->priv->buf, &header); - - XdmcpWriteARRAY8 (&manager->priv->buf, &address); - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); - - g_free (address.data); -} - -static gboolean -managed_forward_handler (ManagedForward *mf) -{ - if (mf->xdmcp_manager->priv->socket_fd > 0) { - gdm_xdmcp_really_send_managed_forward (mf->xdmcp_manager, - &(mf->manager), - &(mf->origin)); - } - - mf->times++; - if (mf->xdmcp_manager->priv->socket_fd <= 0 || mf->times >= 2) { - mf->xdmcp_manager->priv->managed_forwards = g_slist_remove (mf->xdmcp_manager->priv->managed_forwards, mf); - mf->handler = 0; - /* mf freed by glib */ - return FALSE; - } - return TRUE; -} - -static void -gdm_xdmcp_send_managed_forward (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - struct sockaddr_storage *origin) -{ - ManagedForward *mf; - - gdm_xdmcp_really_send_managed_forward (manager, clnt_sa, origin); - - mf = g_new0 (ManagedForward, 1); - mf->times = 0; - mf->xdmcp_manager = manager; - - memcpy (&(mf->manager), clnt_sa, sizeof (struct sockaddr_storage)); - memcpy (&(mf->origin), origin, sizeof (struct sockaddr_storage)); - - mf->handler = g_timeout_add_full (G_PRIORITY_DEFAULT, - MANAGED_FORWARD_INTERVAL, - (GSourceFunc)managed_forward_handler, - mf, - (GDestroyNotify) g_free); - manager->priv->managed_forwards = g_slist_prepend (manager->priv->managed_forwards, mf); -} - -static void -gdm_xdmcp_send_got_managed_forward (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - struct sockaddr_storage *origin) -{ - ARRAY8 address; - XdmcpHeader header; - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("XDMCP: Sending GOT_MANAGED_FORWARD to %s", host); - g_free (host); - - set_address_for_request (origin, &address); - - header.opcode = (CARD16) GDM_XDMCP_GOT_MANAGED_FORWARD; - header.length = 4 + address.length; - header.version = GDM_XDMCP_PROTOCOL_VERSION; - XdmcpWriteHeader (&manager->priv->buf, &header); - - XdmcpWriteARRAY8 (&manager->priv->buf, &address); - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); -} - -static void -gdm_xdmcp_recount_sessions (GdmXdmcpManager *manager) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - manager->priv->num_sessions = 0; - manager->priv->num_pending_sessions = 0; - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - if (SERVER_IS_XDMCP (d)) { - if (d->dispstat == XDMCP_MANAGED) - manager->priv->num_sessions++; - else if (d->dispstat == XDMCP_PENDING) - manager->priv->num_pending_sessions++; - } - } -} - -static void -do_dispose (GdmXdmcpManager *manager, - GdmDisplay *d) -{ - - gdm_display_dispose (d); - gdm_xdmcp_recount_sessions (manager); -} - -static void -gdm_xdmcp_displays_purge (GdmXdmcpManager *manager) -{ - GSList *dlist; - time_t curtime = time (NULL); - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - dlist = displays; - while (dlist != NULL) { - GdmDisplay *d = dlist->data; - - if (d != NULL && - SERVER_IS_XDMCP (d) && - d->dispstat == XDMCP_PENDING && - curtime > d->acctime + manager->priv->max_wait) { - g_debug ("gdm_xdmcp_displays_purge: Disposing session id %ld", - (long)d->sessionid); - do_dispose (manager, d); - - /* restart as the list is now broken */ - dlist = displays; - } else { - /* just go on */ - dlist = dlist->next; - } - } -} - -static void -gdm_xdmcp_display_dispose_check (GdmXdmcpManager *manager, - const char *hostname, - int dspnum) -{ - GSList *dlist; - GSList *displays; - - if (hostname == NULL) { - return; - } - - g_debug ("gdm_xdmcp_display_dispose_check (%s:%d)", hostname, dspnum); - - displays = gdm_daemon_config_get_display_list (); - - dlist = displays; - while (dlist != NULL) { - GdmDisplay *d = dlist->data; - - if (d != NULL && - SERVER_IS_XDMCP (d) && - d->xdmcp_dispnum == dspnum && - strcmp (d->hostname, hostname) == 0) { - - if (d->dispstat == XDMCP_MANAGED) { - gdm_display_unmanage (d); - } else { - do_dispose (manager, d); - } - - /* restart as the list is now broken */ - dlist = displays; - } else { - /* just go on */ - dlist = dlist->next; - } - } -} - -static void -gdm_xdmcp_send_decline (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - const char *reason) -{ - XdmcpHeader header; - ARRAY8 authentype; - ARRAY8 authendata; - ARRAY8 status; - GdmForwardQuery *fq; - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("XMDCP: Sending DECLINE to %s", host); - g_free (host); - - authentype.data = (CARD8 *) 0; - authentype.length = (CARD16) 0; - - authendata.data = (CARD8 *) 0; - authendata.length = (CARD16) 0; - - status.data = (CARD8 *) reason; - status.length = strlen ((char *) status.data); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) DECLINE; - header.length = 2 + status.length; - header.length += 2 + authentype.length; - header.length += 2 + authendata.length; - - XdmcpWriteHeader (&manager->priv->buf, &header); - XdmcpWriteARRAY8 (&manager->priv->buf, &status); - XdmcpWriteARRAY8 (&manager->priv->buf, &authentype); - XdmcpWriteARRAY8 (&manager->priv->buf, &authendata); - - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); - - /* Send MANAGED_FORWARD to indicate that the connection - * reached some sort of resolution */ - fq = gdm_forward_query_lookup (manager, clnt_sa); - if (fq != NULL) { - gdm_xdmcp_send_managed_forward (manager, fq->from_sa, clnt_sa); - gdm_forward_query_dispose (manager, fq); - } -} - -static GdmDisplay * -gdm_xdmcp_display_alloc (GdmXdmcpManager *manager, - struct sockaddr_storage *addr, - GdmHostent *he /* eaten and freed */, - int displaynum) -{ - GdmDisplay *d = NULL; - const char *proxycmd; - gboolean use_proxy = FALSE; - - proxycmd = NULL; - use_proxy = FALSE; -#if 0 - proxycmd = gdm_daemon_config_get_value_string (GDM_KEY_XDMCP_PROXY_XSERVER); - use_proxy = FALSE; -#endif - d = g_new0 (GdmDisplay, 1); - - if (use_proxy && proxycmd != NULL) { - d->type = TYPE_XDMCP_PROXY; - d->command = g_strdup (proxycmd); - g_debug ("Using proxy server for XDMCP: %s\n", d->command); - } else { - d->type = TYPE_XDMCP; - } - - d->logout_action = GDM_LOGOUT_ACTION_NONE; - d->authfile = NULL; - d->auths = NULL; - d->userauth = NULL; - d->greetpid = 0; - d->servpid = 0; - d->servstat = 0; - d->sesspid = 0; - d->slavepid = 0; - d->attached = FALSE; - d->dispstat = XDMCP_PENDING; - d->sessionid = get_next_session_serial (manager); - - d->acctime = time (NULL); - d->dispnum = displaynum; - d->xdmcp_dispnum = displaynum; - - d->handled = TRUE; - d->tcp_disallowed = FALSE; - d->vt = -1; - d->x_servers_order = -1; - d->logged_in = FALSE; - d->login = NULL; - d->sleep_before_run = 0; - - if (gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN) && - ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN))) { - d->timed_login_ok = TRUE; - } else { - d->timed_login_ok = FALSE; - } - - d->name = g_strdup_printf ("%s:%d", - he->hostname, - displaynum); - - memcpy (&d->addr, addr, sizeof (struct sockaddr_storage)); - - d->hostname = he->hostname; - he->hostname = NULL; - d->addrs = he->addrs; - he->addrs = NULL; - d->addr_count = he->addr_count; - he->addr_count = 0; - - gdm_hostent_free (he); - - d->slave_notify_fd = -1; - d->master_notify_fd = -1; - d->xsession_errors_bytes = 0; - d->xsession_errors_fd = -1; - d->session_output_fd = -1; - d->chooser_output_fd = -1; - d->chooser_last_line = NULL; - d->theme_name = NULL; - - /* Secure display with cookie */ - if G_UNLIKELY (! gdm_auth_secure_display (d)) { - g_warning ("gdm_xdmcp_display_alloc: Error setting up cookies for %s", - d->name); - } - - if (d->type == TYPE_XDMCP_PROXY) { - d->parent_disp = d->name; - d->name = g_strdup (":-1"); - d->dispnum = -1; - d->server_uid = gdm_daemon_config_get_gdmuid (); - d->parent_auth_file = d->authfile; - d->authfile = NULL; - } - - gdm_daemon_config_display_list_append (d); - - manager->priv->num_pending_sessions++; - - g_debug ("gdm_xdmcp_display_alloc: display=%s, session id=%ld, xdmcp_pending=%d", - d->name, (long)d->sessionid, manager->priv->num_pending_sessions); - - return d; -} - -static void -gdm_xdmcp_send_accept (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - CARD32 session_id, - ARRAY8Ptr authentication_name, - ARRAY8Ptr authentication_data, - ARRAY8Ptr authorization_name, - ARRAY8Ptr authorization_data) -{ - XdmcpHeader header; - char *host; - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) ACCEPT; - header.length = 4; - header.length += 2 + authentication_name->length; - header.length += 2 + authentication_data->length; - header.length += 2 + authorization_name->length; - header.length += 2 + authorization_data->length; - - XdmcpWriteHeader (&manager->priv->buf, &header); - XdmcpWriteCARD32 (&manager->priv->buf, session_id); - XdmcpWriteARRAY8 (&manager->priv->buf, authentication_name); - XdmcpWriteARRAY8 (&manager->priv->buf, authentication_data); - XdmcpWriteARRAY8 (&manager->priv->buf, authorization_name); - XdmcpWriteARRAY8 (&manager->priv->buf, authorization_data); - - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("XDMCP: Sending ACCEPT to %s with SessionID=%ld", - host, - (long)session_id); - g_free (host); -} - -static void -gdm_xdmcp_handle_request (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - CARD16 clnt_dspnum; - ARRAY16 clnt_conntyp; - ARRAYofARRAY8 clnt_addr; - ARRAY8 clnt_authname; - ARRAY8 clnt_authdata; - ARRAYofARRAY8 clnt_authorization; - ARRAY8 clnt_manufacturer; - int explen; - int i; - gboolean mitauth; - gboolean entered; - char *host; - - mitauth = FALSE; - entered = FALSE; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("gdm_xdmcp_handle_request: Got REQUEST from %s", host); - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - g_warning (_("%s: Got REQUEST from banned host %s"), - "gdm_xdmcp_handle_request", - host); - g_free (host); - return; - } - g_free (host); - - gdm_xdmcp_displays_purge (manager); /* Purge pending displays */ - - /* Remote display number */ - if G_UNLIKELY (! XdmcpReadCARD16 (&manager->priv->buf, &clnt_dspnum)) { - g_warning (_("%s: Could not read Display Number"), - "gdm_xdmcp_handle_request"); - return; - } - - /* We don't care about connection type. Address says it all */ - if G_UNLIKELY (! XdmcpReadARRAY16 (&manager->priv->buf, &clnt_conntyp)) { - g_warning (_("%s: Could not read Connection Type"), - "gdm_xdmcp_handle_request"); - return; - } - - /* This is TCP/IP - we don't care */ - if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&manager->priv->buf, &clnt_addr)) { - g_warning (_("%s: Could not read Client Address"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAY16 (&clnt_conntyp); - return; - } - - /* Read authentication type */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&manager->priv->buf, &clnt_authname)) { - g_warning (_("%s: Could not read Authentication Names"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAY16 (&clnt_conntyp); - return; - } - - /* Read authentication data */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&manager->priv->buf, &clnt_authdata)) { - g_warning (_("%s: Could not read Authentication Data"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAY16 (&clnt_conntyp); - XdmcpDisposeARRAY8 (&clnt_authname); - return; - } - - /* Read and select from supported authorization list */ - if G_UNLIKELY (! XdmcpReadARRAYofARRAY8 (&manager->priv->buf, &clnt_authorization)) { - g_warning (_("%s: Could not read Authorization List"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAY8 (&clnt_authdata); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAY16 (&clnt_conntyp); - XdmcpDisposeARRAY8 (&clnt_authname); - return; - } - - /* libXdmcp doesn't terminate strings properly so we cheat and use strncmp () */ - for (i = 0 ; i < clnt_authorization.length ; i++) - if (clnt_authorization.data[i].length == 18 && - strncmp ((char *) clnt_authorization.data[i].data, - "MIT-MAGIC-COOKIE-1", 18) == 0) - mitauth = TRUE; - - /* Manufacturer ID */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&manager->priv->buf, &clnt_manufacturer)) { - g_warning (_("%s: Could not read Manufacturer ID"), - "gdm_xdmcp_handle_request"); - XdmcpDisposeARRAY8 (&clnt_authname); - XdmcpDisposeARRAY8 (&clnt_authdata); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAYofARRAY8 (&clnt_authorization); - XdmcpDisposeARRAY16 (&clnt_conntyp); - return; - } - - /* Crude checksumming */ - explen = 2; /* Display Number */ - explen += 1 + 2 * clnt_conntyp.length; /* Connection Type */ - explen += 1; /* Connection Address */ - for (i = 0 ; i < clnt_addr.length ; i++) - explen += 2 + clnt_addr.data[i].length; - explen += 2 + clnt_authname.length; /* Authentication Name */ - explen += 2 + clnt_authdata.length; /* Authentication Data */ - explen += 1; /* Authorization Names */ - for (i = 0 ; i < clnt_authorization.length ; i++) - explen += 2 + clnt_authorization.data[i].length; - explen += 2 + clnt_manufacturer.length; - - if G_UNLIKELY (explen != len) { - gdm_address_get_info (clnt_sa, &host, NULL); - g_warning (_("%s: Failed checksum from %s"), - "gdm_xdmcp_handle_request", - host); - g_free (host); - - XdmcpDisposeARRAY8 (&clnt_authname); - XdmcpDisposeARRAY8 (&clnt_authdata); - XdmcpDisposeARRAY8 (&clnt_manufacturer); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAYofARRAY8 (&clnt_authorization); - XdmcpDisposeARRAY16 (&clnt_conntyp); - return; - } - - { - char *s = g_strndup ((char *) clnt_manufacturer.data, clnt_manufacturer.length); - g_debug ("gdm_xdmcp_handle_request: xdmcp_pending=%d, MaxPending=%d, xdmcp_sessions=%d, MaxSessions=%d, ManufacturerID=%s", - manager->priv->num_pending_sessions, - manager->priv->max_pending_displays, - manager->priv->num_sessions, - manager->priv->max_displays, - ve_sure_string (s)); - g_free (s); - } - - /* Check if ok to manage display */ - if (mitauth && - manager->priv->num_sessions < manager->priv->max_displays && - (gdm_address_is_local (clnt_sa) || - gdm_xdmcp_num_displays_from_host (manager, clnt_sa) < manager->priv->max_displays_per_host)) { - entered = TRUE; - } - - if (entered) { - GdmHostent *he; - he = gdm_gethostbyaddr (clnt_sa); - - /* Check if we are already talking to this host */ - gdm_xdmcp_display_dispose_check (manager, he->hostname, clnt_dspnum); - - if (manager->priv->num_pending_sessions >= manager->priv->max_pending_displays) { - g_debug ("gdm_xdmcp_handle_request: maximum pending"); - /* Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii */ - gdm_xdmcp_send_decline (manager, clnt_sa, "Maximum pending servers"); - gdm_hostent_free (he); - } else { - GdmDisplay *d; - - d = gdm_xdmcp_display_alloc (manager, - clnt_sa, - he /* eaten and freed */, - clnt_dspnum); - if (d != NULL) { - ARRAY8 authentication_name; - ARRAY8 authentication_data; - ARRAY8 authorization_name; - ARRAY8 authorization_data; - - authentication_name.data = NULL; - authentication_name.length = 0; - authentication_data.data = NULL; - authentication_data.length = 0; - - authorization_name.data = (CARD8 *) "MIT-MAGIC-COOKIE-1"; - authorization_name.length = strlen ((char *) authorization_name.data); - - authorization_data.data = (CARD8 *) d->bcookie; - authorization_data.length = 16; - - /* the addrs are NOT copied */ - gdm_xdmcp_send_accept (manager, - clnt_sa, - d->sessionid, - &authentication_name, - &authentication_data, - &authorization_name, - &authorization_data); - } - } - } else { - /* Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii */ - if ( ! mitauth) { - gdm_xdmcp_send_decline (manager, - clnt_sa, - "Only MIT-MAGIC-COOKIE-1 supported"); - } else if (manager->priv->num_sessions >= manager->priv->max_displays) { - g_warning ("Maximum number of open XDMCP sessions reached"); - gdm_xdmcp_send_decline (manager, - clnt_sa, - "Maximum number of open sessions reached"); - } else { - g_debug ("Maximum number of open XDMCP sessions from host %s reached", - host); - gdm_xdmcp_send_decline (manager, - clnt_sa, - "Maximum number of open sessions from your host reached"); - } - } - - XdmcpDisposeARRAY8 (&clnt_authname); - XdmcpDisposeARRAY8 (&clnt_authdata); - XdmcpDisposeARRAY8 (&clnt_manufacturer); - XdmcpDisposeARRAYofARRAY8 (&clnt_addr); - XdmcpDisposeARRAYofARRAY8 (&clnt_authorization); - XdmcpDisposeARRAY16 (&clnt_conntyp); -} - -static GdmDisplay * -gdm_xdmcp_display_lookup (GdmXdmcpManager *manager, - CARD32 sessid) -{ - GSList *l; - GdmDisplay *d; - GSList *displays; - - if (sessid == 0) { - return (NULL); - } - - displays = gdm_daemon_config_get_display_list (); - - l = displays; - while (l != NULL) { - d = (GdmDisplay *) l->data; - - if (d && d->sessionid == sessid) { - return (d); - } - - l = l->next; - } - - return (NULL); -} - -static void -gdm_xdmcp_send_failed (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - CARD32 sessid) -{ - XdmcpHeader header; - ARRAY8 status; - - g_debug ("XDMCP: Sending FAILED to %ld", (long)sessid); - - /* - * Don't translate, this goes over the wire to servers where we - * don't know the charset or language, so it must be ascii - */ - status.data = (CARD8 *) "Failed to start session"; - status.length = strlen ((char *) status.data); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) FAILED; - header.length = 6+status.length; - - XdmcpWriteHeader (&manager->priv->buf, &header); - XdmcpWriteCARD32 (&manager->priv->buf, sessid); - XdmcpWriteARRAY8 (&manager->priv->buf, &status); - - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); -} - -static void -gdm_xdmcp_send_refuse (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - CARD32 sessid) -{ - XdmcpHeader header; - GdmForwardQuery *fq; - - g_debug ("XDMCP: Sending REFUSE to %ld", - (long)sessid); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) REFUSE; - header.length = 4; - - XdmcpWriteHeader (&manager->priv->buf, &header); - XdmcpWriteCARD32 (&manager->priv->buf, sessid); - - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); - - /* - * This was from a forwarded query quite apparently so - * send MANAGED_FORWARD - */ - fq = gdm_forward_query_lookup (manager, clnt_sa); - if (fq != NULL) { - gdm_xdmcp_send_managed_forward (manager, fq->from_sa, clnt_sa); - gdm_forward_query_dispose (manager, fq); - } -} - -static void -gdm_xdmcp_handle_manage (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - CARD32 clnt_sessid; - CARD16 clnt_dspnum; - ARRAY8 clnt_dspclass; - GdmDisplay *d; - GdmIndirectDisplay *id; - GdmForwardQuery *fq; - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("gdm_xdmcp_handle_manage: Got MANAGE from %s", host); - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - g_warning (_("%s: Got Manage from banned host %s"), - "gdm_xdmcp_handle_manage", - host); - g_free (host); - return; - } - g_free (host); - - /* SessionID */ - if G_UNLIKELY (! XdmcpReadCARD32 (&manager->priv->buf, &clnt_sessid)) { - g_warning (_("%s: Could not read Session ID"), - "gdm_xdmcp_handle_manage"); - return; - } - - /* Remote display number */ - if G_UNLIKELY (! XdmcpReadCARD16 (&manager->priv->buf, &clnt_dspnum)) { - g_warning (_("%s: Could not read Display Number"), - "gdm_xdmcp_handle_manage"); - return; - } - - /* Display Class */ - if G_UNLIKELY (! XdmcpReadARRAY8 (&manager->priv->buf, &clnt_dspclass)) { - g_warning (_("%s: Could not read Display Class"), - "gdm_xdmcp_handle_manage"); - return; - } - - if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) { - char *s = g_strndup ((char *) clnt_dspclass.data, clnt_dspclass.length); - g_debug ("gdm_xdmcp-handle_manage: Got display=%d, SessionID=%ld Class=%s from %s", - (int)clnt_dspnum, (long)clnt_sessid, ve_sure_string (s), host); - - g_free (s); - } - - d = gdm_xdmcp_display_lookup (manager, clnt_sessid); - if (d != NULL && - d->dispstat == XDMCP_PENDING) { - - g_debug ("gdm_xdmcp_handle_manage: Looked up %s", d->name); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_INDIRECT)) { - id = gdm_choose_indirect_lookup (clnt_sa); - - /* This was an indirect thingie and nothing was yet chosen, - * use a chooser */ - if (d->dispstat == XDMCP_PENDING && - id != NULL && - id->chosen_host == NULL) { - d->use_chooser = TRUE; - d->indirect_id = id->id; - } else { - d->indirect_id = 0; - d->use_chooser = FALSE; - if (id != NULL) - gdm_choose_indirect_dispose (id); - } - } else { - d->indirect_id = 0; - d->use_chooser = FALSE; - } - - /* this was from a forwarded query quite apparently so - * send MANAGED_FORWARD */ - fq = gdm_forward_query_lookup (manager, clnt_sa); - if (fq != NULL) { - gdm_xdmcp_send_managed_forward (manager, fq->from_sa, clnt_sa); - gdm_forward_query_dispose (manager, fq); - } - - d->dispstat = XDMCP_MANAGED; - manager->priv->num_sessions++; - manager->priv->num_pending_sessions--; - - /* Start greeter/session */ - if G_UNLIKELY (!gdm_display_manage (d)) { - gdm_xdmcp_send_failed (manager, clnt_sa, clnt_sessid); - XdmcpDisposeARRAY8 (&clnt_dspclass); - return; - } - } else if G_UNLIKELY (d != NULL && d->dispstat == XDMCP_MANAGED) { - g_debug ("gdm_xdmcp_handle_manage: Session id %ld already managed", - (long)clnt_sessid); - } else { - g_warning ("gdm_xdmcp_handle_manage: Failed to look up session id %ld", - (long)clnt_sessid); - gdm_xdmcp_send_refuse (manager, clnt_sa, clnt_sessid); - } - - XdmcpDisposeARRAY8 (&clnt_dspclass); -} - -static void -gdm_xdmcp_handle_managed_forward (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - ARRAY8 clnt_address; - GdmIndirectDisplay *id; - char *host; - struct sockaddr_storage *disp_sa; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("gdm_xdmcp_handle_managed_forward: Got MANAGED_FORWARD from %s", - host); - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - g_warning ("%s: Got MANAGED_FORWARD from banned host %s", - "gdm_xdmcp_handle_request", host); - g_free (host); - return; - } - g_free (host); - - /* Hostname */ - if G_UNLIKELY ( ! XdmcpReadARRAY8 (&manager->priv->buf, &clnt_address)) { - g_warning (_("%s: Could not read address"), - "gdm_xdmcp_handle_managed_forward"); - return; - } - - disp_sa = NULL; - if (! create_sa_from_request (&clnt_address, NULL, clnt_sa->ss_family, &disp_sa)) { - g_warning ("Unable to parse address for request"); - XdmcpDisposeARRAY8 (&clnt_address); - return; - } - - id = gdm_choose_indirect_lookup_by_chosen (clnt_sa, disp_sa); - if (id != NULL) { - gdm_choose_indirect_dispose (id); - } - - /* Note: we send GOT even on not found, just in case our previous - * didn't get through and this was a second managed forward */ - gdm_xdmcp_send_got_managed_forward (manager, clnt_sa, disp_sa); - - XdmcpDisposeARRAY8 (&clnt_address); -} - -static void -gdm_xdmcp_handle_got_managed_forward (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - struct sockaddr_storage *disp_sa; - ARRAY8 clnt_address; - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("gdm_xdmcp_handle_got_managed_forward: Got MANAGED_FORWARD from %s", - host); - - if (! gdm_xdmcp_host_allow (clnt_sa)) { - g_warning ("%s: Got GOT_MANAGED_FORWARD from banned host %s", - "gdm_xdmcp_handle_request", host); - g_free (host); - return; - } - g_free (host); - - /* Hostname */ - if G_UNLIKELY ( ! XdmcpReadARRAY8 (&manager->priv->buf, &clnt_address)) { - g_warning (_("%s: Could not read address"), - "gdm_xdmcp_handle_got_managed_forward"); - return; - } - - if (! create_sa_from_request (&clnt_address, NULL, clnt_sa->ss_family, &disp_sa)) { - g_warning (_("%s: Could not read address"), - "gdm_xdmcp_handle_got_managed_forward"); - XdmcpDisposeARRAY8 (&clnt_address); - return; - } - - gdm_xdmcp_whack_queued_managed_forwards (manager, clnt_sa, disp_sa); - - XdmcpDisposeARRAY8 (&clnt_address); -} - -static void -gdm_xdmcp_send_alive (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - CARD16 dspnum, - CARD32 sessid) -{ - XdmcpHeader header; - GdmDisplay *d; - int send_running = 0; - CARD32 send_sessid = 0; - - d = gdm_xdmcp_display_lookup (manager, sessid); - if (d == NULL) { - d = gdm_xdmcp_display_lookup_by_host (manager, clnt_sa, dspnum); - } - - if (d != NULL) { - send_sessid = d->sessionid; - if (d->dispstat == XDMCP_MANAGED) { - send_running = 1; - } - } - - g_debug ("XDMCP: Sending ALIVE to %ld (running %d, sessid %ld)", - (long)sessid, - send_running, - (long)send_sessid); - - header.version = XDM_PROTOCOL_VERSION; - header.opcode = (CARD16) ALIVE; - header.length = 5; - - XdmcpWriteHeader (&manager->priv->buf, &header); - XdmcpWriteCARD8 (&manager->priv->buf, send_running); - XdmcpWriteCARD32 (&manager->priv->buf, send_sessid); - - XdmcpFlush (manager->priv->socket_fd, - &manager->priv->buf, - (XdmcpNetaddr)clnt_sa, - (int)sizeof (struct sockaddr_storage)); -} - -static void -gdm_xdmcp_handle_keepalive (GdmXdmcpManager *manager, - struct sockaddr_storage *clnt_sa, - int len) -{ - CARD16 clnt_dspnum; - CARD32 clnt_sessid; - char *host; - - gdm_address_get_info (clnt_sa, &host, NULL); - g_debug ("XDMCP: Got KEEPALIVE from %s", host); - - /* Check with tcp_wrappers if client is allowed to access */ - if (! gdm_xdmcp_host_allow (clnt_sa)) { - g_warning (_("%s: Got KEEPALIVE from banned host %s"), - "gdm_xdmcp_handle_keepalive", - host); - g_free (host); - return; - } - g_free (host); - - /* Remote display number */ - if G_UNLIKELY (! XdmcpReadCARD16 (&manager->priv->buf, &clnt_dspnum)) { - g_warning (_("%s: Could not read Display Number"), - "gdm_xdmcp_handle_keepalive"); - return; - } - - /* SessionID */ - if G_UNLIKELY (! XdmcpReadCARD32 (&manager->priv->buf, &clnt_sessid)) { - g_warning (_("%s: Could not read Session ID"), - "gdm_xdmcp_handle_keepalive"); - return; - } - - gdm_xdmcp_send_alive (manager, clnt_sa, clnt_dspnum, clnt_sessid); -} - -static const char * -opcode_string (int opcode) -{ - static const char * const opcode_names[] = { - NULL, - "BROADCAST_QUERY", - "QUERY", - "INDIRECT_QUERY", - "FORWARD_QUERY", - "WILLING", - "UNWILLING", - "REQUEST", - "ACCEPT", - "DECLINE", - "MANAGE", - "REFUSE", - "FAILED", - "KEEPALIVE", - "ALIVE" - }; - static const char * const gdm_opcode_names[] = { - "MANAGED_FORWARD", - "GOT_MANAGED_FORWARD" - }; - - - if (opcode < G_N_ELEMENTS (opcode_names)) { - return opcode_names [opcode]; - } else if (opcode >= GDM_XDMCP_FIRST_OPCODE && - opcode < GDM_XDMCP_LAST_OPCODE) { - return gdm_opcode_names [opcode - GDM_XDMCP_FIRST_OPCODE]; - } else { - return "UNKNOWN"; - } -} - -static gboolean -decode_packet (GIOChannel *source, - GIOCondition cond, - GdmXdmcpManager *manager) -{ - struct sockaddr_storage clnt_sa; - gint sa_len; - XdmcpHeader header; - char *host; - char *port; - int res; - - sa_len = sizeof (clnt_sa); - - g_debug ("decode_packet: GIOCondition %d", (int)cond); - - if ( ! (cond & G_IO_IN)) { - return TRUE; - } - - res = XdmcpFill (manager->priv->socket_fd, &manager->priv->buf, (XdmcpNetaddr)&clnt_sa, &sa_len); - if G_UNLIKELY (! res) { - g_debug (_("XMCP: Could not create XDMCP buffer!")); - return TRUE; - } - - res = XdmcpReadHeader (&manager->priv->buf, &header); - if G_UNLIKELY (! res) { - g_warning (_("XDMCP: Could not read XDMCP header!")); - return TRUE; - } - - if G_UNLIKELY (header.version != XDM_PROTOCOL_VERSION && - header.version != GDM_XDMCP_PROTOCOL_VERSION) { - g_warning (_("XMDCP: Incorrect XDMCP version!")); - return TRUE; - } - - gdm_address_get_info (&clnt_sa, &host, &port); - - g_debug ("XDMCP: Received opcode %s from client %s : %s", - opcode_string (header.opcode), - host, - port); - - switch (header.opcode) { - case BROADCAST_QUERY: - gdm_xdmcp_handle_broadcast_query (manager, &clnt_sa, header.length); - break; - - case QUERY: - gdm_xdmcp_handle_query (manager, &clnt_sa, header.length); - break; - - case INDIRECT_QUERY: - gdm_xdmcp_handle_indirect_query (manager, &clnt_sa, header.length); - break; - - case FORWARD_QUERY: - gdm_xdmcp_handle_forward_query (manager, &clnt_sa, header.length); - break; - - case REQUEST: - gdm_xdmcp_handle_request (manager, &clnt_sa, header.length); - break; - - case MANAGE: - gdm_xdmcp_handle_manage (manager, &clnt_sa, header.length); - break; - - case KEEPALIVE: - gdm_xdmcp_handle_keepalive (manager, &clnt_sa, header.length); - break; - - case GDM_XDMCP_MANAGED_FORWARD: - gdm_xdmcp_handle_managed_forward (manager, &clnt_sa, header.length); - break; - - case GDM_XDMCP_GOT_MANAGED_FORWARD: - gdm_xdmcp_handle_got_managed_forward (manager, &clnt_sa, header.length); - break; - - default: - g_debug ("XDMCP: Unknown opcode from client %s : %s", - host, - port); - - break; - } - - g_free (host); - g_free (port); - - return TRUE; -} - -gboolean -gdm_xdmcp_manager_start (GdmXdmcpManager *manager, - GError **error) -{ - gboolean ret; - GIOChannel *ioc; - - g_return_val_if_fail (GDM_IS_XDMCP_MANAGER (manager), FALSE); - g_return_val_if_fail (manager->priv->socket_fd == -1, FALSE); - - ret = open_port (manager); - if (! ret) { - return ret; - } - - g_debug ("XDMCP: Starting to listen on XDMCP port"); - - ioc = g_io_channel_unix_new (manager->priv->socket_fd); - - g_io_channel_set_encoding (ioc, NULL, NULL); - g_io_channel_set_buffered (ioc, FALSE); - - manager->priv->socket_watch_id = g_io_add_watch_full (ioc, - G_PRIORITY_DEFAULT, - G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, - (GIOFunc)decode_packet, - manager, - NULL); - g_io_channel_unref (ioc); - - return ret; -} - -gboolean -gdm_xdmcp_manager_stop (GdmXdmcpManager *manager, - GError **error) -{ - g_return_val_if_fail (GDM_IS_XDMCP_MANAGER (manager), FALSE); - g_return_val_if_fail (manager->priv->socket_fd != -1, FALSE); - - if (manager->priv->socket_watch_id > 0) { - g_source_remove (manager->priv->socket_watch_id); - manager->priv->socket_watch_id = 0; - } - - if (manager->priv->socket_fd > 0) { - VE_IGNORE_EINTR (close (manager->priv->socket_fd)); - manager->priv->socket_fd = -1; - } - - return TRUE; -} - -void -gdm_xdmcp_manager_set_port (GdmXdmcpManager *manager, - guint port) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - manager->priv->port = port; -} - -static void -gdm_xdmcp_manager_set_use_multicast (GdmXdmcpManager *manager, - gboolean use_multicast) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - manager->priv->use_multicast = use_multicast; -} - -static void -gdm_xdmcp_manager_set_multicast_address (GdmXdmcpManager *manager, - const char *address) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - g_free (manager->priv->multicast_address); - manager->priv->multicast_address = g_strdup (address); -} - -static void -gdm_xdmcp_manager_set_honor_indirect (GdmXdmcpManager *manager, - gboolean honor_indirect) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - manager->priv->honor_indirect = honor_indirect; -} - -static void -gdm_xdmcp_manager_set_max_displays_per_host (GdmXdmcpManager *manager, - guint num) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - manager->priv->max_displays_per_host = num; -} - -static void -gdm_xdmcp_manager_set_max_displays (GdmXdmcpManager *manager, - guint num) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - manager->priv->max_displays = num; -} - -static void -gdm_xdmcp_manager_set_max_pending_displays (GdmXdmcpManager *manager, - guint num) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - manager->priv->max_pending_displays = num; -} - -static void -gdm_xdmcp_manager_set_max_wait (GdmXdmcpManager *manager, - guint num) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - manager->priv->max_wait = num; -} - -static void -gdm_xdmcp_manager_set_willing_script (GdmXdmcpManager *manager, - const char *script) -{ - g_return_if_fail (GDM_IS_XDMCP_MANAGER (manager)); - - g_free (manager->priv->willing_script); - manager->priv->willing_script = g_strdup (script); -} - -static void -gdm_xdmcp_manager_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - GdmXdmcpManager *self; - - self = GDM_XDMCP_MANAGER (object); - - switch (prop_id) { - case PROP_PORT: - gdm_xdmcp_manager_set_port (self, g_value_get_uint (value)); - break; - case PROP_USE_MULTICAST: - gdm_xdmcp_manager_set_use_multicast (self, g_value_get_boolean (value)); - break; - case PROP_MULTICAST_ADDRESS: - gdm_xdmcp_manager_set_multicast_address (self, g_value_get_string (value)); - break; - case PROP_HONOR_INDIRECT: - gdm_xdmcp_manager_set_honor_indirect (self, g_value_get_boolean (value)); - break; - case PROP_MAX_DISPLAYS_PER_HOST: - gdm_xdmcp_manager_set_max_displays_per_host (self, g_value_get_uint (value)); - break; - case PROP_MAX_DISPLAYS: - gdm_xdmcp_manager_set_max_displays (self, g_value_get_uint (value)); - break; - case PROP_MAX_PENDING_DISPLAYS: - gdm_xdmcp_manager_set_max_pending_displays (self, g_value_get_uint (value)); - break; - case PROP_MAX_WAIT: - gdm_xdmcp_manager_set_max_wait (self, g_value_get_uint (value)); - break; - case PROP_WILLING_SCRIPT: - gdm_xdmcp_manager_set_willing_script (self, g_value_get_string (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gdm_xdmcp_manager_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - GdmXdmcpManager *self; - - self = GDM_XDMCP_MANAGER (object); - - switch (prop_id) { - case PROP_PORT: - g_value_set_uint (value, self->priv->port); - break; - case PROP_USE_MULTICAST: - g_value_set_boolean (value, self->priv->use_multicast); - break; - case PROP_MULTICAST_ADDRESS: - g_value_set_string (value, self->priv->multicast_address); - break; - case PROP_HONOR_INDIRECT: - g_value_set_boolean (value, self->priv->honor_indirect); - break; - case PROP_MAX_DISPLAYS_PER_HOST: - g_value_set_uint (value, self->priv->max_displays_per_host); - break; - case PROP_MAX_DISPLAYS: - g_value_set_uint (value, self->priv->max_displays); - break; - case PROP_MAX_PENDING_DISPLAYS: - g_value_set_uint (value, self->priv->max_pending_displays); - break; - case PROP_MAX_WAIT: - g_value_set_uint (value, self->priv->max_wait); - break; - case PROP_WILLING_SCRIPT: - g_value_set_string (value, self->priv->willing_script); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gdm_xdmcp_manager_class_init (GdmXdmcpManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->get_property = gdm_xdmcp_manager_get_property; - object_class->set_property = gdm_xdmcp_manager_set_property; - object_class->finalize = gdm_xdmcp_manager_finalize; - - g_object_class_install_property (object_class, - PROP_PORT, - g_param_spec_uint ("port", - "UDP port", - "UDP port", - 0, - G_MAXINT, - DEFAULT_PORT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_USE_MULTICAST, - g_param_spec_boolean ("use-multicast", - NULL, - NULL, - DEFAULT_USE_MULTICAST, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_MULTICAST_ADDRESS, - g_param_spec_string ("multicast-address", - "multicast-address", - "multicast-address", - DEFAULT_MULTICAST_ADDRESS, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_HONOR_INDIRECT, - g_param_spec_boolean ("honor-indirect", - NULL, - NULL, - DEFAULT_HONOR_INDIRECT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_WILLING_SCRIPT, - g_param_spec_string ("willing-script", - "willing-script", - "willing-script", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_MAX_DISPLAYS_PER_HOST, - g_param_spec_uint ("max-displays-per-host", - "max-displays-per-host", - "max-displays-per-host", - 0, - G_MAXINT, - DEFAULT_MAX_DISPLAYS_PER_HOST, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_MAX_DISPLAYS, - g_param_spec_uint ("max-displays", - "max-displays", - "max-displays", - 0, - G_MAXINT, - DEFAULT_MAX_DISPLAYS, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_MAX_PENDING_DISPLAYS, - g_param_spec_uint ("max-pending-displays", - "max-pending-displays", - "max-pending-displays", - 0, - G_MAXINT, - DEFAULT_MAX_PENDING_DISPLAYS, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_MAX_WAIT, - g_param_spec_uint ("max-wait", - "max-wait", - "max-wait", - 0, - G_MAXINT, - DEFAULT_MAX_WAIT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_type_class_add_private (klass, sizeof (GdmXdmcpManagerPrivate)); -} - -static void -gdm_xdmcp_manager_init (GdmXdmcpManager *manager) -{ - char hostbuf[1024]; - struct utsname name; - - manager->priv = GDM_XDMCP_MANAGER_GET_PRIVATE (manager); - - manager->priv->socket_fd = -1; - - manager->priv->session_serial = g_random_int (); - - /* Fetch and store local hostname in XDMCP friendly format */ - hostbuf[1023] = '\0'; - if G_UNLIKELY (gethostname (hostbuf, 1023) != 0) { - g_warning (_("Could not get server hostname: %s!"), g_strerror (errno)); - strcpy (hostbuf, "localhost.localdomain"); - } - - uname (&name); - manager->priv->sysid = g_strconcat (name.sysname, - " ", - name.release, - NULL); - - manager->priv->hostname = g_strdup (hostbuf); - - manager->priv->servhost.data = (CARD8 *) g_strdup (hostbuf); - manager->priv->servhost.length = strlen ((char *) manager->priv->servhost.data); -} - -static void -gdm_xdmcp_manager_finalize (GObject *object) -{ - GdmXdmcpManager *manager; - - g_return_if_fail (object != NULL); - g_return_if_fail (GDM_IS_XDMCP_MANAGER (object)); - - manager = GDM_XDMCP_MANAGER (object); - - g_return_if_fail (manager->priv != NULL); - - if (manager->priv->socket_watch_id > 0) { - g_source_remove (manager->priv->socket_watch_id); - } - - g_slist_free (manager->priv->forward_queries); - g_slist_free (manager->priv->managed_forwards); - - g_free (manager->priv->sysid); - g_free (manager->priv->hostname); - g_free (manager->priv->multicast_address); - g_free (manager->priv->willing_script); - - /* FIXME: Free servhost */ - - G_OBJECT_CLASS (gdm_xdmcp_manager_parent_class)->finalize (object); -} - -GdmXdmcpManager * -gdm_xdmcp_manager_new (void) -{ - if (xdmcp_manager_object != NULL) { - g_object_ref (xdmcp_manager_object); - } else { - xdmcp_manager_object = g_object_new (GDM_TYPE_XDMCP_MANAGER, NULL); - g_object_add_weak_pointer (xdmcp_manager_object, - (gpointer *) &xdmcp_manager_object); - } - - return GDM_XDMCP_MANAGER (xdmcp_manager_object); -} diff --git a/daemon/gdm-xdmcp-manager.h b/daemon/gdm-xdmcp-manager.h deleted file mode 100644 index fe12ddc5..00000000 --- a/daemon/gdm-xdmcp-manager.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __GDM_XDMCP_MANAGER_H -#define __GDM_XDMCP_MANAGER_H - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define GDM_TYPE_XDMCP_MANAGER (gdm_xdmcp_manager_get_type ()) -#define GDM_XDMCP_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_XDMCP_MANAGER, GdmXdmcpManager)) -#define GDM_XDMCP_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_XDMCP_MANAGER, GdmXdmcpManagerClass)) -#define GDM_IS_XDMCP_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_XDMCP_MANAGER)) -#define GDM_IS_XDMCP_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_XDMCP_MANAGER)) -#define GDM_XDMCP_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_XDMCP_MANAGER, GdmXdmcpManagerClass)) - -typedef struct GdmXdmcpManagerPrivate GdmXdmcpManagerPrivate; - -typedef struct -{ - GObject parent; - GdmXdmcpManagerPrivate *priv; -} GdmXdmcpManager; - -typedef struct -{ - GObjectClass parent_class; -} GdmXdmcpManagerClass; - -typedef enum -{ - GDM_XDMCP_MANAGER_ERROR_GENERAL -} GdmXdmcpManagerError; - -#define GDM_XDMCP_MANAGER_ERROR gdm_xdmcp_manager_error_quark () - -GQuark gdm_xdmcp_manager_error_quark (void); -GType gdm_xdmcp_manager_get_type (void); - -GdmXdmcpManager * gdm_xdmcp_manager_new (void); - -void gdm_xdmcp_manager_set_port (GdmXdmcpManager *manager, - guint port); -gboolean gdm_xdmcp_manager_start (GdmXdmcpManager *manager, - GError **error); -gboolean gdm_xdmcp_manager_stop (GdmXdmcpManager *manager, - GError **error); - -G_END_DECLS - -#endif /* __GDM_XDMCP_MANAGER_H */ diff --git a/daemon/gdm.c b/daemon/gdm.c deleted file mode 100644 index b6d73a03..00000000 --- a/daemon/gdm.c +++ /dev/null @@ -1,4337 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <signal.h> -#include <limits.h> -#include <stdlib.h> -#include <unistd.h> -#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD) -#include <sched.h> -#endif -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <sys/resource.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <ctype.h> -#include <pwd.h> -#include <grp.h> -#include <fcntl.h> -#include <errno.h> -#include <locale.h> -#include <dirent.h> - -#ifdef HAVE_CHKAUTHATTR -#include <auth_attr.h> -#include <secdb.h> -#endif - -/* This should be moved to auth.c I suppose */ - -#include <X11/Xauth.h> -#include <glib/gi18n.h> -#include <glib-object.h> - -#include <gtk/gtk.h> - -/* Needed for signal handling */ -#include "gdm-common.h" - -#include "gdm.h" -#include "misc.h" -#include "slave.h" -#include "server.h" -#include "verify.h" -#include "display.h" -#include "choose.h" -#include "getvt.h" -#include "gdm-net.h" -#include "cookie.h" -#include "filecheck.h" -#include "errorgui.h" - -#include "gdm-socket-protocol.h" -#include "gdm-daemon-config.h" -#include "gdm-log.h" - -#include "xdmcp.h" - -#define DYNAMIC_ADD 0 -#define DYNAMIC_RELEASE 1 -#define DYNAMIC_REMOVE 2 - -#ifdef HAVE_LOGINDEVPERM -#include <libdevinfo.h> -#endif /* HAVE_LOGINDEVPERM */ - -/* Local functions */ -static void gdm_handle_message (GdmConnection *conn, - const gchar *msg, - gpointer data); -static void gdm_handle_user_message (GdmConnection *conn, - const gchar *msg, - gpointer data); -static void gdm_daemonify (void); -static void gdm_safe_restart (void); -static void gdm_try_logout_action (GdmDisplay *disp); -static void gdm_restart_now (void); -static void handle_flexi_server (GdmConnection *conn, - int type, - const gchar *server, - gboolean handled, - gboolean chooser, - const gchar *xnest_disp, - uid_t xnest_uid, - const gchar *xnest_auth_file, - const gchar *xnest_cookie, - const gchar *username); -static void custom_cmd_restart (long cmd_id); -static void custom_cmd_no_restart (long cmd_id); - -/* Global vars */ -gint flexi_servers = 0; /* Number of flexi servers */ -static pid_t extra_process = 0; /* An extra process. Used for quickie - processes, so that they also get whacked */ -static int extra_status = 0; /* Last status from the last extra process */ - -gboolean gdm_wait_for_go = FALSE; /* wait for a GO in the fifo */ - -static gboolean print_version = FALSE; /* print version number and quit */ -static gboolean preserve_ld_vars = FALSE; /* Preserve the ld environment variables */ -static gboolean no_daemon = FALSE; /* Do not daemonize */ -static gboolean no_console = FALSE; /* There are no static servers, this means, - don't run static servers and second, - don't display info on the console */ - -GdmConnection *fifoconn = NULL; /* Fifo connection */ -GdmConnection *pipeconn = NULL; /* slavepipe (handled just like Fifo for compatibility) connection */ -GdmConnection *unixconn = NULL; /* UNIX Socket connection */ -int slave_fifo_pipe_fd = -1; /* the slavepipe connection */ - -unsigned char *gdm_global_cookie = NULL; -unsigned char *gdm_global_bcookie = NULL; - -gboolean gdm_first_login = TRUE; - -static GdmLogoutAction safe_logout_action = GDM_LOGOUT_ACTION_NONE; - -/* set in the main function */ -gchar **stored_argv = NULL; -int stored_argc = 0; - -static gchar *config_file = NULL; -static gboolean gdm_restart_mode = FALSE; - -static GMainLoop *main_loop = NULL; - -static gboolean monte_carlo_sqrt2 = FALSE; - -/* - * lookup display number if the display number is - * exists then clear the remove flag and return TRUE - * otherwise return FALSE - */ -static gboolean -mark_display_exists (int num) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (disp->dispnum == num) { - disp->removeconf = FALSE; - return TRUE; - } - } - return FALSE; -} - -/** - * gdm_daemonify: - * - * Detach gdm daemon from the controlling terminal - */ - -static void -gdm_daemonify (void) -{ - FILE *pf; - pid_t pid; - - pid = fork (); - if (pid > 0) { - const char *pidfile = GDM_PID_FILE; - - errno = 0; - if ((pf = gdm_safe_fopen_w (pidfile)) != NULL) { - errno = 0; - VE_IGNORE_EINTR (fprintf (pf, "%d\n", (int)pid)); - VE_IGNORE_EINTR (fclose (pf)); - if G_UNLIKELY (errno != 0) { - /* FIXME: how to handle this? */ - gdm_fdprintf (2, _("Cannot write PID file %s: possibly out of diskspace. Error: %s\n"), - pidfile, strerror (errno)); - gdm_error (_("Cannot write PID file %s: possibly out of diskspace. Error: %s"), - pidfile, strerror (errno)); - - } - } else if G_UNLIKELY (errno != 0) { - /* FIXME: how to handle this? */ - gdm_fdprintf (2, _("Cannot write PID file %s: possibly out of diskspace. Error: %s\n"), - pidfile, strerror (errno)); - gdm_error (_("Cannot write PID file %s: possibly out of diskspace. Error: %s"), - pidfile, strerror (errno)); - - } - - exit (EXIT_SUCCESS); - } - - if G_UNLIKELY (pid < 0) - gdm_fail (_("%s: fork () failed!"), "gdm_daemonify"); - - if G_UNLIKELY (setsid () < 0) - gdm_fail (_("%s: setsid () failed: %s!"), "gdm_daemonify", - strerror (errno)); - - VE_IGNORE_EINTR (g_chdir (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR))); - umask (022); - - VE_IGNORE_EINTR (close (0)); - VE_IGNORE_EINTR (close (1)); - VE_IGNORE_EINTR (close (2)); - - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ -} - -static void -gdm_start_first_unborn_local (int delay) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - /* tickle the random stuff */ - gdm_random_tick (); - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - - if (d != NULL && - d->type == TYPE_STATIC && - d->dispstat == DISPLAY_UNBORN) { - GdmXserver *svr; - g_debug ("gdm_start_first_unborn_local: " - "Starting %s", d->name); - - /* well sleep at least 'delay' seconds - * before starting */ - d->sleep_before_run = delay; - - /* only the first static display has - * timed login going on */ - if (gdm_first_login) - d->timed_login_ok = TRUE; - - svr = gdm_server_resolve (d); - - if ( ! gdm_display_manage (d)) { - gdm_display_unmanage (d); - /* only the first static display where - we actually log in gets - autologged in */ - if (svr != NULL && - svr->handled && - ! svr->chooser) - gdm_first_login = FALSE; - } else { - /* only the first static display where - we actually log in gets - autologged in */ - if (svr != NULL && - svr->handled && - ! svr->chooser) - gdm_first_login = FALSE; - break; - } - } - } -} - -void -gdm_final_cleanup (void) -{ - GSList *list, *li; - const char *pidfile; - gboolean first; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - g_debug ("gdm_final_cleanup"); - - if (extra_process > 1) { - /* we sigterm extra processes, and we - * don't wait */ - kill (-(extra_process), SIGTERM); - extra_process = 0; - } - - /* First off whack all XDMCP and FLEXI_XNEST - slaves, we'll wait for them later */ - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - if (SERVER_IS_XDMCP (d) || - SERVER_IS_PROXY (d)) { - /* set to DEAD so that we won't kill it again */ - d->dispstat = DISPLAY_DEAD; - if (d->slavepid > 1) - kill (d->slavepid, SIGTERM); - } - } - - /* Now completely unmanage the static servers */ - first = TRUE; - list = g_slist_copy (displays); - /* somewhat of a hack to kill last server - * started first. This mostly makes things end up on - * the right vt */ - list = g_slist_reverse (list); - for (li = list; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - if (SERVER_IS_XDMCP (d) || - SERVER_IS_PROXY (d)) - continue; - /* HACK! Wait 2 seconds between killing of static servers - * because X is stupid and full of races and will otherwise - * hang my keyboard */ - if ( ! first) { - /* there could be signals happening - here */ - gdm_sleep_no_signal (2); - } - first = FALSE; - gdm_display_unmanage (d); - } - g_slist_free (list); - - /* and now kill and wait for the XDMCP and FLEXI_XNEST - slaves. unmanage will not kill slaves we have already - killed unless a SIGTERM was sent in the meantime */ - - list = g_slist_copy (displays); - for (li = list; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - if (SERVER_IS_XDMCP (d) || - SERVER_IS_PROXY (d)) - gdm_display_unmanage (d); - } - g_slist_free (list); - - /* Close stuff */ - - if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP)) - gdm_xdmcp_close (); - - if (fifoconn != NULL) { - char *path; - gdm_connection_close (fifoconn); - path = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".gdmfifo", NULL); - VE_IGNORE_EINTR (g_unlink (path)); - g_free (path); - fifoconn = NULL; - } - - if (pipeconn != NULL) { - gdm_connection_close (pipeconn); - pipeconn = NULL; - } - - if (slave_fifo_pipe_fd >= 0) { - VE_IGNORE_EINTR (close (slave_fifo_pipe_fd)); - slave_fifo_pipe_fd = -1; - } - - if (unixconn != NULL) { - gdm_connection_close (unixconn); - VE_IGNORE_EINTR (g_unlink (GDM_SUP_SOCKET)); - unixconn = NULL; - } - - pidfile = GDM_PID_FILE; - if (pidfile != NULL) { - VE_IGNORE_EINTR (g_unlink (pidfile)); - } - -#ifdef HAVE_LOGINDEVPERM - (void) di_devperm_logout ("/dev/console"); -#endif /* HAVE_LOGINDEVPERM */ -} - -#ifdef __sun -void -gdm_rmdir (char *thedir) -{ - DIR *odir; - struct stat buf; - struct dirent *dp; - char thefile[FILENAME_MAX]; - - if ((stat(thedir, &buf) == -1) || ! S_ISDIR(buf.st_mode)) - return ; - - if ((rmdir (thedir) == -1) && (errno == EEXIST)) - { - odir = opendir (thedir); - do { - errno = 0; - if ((dp = readdir (odir)) != NULL) - { - if (strcmp (dp->d_name, ".") == 0 || - strcmp (dp->d_name, "..") == 0) - continue ; - snprintf (thefile, FILENAME_MAX, "%s/%s", thedir, dp->d_name); - if (stat (thefile, &buf) == -1) - continue ; - if (S_ISDIR(buf.st_mode)) - gdm_rmdir (thefile); - else - g_unlink (thefile); - } - } while (dp != NULL); - closedir (odir); - rmdir (thedir); - } -} -#endif - -static gboolean -deal_with_x_crashes (GdmDisplay *d) -{ - gboolean just_abort = FALSE; - const char *failsafe = gdm_daemon_config_get_value_string (GDM_KEY_FAILSAFE_XSERVER); - const char *keepscrashing = gdm_daemon_config_get_value_string (GDM_KEY_X_KEEPS_CRASHING); - - if ( ! d->failsafe_xserver && - ! ve_string_empty (failsafe)) { - char *bin = ve_first_word (failsafe); - /* Yay we have a failsafe */ - if ( ! ve_string_empty (bin) && - g_access (bin, X_OK) == 0) { - gdm_info (_("%s: Trying failsafe X " - "server %s"), - "deal_with_x_crashes", - failsafe); - g_free (bin); - g_free (d->command); - d->command = g_strdup (failsafe); - d->failsafe_xserver = TRUE; - return TRUE; - } - g_free (bin); - } - - /* Eeek X keeps crashing, let's try the XKeepsCrashing script */ - if ( ! ve_string_empty (keepscrashing) && - g_access (keepscrashing, X_OK|R_OK) == 0) { - pid_t pid; - - gdm_info (_("%s: Running the " - "XKeepsCrashing script"), - "deal_with_x_crashes"); - - extra_process = pid = fork (); - if (pid < 0) - extra_process = 0; - - if (pid == 0) { - char *argv[2]; - char *xlog = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log"); - - gdm_unset_signals (); - - /* Also make a new process group so that we may use - * kill -(extra_process) to kill extra process and all its - * possible children */ - setsid (); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP)) - gdm_xdmcp_close (); - - gdm_close_all_descriptors (0 /* from */, -1 /* except */, -1 /* except2 */); - - /* No error checking here - if it's messed the best response - * is to ignore & try to continue */ - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - argv[0] = (char *)gdm_daemon_config_get_value_string (GDM_KEY_X_KEEPS_CRASHING); - argv[1] = NULL; - - gdm_restoreenv (); - - /* unset DISPLAY and XAUTHORITY if they exist - * so that gdialog (if used) doesn't get confused */ - g_unsetenv ("DISPLAY"); - g_unsetenv ("XAUTHORITY"); - - /* some promised variables */ - g_setenv ("XLOG", xlog, TRUE); - g_setenv ("BINDIR", BINDIR, TRUE); - g_setenv ("SBINDIR", SBINDIR, TRUE); - g_setenv ("LIBEXECDIR", LIBEXECDIR, TRUE); - g_setenv ("SYSCONFDIR", GDMCONFDIR, TRUE); - - /* To enable gettext stuff in the script */ - g_setenv ("TEXTDOMAIN", GETTEXT_PACKAGE, TRUE); - g_setenv ("TEXTDOMAINDIR", GNOMELOCALEDIR, TRUE); - - if ( ! gdm_ok_console_language ()) { - g_unsetenv ("LANG"); - g_unsetenv ("LC_ALL"); - g_unsetenv ("LC_MESSAGES"); - g_setenv ("LANG", "C", TRUE); - g_setenv ("UNSAFE_TO_TRANSLATE", "yes", TRUE); - } - - VE_IGNORE_EINTR (execv (argv[0], argv)); - - /* yaikes! */ - _exit (32); - } else if (pid > 0) { - int status; - - if (extra_process > 1) { - int ret; - int killsignal = SIGTERM; - int storeerrno; - errno = 0; - ret = waitpid (extra_process, &status, WNOHANG); - do { - /* wait for some signal, yes this is a race */ - if (ret <= 0) - sleep (10); - errno = 0; - ret = waitpid (extra_process, &status, WNOHANG); - storeerrno = errno; - if ((ret <= 0) && gdm_daemon_config_signal_terminthup_was_notified ()) { - kill (-(extra_process), killsignal); - killsignal = SIGKILL; - } - } while (ret == 0 || (ret < 0 && storeerrno == EINTR)); - } - extra_process = 0; - - if (WIFEXITED (status) && - WEXITSTATUS (status) == 0) { - /* Yay, the user wants to try again, so - * here we go */ - return TRUE; - } else if (WIFEXITED (status) && - WEXITSTATUS (status) == 32) { - /* We couldn't run the script, just drop through */ - ; - } else { - /* Things went wrong. */ - just_abort = TRUE; - } - } - - /* if we failed to fork, or something else has happened, - * we fall through to the other options below */ - } - - /* if we have "open" we can talk to the user, not as user - * friendly as the above script, but getting there */ - if ( ! just_abort && - g_access (LIBEXECDIR "/gdmopen", X_OK) == 0) { - /* Shit if we knew what the program was to tell the user, - * the above script would have been defined and we'd run - * it for them */ - const char *error = - C_(N_("The X server (your graphical interface) " - "cannot be started. It is likely that it is not " - "set up correctly. You will need to log in on a " - "console and rerun the X configuration " - "application, then restart GDM.")); - gdm_text_message_dialog (error); - } /* else { - * At this point .... screw the user, we don't know how to - * talk to him. He's on some 'l33t system anyway, so syslog - * reading will do him good - * } */ - - gdm_error (_("Failed to start X server several times in a short time period; disabling display %s"), d->name); - - return FALSE; -} - -static gboolean -try_command (const char *command, - int *statusp) -{ - GError *error; - gboolean res; - int status; - - g_debug ("Running %s", command); - - error = NULL; - res = g_spawn_command_line_sync (command, NULL, NULL, &status, &error); - if (error != NULL) { - g_warning ("Command failed %s: %s", command, error->message); - g_error_free (error); - } - - *statusp = 0; - - if (WIFEXITED (status)) { - *statusp = WEXITSTATUS (status); - } - - return res; -} - -static gboolean -try_commands (const char **array) -{ - int i; - int status; - gboolean ret; - - ret = FALSE; - - /* the idea here is to try the first available command and return if it succeeded */ - - for (i = 0; array[i] != NULL; i++) { - if (try_command (array[i], &status)) { - ret = (status == 0); - - if (! ret) { - gdm_error (_("command failed %s: %d"), array[i], status); - } - - break; - } - } - - return ret; -} - -static void -suspend_machine (void) -{ - const gchar **suspend; - - suspend = gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND); - - gdm_info (_("Master suspending...")); - - if (suspend == NULL) { - return; - } - - try_commands (suspend); -} - -#ifdef __linux__ -static void -change_to_first_and_clear (gboolean restart) -{ - gdm_change_vt (1); - VE_IGNORE_EINTR (close (0)); - VE_IGNORE_EINTR (close (1)); - VE_IGNORE_EINTR (close (2)); - VE_IGNORE_EINTR (open ("/dev/tty1", O_WRONLY)); - VE_IGNORE_EINTR (open ("/dev/tty1", O_WRONLY)); - VE_IGNORE_EINTR (open ("/dev/tty1", O_WRONLY)); - - g_setenv ("TERM", "linux", TRUE); - - /* evil hack that will get the fonts right */ - if (g_access ("/bin/bash", X_OK) == 0) - system ("/bin/bash -l -c /bin/true"); - - /* clear screen and set to red */ - printf ("\033[H\033[J\n\n\033[1m---\n\033[1;31m "); - - if (restart) - printf (_("System is restarting, please wait ...")); - else - printf (_("System is shutting down, please wait ...")); - /* set to black */ - printf ("\033[0m\n\033[1m---\033[0m\n\n"); -} -#endif /* __linux__ */ - -static void -halt_machine (void) -{ - const char **s; - - g_debug (_("Master halting...")); - - s = gdm_daemon_config_get_value_string_array (GDM_KEY_HALT); - - if (try_commands (s)) { - /* maybe these don't run but oh well - there isn't - really a good way to know a priori if the command - will succeed. */ - gdm_final_cleanup (); - VE_IGNORE_EINTR (g_chdir ("/")); -#ifdef __linux__ - change_to_first_and_clear (FALSE); -#endif /* __linux */ - - } -} - -static void -restart_machine (void) -{ - const char **s; - - g_debug (_("Restarting computer...")); - - s = gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT); - - if (try_commands (s)) { - gdm_final_cleanup (); - VE_IGNORE_EINTR (g_chdir ("/")); - -#ifdef __linux__ - change_to_first_and_clear (TRUE); -#endif /* __linux */ - - } -} - -static void -custom_cmd (long cmd_id) -{ - gchar * key_string; - - if (cmd_id < 0 || cmd_id >= GDM_CUSTOM_COMMAND_MAX) { - /* We are just feeling very paranoid */ - gdm_error (_("custom_cmd: Custom command index %ld outside permitted range [0,%d)"), - cmd_id, GDM_CUSTOM_COMMAND_MAX); - return; - } - - key_string = g_strdup_printf ("%s%ld=", GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, cmd_id); - if (gdm_daemon_config_get_value_bool (key_string)) - custom_cmd_no_restart (cmd_id); - else - custom_cmd_restart (cmd_id); - - g_free(key_string); -} - -static void -custom_cmd_restart (long cmd_id) -{ - gchar * key_string; - char **argv; - const char *s; - - g_debug (_("Executing custom command %ld with restart option..."), cmd_id); - - gdm_final_cleanup (); - VE_IGNORE_EINTR (g_chdir ("/")); - -#ifdef __linux__ - change_to_first_and_clear (TRUE); -#endif /* __linux */ - - key_string = g_strdup_printf ("%s%ld=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_id); - - argv = NULL; - s = gdm_daemon_config_get_value_string (key_string); - g_free (key_string); - if (s != NULL) { - g_shell_parse_argv (s, NULL, &argv, NULL); - } - - if (argv != NULL && argv[0] != NULL) - VE_IGNORE_EINTR (execv (argv[0], argv)); - - g_strfreev (argv); - - gdm_error (_("%s: Execution of custom command failed: %s"), - "gdm_child_action", strerror (errno)); -} - -static void -custom_cmd_no_restart (long cmd_id) -{ - pid_t pid; - - g_debug (_("Executing custom command %ld with no restart option ..."), cmd_id); - - pid = fork (); - - if (pid < 0) { - /*failed fork*/ - gdm_error (_("custom_cmd: forking process for custom command %ld failed"), cmd_id); - return; - } - else if (pid == 0) { - /* child */ - char **argv; - const char *s; - gchar *key_string; - - key_string = g_strdup_printf ("%s%ld=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_id); - - argv = NULL; - s = gdm_daemon_config_get_value_string (key_string); - g_free (key_string); - if (s != NULL) { - g_shell_parse_argv (s, NULL, &argv, NULL); - } - - if (argv != NULL && argv[0] != NULL) - VE_IGNORE_EINTR (execv (argv[0], argv)); - - g_strfreev (argv); - - gdm_error (_("%s: Execution of custom command failed: %s"), - "gdm_child_action", strerror (errno)); - _exit (0); - } - else { - /* parent */ - gint exitstatus = 0, status; - pid_t p_stat = waitpid (1, &exitstatus, WNOHANG); - if (p_stat > 0) { - if G_LIKELY (WIFEXITED (exitstatus)){ - status = WEXITSTATUS (exitstatus); - g_debug (_("custom_cmd: child %d returned %d"), p_stat, status); - } - return; - } - } -} - -static gboolean -gdm_cleanup_children (void) -{ - pid_t pid; - gint exitstatus = 0, status; - GdmDisplay *d = NULL; - gboolean crashed; - gboolean sysmenu; - - /* Pid and exit status of slave that died */ - pid = waitpid (-1, &exitstatus, WNOHANG); - - if (pid <= 0) - return FALSE; - - if G_LIKELY (WIFEXITED (exitstatus)) { - status = WEXITSTATUS (exitstatus); - crashed = FALSE; - g_debug ("gdm_cleanup_children: child %d returned %d", pid, status); - } else { - status = EXIT_SUCCESS; - crashed = TRUE; - if (WIFSIGNALED (exitstatus)) { - if (WTERMSIG (exitstatus) == SIGTERM || - WTERMSIG (exitstatus) == SIGINT) { - /* we send these signals, sometimes children don't handle them */ - g_debug ("gdm_cleanup_children: child %d died of signal %d (TERM/INT)", pid, - (int)WTERMSIG (exitstatus)); - } else { - gdm_error ("gdm_cleanup_children: child %d crashed of signal %d", pid, - (int)WTERMSIG (exitstatus)); - } - } else { - gdm_error ("gdm_cleanup_children: child %d crashed", pid); - } - } - - if (pid == extra_process) { - /* an extra process died, yay! */ - extra_process = 0; - extra_status = exitstatus; - return TRUE; - } - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (pid); - - if (d == NULL) - return TRUE; - - /* whack connections about this display */ - if (unixconn != NULL) - gdm_kill_subconnections_with_display (unixconn, d); - - if G_UNLIKELY (crashed) { - gdm_error ("gdm_cleanup_children: Slave crashed, killing its " - "children"); - - if (d->sesspid > 1) - kill (-(d->sesspid), SIGTERM); - d->sesspid = 0; - if (d->greetpid > 1) - kill (-(d->greetpid), SIGTERM); - d->greetpid = 0; - if (d->chooserpid > 1) - kill (-(d->chooserpid), SIGTERM); - d->chooserpid = 0; - if (d->servpid > 1) - kill (d->servpid, SIGTERM); - d->servpid = 0; - - if (gdm_daemon_config_get_value_bool (GDM_KEY_DYNAMIC_XSERVERS)) { - /* XXX - This needs to be handled better */ - gdm_server_whack_lockfile (d); - } - - /* race avoider */ - gdm_sleep_no_signal (1); - } - - /* null all these, they are not valid most definately */ - d->servpid = 0; - d->sesspid = 0; - d->greetpid = 0; - d->chooserpid = 0; - - /* definately not logged in now */ - d->logged_in = FALSE; - g_free (d->login); - d->login = NULL; - - /* Declare the display dead */ - d->slavepid = 0; - d->dispstat = DISPLAY_DEAD; - - sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name); - - if ( ! sysmenu && - (status == DISPLAY_RESTARTGDM || - status == DISPLAY_REBOOT || - status == DISPLAY_SUSPEND || - status == DISPLAY_HALT)) { - gdm_info (_("Restart GDM, Restart machine, Suspend, or Halt request when there is no system menu from display %s"), d->name); - status = DISPLAY_REMANAGE; - } - - if ( ! d->attached && - (status == DISPLAY_RESTARTGDM || - status == DISPLAY_REBOOT || - status == DISPLAY_SUSPEND || - status == DISPLAY_HALT)) { - gdm_info (_("Restart GDM, Restart machine, Suspend or Halt request from a non-static display %s"), d->name); - status = DISPLAY_REMANAGE; - } - - if (status == DISPLAY_RUN_CHOOSER) { - /* use the chooser on the next run (but only if allowed) */ - if (sysmenu && - gdm_daemon_config_get_value_bool_per_display (GDM_KEY_CHOOSER_BUTTON, d->name)) - d->use_chooser = TRUE; - status = DISPLAY_REMANAGE; - /* go around the display loop detection, these are short - * sessions, so this decreases the chances of the loop - * detection being hit */ - d->last_loop_start_time = 0; - } - - if (status == DISPLAY_CHOSEN) { - /* forget about this indirect id, since this - * display will be dead very soon, and we don't want it - * to take the indirect display with it */ - d->indirect_id = 0; - status = DISPLAY_REMANAGE; - } - - if (status == DISPLAY_GREETERFAILED) { - if (d->managetime + 10 >= time (NULL)) { - d->try_different_greeter = TRUE; - } else { - d->try_different_greeter = FALSE; - } - /* now just remanage */ - status = DISPLAY_REMANAGE; - } else { - d->try_different_greeter = FALSE; - } - - /* checkout if we can actually do stuff */ - switch (status) { - case DISPLAY_REBOOT: - if (gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT) == NULL) - status = DISPLAY_REMANAGE; - break; - case DISPLAY_HALT: - if (gdm_daemon_config_get_value_string_array (GDM_KEY_HALT) == NULL) - status = DISPLAY_REMANAGE; - break; - case DISPLAY_SUSPEND: - if (gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) == NULL) - status = DISPLAY_REMANAGE; - break; - default: - break; - } - - /* if we crashed clear the theme */ - if (crashed) { - g_free (d->theme_name); - d->theme_name = NULL; - } - - start_autopsy: - - /* Autopsy */ - switch (status) { - - case DISPLAY_ABORT: /* Bury this display for good */ - gdm_info (_("%s: Aborting display %s"), - "gdm_child_action", d->name); - - gdm_try_logout_action (d); - gdm_safe_restart (); - - gdm_display_unmanage (d); - - /* If there are some pending statics, start them now */ - gdm_start_first_unborn_local (3 /* delay */); - break; - - case DISPLAY_REBOOT: /* Restart machine */ - restart_machine (); - - status = DISPLAY_REMANAGE; - goto start_autopsy; - break; - - case DISPLAY_HALT: /* Halt machine */ - halt_machine (); - - status = DISPLAY_REMANAGE; - goto start_autopsy; - break; - - case DISPLAY_SUSPEND: /* Suspend machine */ - /* XXX: this is ugly, why should there be a suspend like this, - * see GDM_SOP_SUSPEND_MACHINE */ - suspend_machine (); - - status = DISPLAY_REMANAGE; - goto start_autopsy; - break; - - case DISPLAY_RESTARTGDM: - gdm_restart_now (); - break; - - case DISPLAY_XFAILED: /* X sucks */ - g_debug ("X failed!"); - /* inform about error if needed */ - if (d->socket_conn != NULL) { - GdmConnection *conn = d->socket_conn; - d->socket_conn = NULL; - gdm_connection_set_close_notify (conn, NULL, NULL); - gdm_connection_write (conn, "ERROR 3 X failed\n"); - } - - gdm_try_logout_action (d); - gdm_safe_restart (); - - /* in remote/flexi case just drop to _REMANAGE */ - if (d->type == TYPE_STATIC) { - time_t now = time (NULL); - d->x_faileds++; - /* This really is likely the first time if it's been, - some time, say 5 minutes */ - if (now - d->last_x_failed > (5*60)) { - /* reset */ - d->x_faileds = 1; - d->last_x_failed = now; - /* well sleep at least 3 seconds before starting */ - d->sleep_before_run = 3; - } else if (d->x_faileds >= 3) { - g_debug ("gdm_child_action: dealing with X crashes"); - if ( ! deal_with_x_crashes (d)) { - g_debug ("gdm_child_action: Aborting display"); - /* an original way to deal with these things: - * "Screw you guys, I'm going home!" */ - gdm_display_unmanage (d); - - /* If there are some pending statics, - * start them now */ - gdm_start_first_unborn_local (3 /* delay */); - break; - } - g_debug ("gdm_child_action: Trying again"); - - /* reset */ - d->x_faileds = 0; - d->last_x_failed = 0; - } else { - /* well sleep at least 3 seconds before starting */ - d->sleep_before_run = 3; - } - /* go around the display loop detection, we're doing - * our own here */ - d->last_loop_start_time = 0; - } - /* fall through */ - - case DISPLAY_REMANAGE: /* Remanage display */ - default: - g_debug ("gdm_child_action: In remanage"); - - /* if we did REMANAGE, that means that we're no longer failing */ - if (status == DISPLAY_REMANAGE) { - /* reset */ - d->x_faileds = 0; - d->last_x_failed = 0; - } - - /* inform about error if needed */ - if (d->socket_conn != NULL) { - GdmConnection *conn = d->socket_conn; - d->socket_conn = NULL; - gdm_connection_set_close_notify (conn, NULL, NULL); - gdm_connection_write (conn, "ERROR 2 Startup errors\n"); - } - - gdm_try_logout_action (d); - gdm_safe_restart (); - - /* This is a static server so we start a new slave */ - if (d->type == TYPE_STATIC) { - if ( ! gdm_display_manage (d)) { - gdm_display_unmanage (d); - /* If there are some pending statics, - * start them now */ - gdm_start_first_unborn_local (3 /* delay */); - } - } else if (d->type == TYPE_FLEXI || d->type == TYPE_FLEXI_XNEST) { - /* if this was a chooser session and we have chosen a host, - then we don't want to unmanage, we want to manage and - choose that host */ - if (d->chosen_hostname != NULL || d->use_chooser) { - if ( ! gdm_display_manage (d)) { - gdm_display_unmanage (d); - } - } else { - /* else, this is a one time thing */ - gdm_display_unmanage (d); - } - /* Remote displays will send a request to be managed */ - } else /* TYPE_XDMCP */ { - gdm_display_unmanage (d); - } - - break; - } - - gdm_try_logout_action (d); - gdm_safe_restart (); - - return TRUE; -} - -static void -gdm_restart_now (void) -{ - gdm_info (_("GDM restarting ...")); - gdm_final_cleanup (); - gdm_restoreenv (); - VE_IGNORE_EINTR (execvp (stored_argv[0], stored_argv)); - gdm_error (_("Failed to restart self")); - _exit (1); -} - -static void -gdm_safe_restart (void) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - if ( ! gdm_restart_mode) - return; - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - - if (d->logged_in) - return; - } - - gdm_restart_now (); -} - -static void -gdm_do_logout_action (GdmLogoutAction logout_action) -{ - switch (logout_action) { - case GDM_LOGOUT_ACTION_HALT: - halt_machine (); - break; - - case GDM_LOGOUT_ACTION_REBOOT: - restart_machine (); - break; - - case GDM_LOGOUT_ACTION_SUSPEND: - suspend_machine (); - break; - - default: - /* This is a bit ugly but its the only place we can - check for the range of values */ - if (logout_action >= GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST && - logout_action <= GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST) - custom_cmd (logout_action - GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST); - break; - } -} - -static void -gdm_try_logout_action (GdmDisplay *disp) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - if (disp != NULL && - disp->logout_action != GDM_LOGOUT_ACTION_NONE && - ! disp->logged_in) { - gdm_do_logout_action (disp->logout_action); - disp->logout_action = GDM_LOGOUT_ACTION_NONE; - return; - } - - if (safe_logout_action == GDM_LOGOUT_ACTION_NONE) - return; - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - - if (d->logged_in) - return; - } - - gdm_do_logout_action (safe_logout_action); - safe_logout_action = GDM_LOGOUT_ACTION_NONE; -} - -static void -main_daemon_abrt (int sig) -{ - /* FIXME: note that this could mean out of memory */ - gdm_error (_("main daemon: Got SIGABRT. Something went very wrong. Going down!")); - gdm_final_cleanup (); - exit (EXIT_FAILURE); -} - -static gboolean -mainloop_sig_callback (int sig, gpointer data) -{ - /* signals are at somewhat random times aren't they? */ - gdm_random_tick (); - - g_debug ("mainloop_sig_callback: Got signal %d", (int)sig); - switch (sig) - { - case SIGCHLD: - while (gdm_cleanup_children ()) - ; - break; - - case SIGINT: - case SIGTERM: - g_debug ("mainloop_sig_callback: Got TERM/INT. Going down!"); - gdm_final_cleanup (); - exit (EXIT_SUCCESS); - break; - -#ifdef SIGXFSZ - case SIGXFSZ: - gdm_error ("main daemon: Hit file size rlimit, restarting!"); - gdm_restart_now (); - break; -#endif - -#ifdef SIGXCPU - case SIGXCPU: - gdm_error ("main daemon: Hit CPU rlimit, restarting!"); - gdm_restart_now (); - break; -#endif - - case SIGHUP: - gdm_restart_now (); - break; - - case SIGUSR1: - gdm_restart_mode = TRUE; - gdm_safe_restart (); - break; - - default: - break; - } - - return TRUE; -} - -/* - * main: The main daemon control - */ - -static void -store_argv (int argc, char *argv[]) -{ - int i; - - stored_argv = g_new0 (char *, argc + 1); - for (i = 0; i < argc; i++) - stored_argv[i] = g_strdup (argv[i]); - stored_argv[i] = NULL; - stored_argc = argc; -} - -static void -close_notify (gpointer data) -{ - GdmConnection **conn = data; - * conn = NULL; -} - -static void -create_connections (void) -{ - int p[2]; - gchar *path; - - path = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".gdmfifo", NULL); - fifoconn = gdm_connection_open_fifo (path, 0660); - g_free (path); - - if G_LIKELY (fifoconn != NULL) { - gdm_connection_set_handler (fifoconn, - gdm_handle_message, - NULL /* data */, - NULL /* destroy_notify */); - gdm_connection_set_close_notify (fifoconn, - &fifoconn, - close_notify); - } - - if G_UNLIKELY (pipe (p) < 0) { - slave_fifo_pipe_fd = -1; - pipeconn = NULL; - } else { - slave_fifo_pipe_fd = p[1]; - pipeconn = gdm_connection_open_fd (p[0]); - } - - if G_LIKELY (pipeconn != NULL) { - gdm_connection_set_handler (pipeconn, - gdm_handle_message, - NULL /* data */, - NULL /* destroy_notify */); - gdm_connection_set_close_notify (pipeconn, - &pipeconn, - close_notify); - } else { - VE_IGNORE_EINTR (close (p[0])); - VE_IGNORE_EINTR (close (p[1])); - slave_fifo_pipe_fd = -1; - } - - unixconn = gdm_connection_open_unix (GDM_SUP_SOCKET, 0666); - - if G_LIKELY (unixconn != NULL) { - gdm_connection_set_handler (unixconn, - gdm_handle_user_message, - NULL /* data */, - NULL /* destroy_notify */); - gdm_connection_set_nonblock (unixconn, TRUE); - gdm_connection_set_close_notify (unixconn, - &unixconn, - close_notify); - } -} - -static void -calc_sqrt2 (void) -{ - unsigned long n = 0, h = 0; - double x; - printf ("\n"); - for (;;) { - x = g_random_double_range (1.0, 2.0); - if (x*x <= 2.0) - h++; - n++; - if ( ! (n & 0xfff)) { - double sqrttwo = 1.0 + ((double)h)/(double)n; - printf ("sqrt(2) ~~ %1.10f\t(1 + %lu/%lu) " - "iteration: %lu \r", - sqrttwo, h, n, n); - } - } -} - -GOptionEntry options [] = { - { "nodaemon", '\0', 0, G_OPTION_ARG_NONE, - &no_daemon, N_("Do not fork into the background"), NULL }, - { "no-console", '\0', 0, G_OPTION_ARG_NONE, - &no_console, N_("No console (static) servers to be run"), NULL }, - { "config", '\0', 0, G_OPTION_ARG_STRING, - &config_file, N_("Alternative GDM System Defaults configuration file"), N_("CONFIGFILE") }, - { "preserve-ld-vars", '\0', 0, G_OPTION_ARG_NONE, - &preserve_ld_vars, N_("Preserve LD_* variables"), NULL }, - { "version", '\0', 0, G_OPTION_ARG_NONE, - &print_version, N_("Print GDM version"), NULL }, - { "wait-for-go", '\0', 0, G_OPTION_ARG_NONE, - &gdm_wait_for_go, N_("Start the first X server but then halt until we get a GO in the fifo"), NULL }, - { "monte-carlo-sqrt2", 0, 0, G_OPTION_ARG_NONE, - &monte_carlo_sqrt2, NULL, NULL }, - { NULL } -}; - -static gboolean -linux_only_is_running (pid_t pid) -{ - char resolved_self[PATH_MAX]; - char resolved_running[PATH_MAX]; - - char *running = g_strdup_printf ("/proc/%lu/exe", (gulong)pid); - - if (realpath ("/proc/self/exe", resolved_self) == NULL) { - g_free (running); - /* probably not a linux system */ - return TRUE; - } - - if (realpath (running, resolved_running) == NULL) { - g_free (running); - /* probably not a linux system */ - return TRUE; - } - - g_free (running); - - if (strcmp (resolved_running, resolved_self) == 0) - return TRUE; - return FALSE; -} - -static void -ensure_desc_012 (void) -{ - int fd; - /* We here ensure descriptors 0, 1 and 2 - * we of course count on the fact that open - * opens the lowest available descriptor */ - for (;;) { - fd = gdm_open_dev_null (O_RDWR); - /* Once we are up to 3, we're beyond stdin, - * stdout and stderr */ - if (fd >= 3) { - VE_IGNORE_EINTR (close (fd)); - break; - } - } -} - -/* initially if we get a TERM or INT we just want to die, - but we want to also kill an extra process if it exists */ -static void -initial_term_int (int signal) -{ - if (extra_process > 1) - kill (-(extra_process), SIGTERM); - _exit (EXIT_FAILURE); -} - -static void -gdm_make_global_cookie (void) -{ - FILE *fp; - char *file; - mode_t oldmode; - - gdm_cookie_generate ((char **)&gdm_global_cookie, (char **)&gdm_global_bcookie); - - file = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".cookie", NULL); - VE_IGNORE_EINTR (g_unlink (file)); - - oldmode = umask (077); - fp = gdm_safe_fopen_w (file); - umask (oldmode); - if G_UNLIKELY (fp == NULL) { - gdm_error (_("Can't open %s for writing"), file); - g_free (file); - return; - } - - VE_IGNORE_EINTR (fprintf (fp, "%s\n", gdm_global_cookie)); - - /* FIXME: What about out of disk space errors? */ - errno = 0; - VE_IGNORE_EINTR (fclose (fp)); - if G_UNLIKELY (errno != 0) { - gdm_error (_("Can't write to %s: %s"), file, - strerror (errno)); - } - - g_free (file); -} - -int -main (int argc, char *argv[]) -{ - FILE *pf; - sigset_t mask; - struct sigaction sig, child, abrt; - GOptionContext *ctx; - const char *pidfile; - int i; - - /* semi init pseudorandomness */ - gdm_random_tick (); - - /* We here ensure descriptors 0, 1 and 2 */ - ensure_desc_012 (); - - /* store all initial stuff, args, env, rlimits, runlevel */ - store_argv (argc, argv); - gdm_saveenv (); - gdm_get_initial_limits (); - - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - textdomain (GETTEXT_PACKAGE); - - setlocale (LC_ALL, ""); - - /* Initialize runtime environment */ - umask (022); - - g_type_init (); - - ctx = g_option_context_new (_("- The GNOME login manager")); - g_option_context_add_main_entries (ctx, options, _("main options")); - - /* preprocess the arguments to support the xdm style -nodaemon - * option - */ - for (i = 0; i < argc; i++) { - if (strcmp (argv[i], "-nodaemon") == 0) - argv[i] = (char *) "--nodaemon"; - } - - g_option_context_parse (ctx, &argc, &argv, NULL); - g_option_context_free (ctx); - - if (monte_carlo_sqrt2) { - calc_sqrt2 (); - return 0; - } - - if (print_version) { - printf ("GDM %s\n", VERSION); - fflush (stdout); - exit (0); - } - - gdm_log_init (); - /* Parse configuration file */ - gdm_daemon_config_parse (config_file, no_console); - gdm_log_set_debug (gdm_daemon_config_get_bool_for_id (GDM_ID_DEBUG)); - - /* XDM compliant error message */ - if G_UNLIKELY (getuid () != 0) { - /* make sure the pid file doesn't get wiped */ - gdm_error (_("Only root wants to run GDM\n")); - exit (-1); - } - - main_loop = g_main_loop_new (NULL, FALSE); - - /* initial TERM/INT handler */ - sig.sa_handler = initial_term_int; - sig.sa_flags = SA_RESTART; - sigemptyset (&sig.sa_mask); - - /* - * Do not call gdm_fail before calling gdm_config_parse () - * since the gdm_fail function uses config data - */ - if G_UNLIKELY (sigaction (SIGTERM, &sig, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "TERM", strerror (errno)); - - if G_UNLIKELY (sigaction (SIGINT, &sig, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "INT", strerror (errno)); - - /* get the name of the root user */ - gdm_root_user (); - - pidfile = GDM_PID_FILE; - - /* Check if another gdm process is already running */ - if (g_access (pidfile, R_OK) == 0) { - - /* Check if the existing process is still alive. */ - gint pidv; - - pf = fopen (pidfile, "r"); - - if (pf != NULL && - fscanf (pf, "%d", &pidv) == 1 && - kill (pidv, 0) == 0 && - linux_only_is_running (pidv)) { - /* make sure the pid file doesn't get wiped */ - VE_IGNORE_EINTR (fclose (pf)); - gdm_fail (_("GDM already running. Aborting!")); - } - - if (pf != NULL) - VE_IGNORE_EINTR (fclose (pf)); - } - - /* Become daemon unless started in -nodaemon mode or child of init */ - if (no_daemon || getppid () == 1) { - - /* Write pid to pidfile */ - errno = 0; - if ((pf = gdm_safe_fopen_w (pidfile)) != NULL) { - errno = 0; - VE_IGNORE_EINTR (fprintf (pf, "%d\n", (int)getpid ())); - VE_IGNORE_EINTR (fclose (pf)); - if (errno != 0) { - /* FIXME: how to handle this? */ - gdm_fdprintf (2, _("Cannot write PID file %s: possibly out of diskspace. Error: %s\n"), - pidfile, strerror (errno)); - gdm_error (_("Cannot write PID file %s: possibly out of diskspace. Error: %s"), - pidfile, strerror (errno)); - - } - } else if (errno != 0) { - /* FIXME: how to handle this? */ - gdm_fdprintf (2, _("Cannot write PID file %s: possibly out of diskspace. Error: %s\n"), - pidfile, strerror (errno)); - gdm_error (_("Cannot write PID file %s: possibly out of diskspace. Error: %s"), - pidfile, strerror (errno)); - - } - - VE_IGNORE_EINTR (g_chdir (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR))); - umask (022); - } - else - gdm_daemonify (); - -#ifdef __sun - g_unlink (SDTLOGIN_DIR); - g_mkdir (SDTLOGIN_DIR, 0700); -#endif - - /* Signal handling */ - ve_signal_add (SIGCHLD, mainloop_sig_callback, NULL); - ve_signal_add (SIGTERM, mainloop_sig_callback, NULL); - ve_signal_add (SIGINT, mainloop_sig_callback, NULL); - ve_signal_add (SIGHUP, mainloop_sig_callback, NULL); - ve_signal_add (SIGUSR1, mainloop_sig_callback, NULL); - - sig.sa_handler = ve_signal_notify; - sig.sa_flags = SA_RESTART; - sigemptyset (&sig.sa_mask); - - if G_UNLIKELY (sigaction (SIGTERM, &sig, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "TERM", strerror (errno)); - - if G_UNLIKELY (sigaction (SIGINT, &sig, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "INT", strerror (errno)); - - if G_UNLIKELY (sigaction (SIGHUP, &sig, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "HUP", strerror (errno)); - - if G_UNLIKELY (sigaction (SIGUSR1, &sig, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "USR1", strerror (errno)); - - /* some process limit signals we catch and restart on, - note that we don't catch these in the slave, but then - we catch those in the main daemon as slave crashing - (terminated by signal), and we clean up appropriately */ -#ifdef SIGXCPU - ve_signal_add (SIGXCPU, mainloop_sig_callback, NULL); - if G_UNLIKELY (sigaction (SIGXCPU, &sig, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "XCPU", strerror (errno)); -#endif -#ifdef SIGXFSZ - ve_signal_add (SIGXFSZ, mainloop_sig_callback, NULL); - if G_UNLIKELY (sigaction (SIGXFSZ, &sig, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "XFSZ", strerror (errno)); -#endif - - /* cannot use mainloop for SIGABRT, the handler can never - return */ - abrt.sa_handler = main_daemon_abrt; - abrt.sa_flags = SA_RESTART; - sigemptyset (&abrt.sa_mask); - - if G_UNLIKELY (sigaction (SIGABRT, &abrt, NULL) < 0) - gdm_fail (_("%s: Error setting up %s signal handler: %s"), - "main", "ABRT", strerror (errno)); - - child.sa_handler = ve_signal_notify; - child.sa_flags = SA_RESTART|SA_NOCLDSTOP; - sigemptyset (&child.sa_mask); - sigaddset (&child.sa_mask, SIGCHLD); - - if G_UNLIKELY (sigaction (SIGCHLD, &child, NULL) < 0) - gdm_fail (_("%s: Error setting up CHLD signal handler"), "gdm_main"); - - sigemptyset (&mask); - sigaddset (&mask, SIGINT); - sigaddset (&mask, SIGTERM); - sigaddset (&mask, SIGCHLD); - sigaddset (&mask, SIGHUP); - sigaddset (&mask, SIGUSR1); - sigaddset (&mask, SIGABRT); -#ifdef SIGXCPU - sigaddset (&mask, SIGXCPU); -#endif -#ifdef SIGXFSZ - sigaddset (&mask, SIGXFSZ); -#endif - sigprocmask (SIG_UNBLOCK, &mask, NULL); - - gdm_signal_ignore (SIGUSR2); - gdm_signal_ignore (SIGPIPE); - - /* ignore power failures, up to user processes to - * handle things correctly */ -#ifdef SIGPWR - gdm_signal_ignore (SIGPWR); -#endif - /* can we ever even get this one? */ -#ifdef SIGLOST - gdm_signal_ignore (SIGLOST); -#endif - - g_debug ("gdm_main: Here we go..."); - -#ifdef HAVE_LOGINDEVPERM - di_devperm_login ("/dev/console", gdm_daemon_config_get_gdmuid (), gdm_daemon_config_get_gdmgid (), NULL); -#endif /* HAVE_LOGINDEVPERM */ - - /* Init XDMCP if applicable */ - if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go) { - gdm_xdmcp_init (); - } - - create_connections (); - - /* make sure things (currently /tmp/.ICE-unix and /tmp/.X11-unix) - * are sane */ - gdm_ensure_sanity () ; - - /* Make us a unique global cookie to authenticate */ - gdm_make_global_cookie (); - - /* Start static X servers */ - gdm_start_first_unborn_local (0 /* delay */); - - /* Accept remote connections */ - if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go) { - g_debug ("Accepting XDMCP connections..."); - gdm_xdmcp_run (); - } - - /* We always exit via exit (), and sadly we need to g_main_quit () - * at times not knowing if it's this main or a recursive one we're - * quitting. - */ - while (1) - { - g_main_loop_run (main_loop); - g_debug ("main: Exited main loop"); - } - - return EXIT_SUCCESS; /* Not reached */ -} - -static gboolean -order_exists (int order) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - if (d->x_servers_order == order) - return TRUE; - } - return FALSE; -} - -static int -get_new_order (GdmDisplay *d) -{ - int order; - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - /* first try the position in the 'displays' list as - * our order */ - for (order = 0, li = displays; li != NULL; order++, li = li->next) { - if (li->data == d) - break; - } - /* next make sure it's unique */ - while (order_exists (order)) - order++; - return order; -} - -static void -write_x_servers (GdmDisplay *d) -{ - FILE *fp; - char *file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xservers"); - int i; - int bogusname; - - if (d->x_servers_order < 0) - d->x_servers_order = get_new_order (d); - - fp = gdm_safe_fopen_w (file); - if G_UNLIKELY (fp == NULL) { - gdm_error (_("Can't open %s for writing"), file); - g_free (file); - return; - } - - for (bogusname = 0, i = 0; i < d->x_servers_order; bogusname++, i++) { - char buf[32]; - g_snprintf (buf, sizeof (buf), ":%d", bogusname); - if (strcmp (buf, d->name) == 0) - g_snprintf (buf, sizeof (buf), ":%d", ++bogusname); - VE_IGNORE_EINTR (fprintf (fp, "%s local /usr/X11R6/bin/Xbogus\n", buf)); - } - - if (SERVER_IS_LOCAL (d)) { - char **argv; - char *command; - int argc; - argc = 0; - argv = NULL; - gdm_server_resolve_command_line (d, - FALSE, /* resolve_flags */ - NULL, /* vtarg */ - &argc, - &argv); - command = g_strjoinv (" ", argv); - g_strfreev (argv); - VE_IGNORE_EINTR (fprintf (fp, "%s local %s\n", d->name, command)); - g_free (command); - } else { - VE_IGNORE_EINTR (fprintf (fp, "%s foreign\n", d->name)); - } - - /* FIXME: What about out of disk space errors? */ - errno = 0; - VE_IGNORE_EINTR (fclose (fp)); - if G_UNLIKELY (errno != 0) { - gdm_error (_("Can't write to %s: %s"), file, - strerror (errno)); - } - - g_free (file); -} - -static void -send_slave_ack_dialog_int (GdmDisplay *d, int type, int response) -{ - if (d->master_notify_fd >= 0) { - char *not; - - not = g_strdup_printf ("%c%c%d\n", GDM_SLAVE_NOTIFY_RESPONSE, type, response); - VE_IGNORE_EINTR (write (d->master_notify_fd, not, strlen (not))); - - g_free (not); - } - if (d->slavepid > 1) { - /* now yield the CPU as the other process has more - useful work to do then we do */ -#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD) - sched_yield (); -#endif - } -} - -static void -send_slave_ack_dialog_char (GdmDisplay *d, int type, const char *resp) -{ - if (d->master_notify_fd >= 0) { - if (resp == NULL) { - char not[3]; - - not[0] = GDM_SLAVE_NOTIFY_RESPONSE; - not[1] = type; - not[2] = '\n'; - VE_IGNORE_EINTR (write (d->master_notify_fd, not, 3)); - } else { - char *not = g_strdup_printf ("%c%c%s\n", - GDM_SLAVE_NOTIFY_RESPONSE, - type, - resp); - VE_IGNORE_EINTR (write (d->master_notify_fd, not, strlen (not))); - g_free (not); - } - } - if (d->slavepid > 1) { - /* now yield the CPU as the other process has more - useful work to do then we do */ -#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD) - sched_yield (); -#endif - } -} - -static void -send_slave_ack (GdmDisplay *d, const char *resp) -{ - if (d->master_notify_fd >= 0) { - if (resp == NULL) { - char not[2]; - not[0] = GDM_SLAVE_NOTIFY_ACK; - not[1] = '\n'; - VE_IGNORE_EINTR (write (d->master_notify_fd, not, 2)); - } else { - char *not = g_strdup_printf ("%c%s\n", - GDM_SLAVE_NOTIFY_ACK, - resp); - VE_IGNORE_EINTR (write (d->master_notify_fd, not, strlen (not))); - g_free (not); - } - } - if (d->slavepid > 1) { - kill (d->slavepid, SIGUSR2); - /* now yield the CPU as the other process has more - useful work to do then we do */ -#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD) - sched_yield (); -#endif - } -} - -static void -send_slave_command (GdmDisplay *d, const char *command) -{ - if (d->master_notify_fd >= 0) { - char *cmd = g_strdup_printf ("%c%s\n", - GDM_SLAVE_NOTIFY_COMMAND, - command); - VE_IGNORE_EINTR (write (d->master_notify_fd, cmd, strlen (cmd))); - g_free (cmd); - } - if (d->slavepid > 1) { - kill (d->slavepid, SIGUSR2); - /* now yield the CPU as the other process has more - useful work to do then we do */ -#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD) - sched_yield (); -#endif - } -} - -static void -gdm_handle_message (GdmConnection *conn, const char *msg, gpointer data) -{ - /* Evil!, all this for debugging? */ - if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) { - if (strncmp (msg, GDM_SOP_COOKIE " ", - strlen (GDM_SOP_COOKIE " ")) == 0) { - char *s = g_strndup - (msg, strlen (GDM_SOP_COOKIE " XXXX XX")); - /* cut off most of the cookie for "security" */ - g_debug ("Handling message: '%s...'", s); - g_free (s); - } else if (strncmp (msg, GDM_SOP_SYSLOG " ", - strlen (GDM_SOP_SYSLOG " ")) != 0) { - /* Don't print out the syslog message as it will - * be printed out anyway as that's the whole point - * of the message. */ - g_debug ("Handling message: '%s'", msg); - } - } - - if (strncmp (msg, GDM_SOP_CHOSEN " ", - strlen (GDM_SOP_CHOSEN " ")) == 0) { - gdm_choose_data (msg); - } else if (strncmp (msg, GDM_SOP_CHOSEN_LOCAL " ", - strlen (GDM_SOP_CHOSEN_LOCAL " ")) == 0) { - GdmDisplay *d; - long slave_pid; - char *p; - - if (sscanf (msg, GDM_SOP_CHOSEN_LOCAL " %ld", &slave_pid) - != 1) - return; - p = strchr (msg, ' '); - if (p != NULL) - p = strchr (p+1, ' '); - if (p == NULL) - return; - p++; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - g_free (d->chosen_hostname); - d->chosen_hostname = g_strdup (p); - g_debug ("Got CHOSEN_LOCAL == %s", p); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_XPID " ", - strlen (GDM_SOP_XPID " ")) == 0) { - GdmDisplay *d; - long slave_pid, pid; - - if (sscanf (msg, GDM_SOP_XPID " %ld %ld", &slave_pid, &pid) - != 2) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - d->servpid = pid; - g_debug ("Got XPID == %ld", (long)pid); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_SESSPID " ", - strlen (GDM_SOP_SESSPID " ")) == 0) { - GdmDisplay *d; - long slave_pid, pid; - - if (sscanf (msg, GDM_SOP_SESSPID " %ld %ld", &slave_pid, &pid) - != 2) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - d->sesspid = pid; - g_debug ("Got SESSPID == %ld", (long)pid); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_GREETPID " ", - strlen (GDM_SOP_GREETPID " ")) == 0) { - GdmDisplay *d; - long slave_pid, pid; - - if (sscanf (msg, GDM_SOP_GREETPID " %ld %ld", &slave_pid, &pid) - != 2) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - d->greetpid = pid; - g_debug ("Got GREETPID == %ld", (long)pid); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_CHOOSERPID " ", - strlen (GDM_SOP_CHOOSERPID " ")) == 0) { - GdmDisplay *d; - long slave_pid, pid; - - if (sscanf (msg, GDM_SOP_CHOOSERPID " %ld %ld", - &slave_pid, &pid) != 2) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - d->chooserpid = pid; - g_debug ("Got CHOOSERPID == %ld", (long)pid); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_LOGGED_IN " ", - strlen (GDM_SOP_LOGGED_IN " ")) == 0) { - GdmDisplay *d; - long slave_pid; - int logged_in; - if (sscanf (msg, GDM_SOP_LOGGED_IN " %ld %d", &slave_pid, - &logged_in) != 2) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - d->logged_in = logged_in ? TRUE : FALSE; - g_debug ("Got logged in == %s", - d->logged_in ? "TRUE" : "FALSE"); - - /* whack connections about this display if a user - * just logged out since we don't want such - * connections persisting to be authenticated */ - if ( ! logged_in && unixconn != NULL) - gdm_kill_subconnections_with_display (unixconn, d); - - /* if the user just logged out, - * let's see if it's safe to restart */ - if ( ! d->logged_in) { - gdm_try_logout_action (d); - gdm_safe_restart (); - } - - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_DISP_NUM " ", - strlen (GDM_SOP_DISP_NUM " ")) == 0) { - GdmDisplay *d; - long slave_pid; - int disp_num; - - if (sscanf (msg, GDM_SOP_DISP_NUM " %ld %d", - &slave_pid, &disp_num) != 2) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - g_free (d->name); - d->name = g_strdup_printf (":%d", disp_num); - d->dispnum = disp_num; - g_debug ("Got DISP_NUM == %d", disp_num); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_VT_NUM " ", - strlen (GDM_SOP_VT_NUM " ")) == 0) { - GdmDisplay *d; - long slave_pid; - int vt_num; - - if (sscanf (msg, GDM_SOP_VT_NUM " %ld %d", - &slave_pid, &vt_num) != 2) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - d->vt = vt_num; - g_debug ("Got VT_NUM == %d", vt_num); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_LOGIN " ", - strlen (GDM_SOP_LOGIN " ")) == 0) { - GdmDisplay *d; - long slave_pid; - char *p; - - if (sscanf (msg, GDM_SOP_LOGIN " %ld", - &slave_pid) != 1) - return; - p = strchr (msg, ' '); - if (p != NULL) - p = strchr (p+1, ' '); - if (p == NULL) - return; - - p++; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - g_free (d->login); - d->login = g_strdup (p); - g_debug ("Got LOGIN == %s", p); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_QUERYLOGIN " ", - strlen (GDM_SOP_QUERYLOGIN " ")) == 0) { - GdmDisplay *d; - long slave_pid; - char *p; - - if (sscanf (msg, GDM_SOP_QUERYLOGIN " %ld", - &slave_pid) != 1) - return; - p = strchr (msg, ' '); - if (p != NULL) - p = strchr (p+1, ' '); - if (p == NULL) - return; - - p++; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - GString *resp = NULL; - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - g_debug ("Got QUERYLOGIN %s", p); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *di = li->data; - if (di->logged_in && - di->login != NULL && - strcmp (di->login, p) == 0) { - gboolean migratable = FALSE; - - if (resp == NULL) - resp = g_string_new (NULL); - else - resp = g_string_append_c (resp, ','); - - g_string_append (resp, di->name); - g_string_append_c (resp, ','); - - if (d->attached && di->attached && di->vt > 0) - migratable = TRUE; - else if (gdm_daemon_config_get_value_string (GDM_KEY_XDMCP_PROXY_RECONNECT) != NULL && - d->type == TYPE_XDMCP_PROXY && di->type == TYPE_XDMCP_PROXY) - migratable = TRUE; - - g_string_append_c (resp, migratable ? '1' : '0'); - } - } - - /* send ack */ - if (resp != NULL) { - send_slave_ack (d, resp->str); - g_string_free (resp, TRUE); - } else { - send_slave_ack (d, NULL); - } - } - } else if (strncmp (msg, GDM_SOP_MIGRATE " ", - strlen (GDM_SOP_MIGRATE " ")) == 0) { - GdmDisplay *d; - long slave_pid; - char *p; - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - if (sscanf (msg, GDM_SOP_MIGRATE " %ld", &slave_pid) != 1) - return; - p = strchr (msg, ' '); - if (p != NULL) - p = strchr (p+1, ' '); - if (p == NULL) - return; - - p++; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - if (d == NULL) - return; - - g_debug ("Got MIGRATE %s", p); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *di = li->data; - if (di->logged_in && strcmp (di->name, p) == 0) { - if (d->attached && di->vt > 0) - gdm_change_vt (di->vt); - else if (d->type == TYPE_XDMCP_PROXY && di->type == TYPE_XDMCP_PROXY) - gdm_xdmcp_migrate (d, di); - } - } - send_slave_ack (d, NULL); - } else if (strncmp (msg, GDM_SOP_COOKIE " ", - strlen (GDM_SOP_COOKIE " ")) == 0) { - GdmDisplay *d; - long slave_pid; - char *p; - - if (sscanf (msg, GDM_SOP_COOKIE " %ld", - &slave_pid) != 1) - return; - p = strchr (msg, ' '); - if (p != NULL) - p = strchr (p+1, ' '); - if (p == NULL) - return; - - p++; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - g_free (d->cookie); - d->cookie = g_strdup (p); - g_debug ("Got COOKIE == <secret>"); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_AUTHFILE " ", - strlen (GDM_SOP_AUTHFILE " ")) == 0) { - GdmDisplay *d; - long slave_pid; - char *p; - - if (sscanf (msg, GDM_SOP_AUTHFILE " %ld", - &slave_pid) != 1) - return; - p = strchr (msg, ' '); - if (p != NULL) - p = strchr (p+1, ' '); - if (p == NULL) - return; - - p++; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - g_free (d->authfile); - d->authfile = g_strdup (p); - g_debug ("Got AUTHFILE == %s", d->authfile); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_FLEXI_ERR " ", - strlen (GDM_SOP_FLEXI_ERR " ")) == 0) { - GdmDisplay *d; - long slave_pid; - int err; - - if (sscanf (msg, GDM_SOP_FLEXI_ERR " %ld %d", - &slave_pid, &err) != 2) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - char *error = NULL; - GdmConnection *conn = d->socket_conn; - d->socket_conn = NULL; - - if (conn != NULL) - gdm_connection_set_close_notify (conn, - NULL, NULL); - - if (err == 3) - error = "ERROR 3 X failed\n"; - else if (err == 4) - error = "ERROR 4 X too busy\n"; - else if (err == 5) - error = "ERROR 5 Nested display can't connect\n"; - else - error = "ERROR 999 Unknown error\n"; - if (conn != NULL) - gdm_connection_write (conn, error); - - g_debug ("Got FLEXI_ERR == %d", err); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_FLEXI_OK " ", - strlen (GDM_SOP_FLEXI_OK " ")) == 0) { - GdmDisplay *d; - long slave_pid; - - if (sscanf (msg, GDM_SOP_FLEXI_OK " %ld", - &slave_pid) != 1) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - GdmConnection *conn = d->socket_conn; - d->socket_conn = NULL; - - if (conn != NULL) { - gdm_connection_set_close_notify (conn, - NULL, NULL); - if ( ! gdm_connection_printf (conn, "OK %s\n", d->name)) - gdm_display_unmanage (d); - } - - g_debug ("Got FLEXI_OK"); - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strcmp (msg, GDM_SOP_SOFT_RESTART) == 0) { - gdm_restart_mode = TRUE; - gdm_safe_restart (); - } else if (strcmp (msg, GDM_SOP_DIRTY_SERVERS) == 0) { - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - send_slave_command (d, GDM_NOTIFY_DIRTY_SERVERS); - } - } else if (strcmp (msg, GDM_SOP_SOFT_RESTART_SERVERS) == 0) { - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - send_slave_command (d, GDM_NOTIFY_SOFT_RESTART_SERVERS); - } - } else if (strncmp (msg, GDM_SOP_SYSLOG " ", - strlen (GDM_SOP_SYSLOG " ")) == 0) { - char *p; - long pid; - int type; - p = strchr (msg, ' '); - if (p == NULL) - return; - p++; - if (sscanf (p, "%ld", &pid) != 1) - return; - p = strchr (p, ' '); - if (p == NULL) - return; - p++; - if (sscanf (p, "%d", &type) != 1) - return; - - p = strchr (p, ' '); - if (p == NULL) - return; - p++; - - /* FIXME: use g_critical or g_debug when required */ - g_warning ("(child %ld) %s", pid, p); - } else if (strcmp (msg, GDM_SOP_START_NEXT_LOCAL) == 0) { - gdm_start_first_unborn_local (3 /* delay */); - } else if (strcmp (msg, GDM_SOP_HUP_ALL_GREETERS) == 0) { - /* probably shouldn't be done too often */ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - if (d->greetpid > 1) - kill (d->greetpid, SIGHUP); - else if (d->chooserpid > 1) - kill (d->chooserpid, SIGHUP); - } - } else if (strcmp (msg, GDM_SOP_GO) == 0) { - GSList *li; - gboolean old_wait = gdm_wait_for_go; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - gdm_wait_for_go = FALSE; - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *d = li->data; - send_slave_command (d, GDM_NOTIFY_GO); - } - /* Init XDMCP if applicable */ - if (old_wait && gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP)) { - if (gdm_xdmcp_init ()) { - g_debug ("Accepting XDMCP connections..."); - gdm_xdmcp_run (); - } - } - } else if (strncmp (msg, GDM_SOP_WRITE_X_SERVERS " ", - strlen (GDM_SOP_WRITE_X_SERVERS " ")) == 0) { - GdmDisplay *d; - long slave_pid; - - if (sscanf (msg, GDM_SOP_WRITE_X_SERVERS " %ld", - &slave_pid) != 1) - return; - - /* Find out who this slave belongs to */ - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - write_x_servers (d); - - /* send ack */ - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_SUSPEND_MACHINE " ", - strlen (GDM_SOP_SUSPEND_MACHINE " ")) == 0) { - GdmDisplay *d; - long slave_pid; - gboolean sysmenu; - - if (sscanf (msg, GDM_SOP_SUSPEND_MACHINE " %ld", &slave_pid) != 1) - return; - d = gdm_display_lookup (slave_pid); - - gdm_info (_("Master suspending...")); - - sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name); - if (sysmenu && gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND) != NULL) { - suspend_machine (); - } - } else if (strncmp (msg, GDM_SOP_CHOSEN_THEME " ", - strlen (GDM_SOP_CHOSEN_THEME " ")) == 0) { - GdmDisplay *d; - long slave_pid; - const char *p; - - if (sscanf (msg, GDM_SOP_CHOSEN_THEME " %ld", &slave_pid) != 1) - return; - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - g_free (d->theme_name); - d->theme_name = NULL; - - /* Syntax errors are partially OK here, if there - was no theme argument we just wanted to clear the - theme field */ - p = strchr (msg, ' '); - if (p != NULL) { - p = strchr (p+1, ' '); - if (p != NULL) { - while (*p == ' ') - p++; - if ( ! ve_string_empty (p)) - d->theme_name = g_strdup (p); - } - } - - send_slave_ack (d, NULL); - } - } else if (strncmp (msg, GDM_SOP_CUSTOM_CMD " ", - strlen (GDM_SOP_CUSTOM_CMD " ")) == 0) { - GdmDisplay *d; - long slave_pid; - long cmd_id; - - if (sscanf (msg, GDM_SOP_CUSTOM_CMD " %ld %ld", &slave_pid, &cmd_id) != 2) - return; - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - custom_cmd (cmd_id); - send_slave_ack (d, NULL); - } - } else if (strcmp (msg, GDM_SOP_FLEXI_XSERVER) == 0) { - handle_flexi_server (NULL, TYPE_FLEXI, gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER), - TRUE /* handled */, - FALSE /* chooser */, - NULL, 0, NULL, NULL, NULL); - } else if (strncmp (msg, "opcode="GDM_SOP_SHOW_ERROR_DIALOG, - strlen ("opcode="GDM_SOP_SHOW_ERROR_DIALOG)) == 0) { - GdmDisplay *d; - GtkMessageType type; - char **list; - char *ptr; - char *error; - char *details_label; - char *details_file; - long slave_pid; - int uid, gid; - - list = g_strsplit (msg, "$$", -1); - - ptr = strchr (list[1], '='); - slave_pid = atol (ptr + 1); - - ptr = strchr (list[2], '='); - type = atoi (ptr + 1); - - ptr = strchr (list[3], '='); - error = g_malloc0 (strlen (ptr)); - strcpy (error, ptr + 1); - - ptr = strchr (list[4], '='); - details_label = g_malloc0 (strlen (ptr)); - strcpy (details_label, ptr + 1); - - ptr = strchr (list[5], '='); - details_file = g_malloc0 (strlen (ptr)); - strcpy (details_file, ptr + 1); - - ptr = strchr (list[6], '='); - uid = atoi (ptr + 1); - - ptr = strchr (list[7], '='); - gid = atoi (ptr + 1); - - d = gdm_display_lookup (slave_pid); - - if (d != NULL) { - if (GDM_AUTHFILE (d)) { - VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0644)); - } - - /* FIXME: this is really bad */ - gdm_errorgui_error_box_full (d, type, error, details_label, details_file, 0, 0); - - if (GDM_AUTHFILE (d)) { - VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0640)); - } - - send_slave_ack_dialog_char (d, GDM_SLAVE_NOTIFY_ERROR_RESPONSE, NULL); - } - - g_free (error); - g_free (details_label); - g_free (details_file); - g_strfreev (list); - } else if (strncmp (msg, "opcode="GDM_SOP_SHOW_YESNO_DIALOG, - strlen ("opcode="GDM_SOP_SHOW_YESNO_DIALOG)) == 0) { - GdmDisplay *d; - char **list; - char *ptr; - char *yesno_msg; - long slave_pid; - gboolean response_yesno; - - list = g_strsplit (msg, "$$", -1); - - ptr = strchr (list [1], '='); - slave_pid = atol (ptr + 1); - - ptr = strchr (list [2], '='); - yesno_msg = g_malloc0 (strlen (ptr)); - strcpy (yesno_msg, ptr + 1); - - d = gdm_display_lookup (slave_pid); - if (d != NULL) { - if (GDM_AUTHFILE (d)) { - VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0644)); - } - - response_yesno = gdm_errorgui_failsafe_yesno (d, yesno_msg); - - send_slave_ack_dialog_int (d, GDM_SLAVE_NOTIFY_YESNO_RESPONSE, response_yesno); - - if (GDM_AUTHFILE (d)) { - VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0640)); - } - } - - g_free (yesno_msg); - g_strfreev (list); - } else if (strncmp (msg, "opcode="GDM_SOP_SHOW_QUESTION_DIALOG, - strlen ("opcode="GDM_SOP_SHOW_QUESTION_DIALOG)) == 0) { - GdmDisplay *d; - char **list; - char *ptr; - char *question_msg; - char *response_question; - long slave_pid; - gboolean echo; - - list = g_strsplit (msg, "$$", -1); - - ptr = strchr (list [1], '='); - slave_pid = atol (ptr + 1); - - ptr = strchr (list [2], '='); - question_msg = g_malloc0 (strlen (ptr)); - strcpy (question_msg, ptr + 1); - - ptr = strchr (list [3], '='); - echo = atoi (ptr + 1); - - d = gdm_display_lookup (slave_pid); - if (d != NULL) { - if (GDM_AUTHFILE (d)) { - VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0644)); - } - - response_question = gdm_errorgui_failsafe_question (d, question_msg, echo); - - send_slave_ack_dialog_char (d, GDM_SLAVE_NOTIFY_QUESTION_RESPONSE, response_question); - - if (GDM_AUTHFILE (d)) { - VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0640)); - } - } - - g_free (question_msg); - g_strfreev (list); - } else if (strncmp (msg, "opcode="GDM_SOP_SHOW_ASKBUTTONS_DIALOG, - strlen ("opcode="GDM_SOP_SHOW_ASKBUTTONS_DIALOG)) == 0) { - GdmDisplay *d; - char *askbuttons_msg; - char **list; - char *ptr; - char *options[4]; - long slave_pid; - int i; - int response_askbuttons; - - list = g_strsplit (msg, "$$", -1); - - ptr = strchr (list [1], '='); - slave_pid = atol (ptr + 1); - - ptr = strchr (list [2], '='); - askbuttons_msg = g_malloc0 (strlen (ptr)); - strcpy (askbuttons_msg, ptr + 1); - - ptr = strchr (list [3], '='); - options[0] = g_malloc0 (strlen (ptr)); - strcpy (options[0], ptr + 1); - - ptr = strchr (list [4], '='); - options[1] = g_malloc0 (strlen (ptr)); - strcpy (options[1], ptr + 1); - - ptr = strchr (list [5], '='); - options[2] = g_malloc0 (strlen (ptr)); - strcpy (options[2], ptr + 1); - - ptr = strchr (list [6], '='); - options[3] = g_malloc0 (strlen (ptr)); - strcpy (options[3], ptr + 1); - - d = gdm_display_lookup (slave_pid); - if (d != NULL) { - if (GDM_AUTHFILE (d)) { - VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0644)); - } - - response_askbuttons = gdm_errorgui_failsafe_ask_buttons (d, askbuttons_msg, options); - - send_slave_ack_dialog_int (d, GDM_SLAVE_NOTIFY_ASKBUTTONS_RESPONSE, response_askbuttons); - if (GDM_AUTHFILE (d)) { - VE_IGNORE_EINTR (chmod (GDM_AUTHFILE (d), 0640)); - } - } - - g_free (askbuttons_msg); - - for (i = 0; i < 3; i ++) - g_free (options[i]); - g_strfreev (list); - } -} - -/* extract second word and the rest of the string */ -static void -extract_dispname_uid_xauthfile_cookie (const char *msg, - char **dispname, - uid_t *uid, - char **xauthfile, - char **cookie) -{ - const char *p; - int i; - char *pp; - - *dispname = NULL; - *xauthfile = NULL; - *cookie = NULL; - - /* Get dispname */ - p = strchr (msg, ' '); - if (p == NULL) - return; - - while (*p == ' ') - p++; - - *dispname = g_strdup (p); - pp = strchr (*dispname, ' '); - if (pp != NULL) - *pp = '\0'; - - /* Get uid */ - p = strchr (p, ' '); - if (p == NULL) { - *dispname = NULL; - g_free (*dispname); - return; - } - while (*p == ' ') - p++; - - if (sscanf (p, "%d", &i) != 1) { - *dispname = NULL; - g_free (*dispname); - return; - } - *uid = i; - - /* Get cookie */ - p = strchr (p, ' '); - if (p == NULL) { - *dispname = NULL; - g_free (*dispname); - return; - } - while (*p == ' ') - p++; - - *cookie = g_strdup (p); - pp = strchr (*cookie, ' '); - if (pp != NULL) - *pp = '\0'; - - /* Get xauthfile */ - p = strchr (p, ' '); - if (p == NULL) { - *cookie = NULL; - g_free (*cookie); - *dispname = NULL; - g_free (*dispname); - return; - } - - while (*p == ' ') - p++; - - *xauthfile = g_strstrip (g_strdup (p)); - -} - -static void -close_conn (gpointer data) -{ - GdmDisplay *disp = data; - - /* We still weren't finished, so we want to whack this display */ - if (disp->socket_conn != NULL) { - disp->socket_conn = NULL; - gdm_display_unmanage (disp); - } -} - -static GdmDisplay * -find_display (const char *name) -{ - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (disp->name != NULL && - strcmp (disp->name, name) == 0) - return disp; - } - return NULL; -} - -static char * -extract_dispnum (const char *addy) -{ - int num; - char *p; - - gdm_assert (addy != NULL); - - p = strchr (addy, ':'); - if (p == NULL) - return NULL; - - /* Whee! handles DECnet even if we don't do that */ - while (*p == ':') - p++; - - if (sscanf (p, "%d", &num) != 1) - return NULL; - - return g_strdup_printf ("%d", num); -} - -static char * -dehex_cookie (const char *cookie, int *len) -{ - /* it should be +1 really, but I'm paranoid */ - char *bcookie = g_new0 (char, (strlen (cookie) / 2) + 2); - int i; - const char *p; - - *len = 0; - - for (i = 0, p = cookie; - *p != '\0' && *(p+1) != '\0'; - i++, p += 2) { - unsigned int num; - if (sscanf (p, "%02x", &num) != 1) { - g_free (bcookie); - return NULL; - } - bcookie[i] = num; - } - *len = i; - return bcookie; -} - -/* This runs as the user who owns the file */ -static gboolean -check_cookie (const gchar *file, const gchar *disp, const gchar *cookie) -{ - Xauth *xa; - gchar *number; - gchar *bcookie; - int cookielen; - gboolean ret = FALSE; - int cnt = 0; - - FILE *fp = fopen (file, "r"); - if (fp == NULL) - return FALSE; - - number = extract_dispnum (disp); - if (number == NULL) - return FALSE; - bcookie = dehex_cookie (cookie, &cookielen); - if (bcookie == NULL) { - g_free (number); - return FALSE; - } - - while ((xa = XauReadAuth (fp)) != NULL) { - if (xa->number_length == strlen (number) && - strncmp (xa->number, number, xa->number_length) == 0 && - xa->name_length == strlen ("MIT-MAGIC-COOKIE-1") && - strncmp (xa->name, "MIT-MAGIC-COOKIE-1", - xa->name_length) == 0 && - xa->data_length == cookielen && - memcmp (xa->data, bcookie, cookielen) == 0) { - XauDisposeAuth (xa); - ret = TRUE; - break; - } - XauDisposeAuth (xa); - - /* just being ultra anal */ - cnt++; - if (cnt > 500) - break; - } - - g_free (number); - g_free (bcookie); - - VE_IGNORE_EINTR (fclose (fp)); - - return ret; -} - -static void -handle_flexi_server (GdmConnection *conn, - int type, - const char *server, - gboolean handled, - gboolean chooser, - const char *xnest_disp, - uid_t xnest_uid, - const char *xnest_auth_file, - const char *xnest_cookie, - const char *username) -{ - GdmDisplay *display; - gchar *bin; - uid_t server_uid = 0; - - g_debug ("flexi server: '%s'", server); - - if (gdm_wait_for_go) { - if (conn != NULL) - gdm_connection_write (conn, - "ERROR 1 No more flexi servers\n"); - return; - } - - if (type == TYPE_FLEXI_XNEST) { - gboolean authorized = TRUE; - struct passwd *pw; - gid_t oldgid = getegid (); - - pw = getpwuid (xnest_uid); - if (pw == NULL) { - if (conn != NULL) - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - /* paranoia */ - NEVER_FAILS_seteuid (0); - - if (setegid (pw->pw_gid) < 0) - NEVER_FAILS_setegid (gdm_daemon_config_get_gdmgid ()); - - if (seteuid (xnest_uid) < 0) { - if (conn != NULL) - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - gdm_assert (xnest_auth_file != NULL); - gdm_assert (xnest_disp != NULL); - gdm_assert (xnest_cookie != NULL); - - if (authorized && - ! gdm_auth_file_check ("handle_flexi_server", xnest_uid, xnest_auth_file, FALSE /* absentok */, NULL)) - authorized = FALSE; - - if (authorized && - ! check_cookie (xnest_auth_file, - xnest_disp, - xnest_cookie)) { - authorized = FALSE; - } - - /* this must always work, thus the asserts */ - NEVER_FAILS_root_set_euid_egid (0, oldgid); - - if (! authorized) { - /* Sorry dude, you're not doing something - * right */ - if (conn != NULL) - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - server_uid = xnest_uid; - } - - if (flexi_servers >= gdm_daemon_config_get_value_int (GDM_KEY_FLEXIBLE_XSERVERS)) { - if (conn != NULL) - gdm_connection_write (conn, - "ERROR 1 No more flexi servers\n"); - return; - } - - bin = ve_first_word (server); - if (ve_string_empty (server) || - g_access (bin, X_OK) != 0) { - g_free (bin); - if (conn != NULL) - gdm_connection_write (conn, - "ERROR 6 No server binary\n"); - return; - } - g_free (bin); - - display = gdm_server_alloc (-1, server); - if G_UNLIKELY (display == NULL) { - if (conn != NULL) - gdm_connection_write (conn, - "ERROR 2 Startup errors\n"); - return; - } - - /* It is kind of ugly that we don't use - the standard resolution for this, but - oh well, this makes other things simpler */ - display->handled = handled; - display->use_chooser = chooser; - - if (type == TYPE_FLEXI_XNEST) { - GdmDisplay *parent; - gchar *disp, *p; - gdm_assert (xnest_disp != NULL); - - disp = g_strdup (xnest_disp); - /* whack the screen info */ - p = strchr (disp, ':'); - if (p != NULL) - p = strchr (p+1, '.'); - if (p != NULL) - *p = '\0'; - /* if it's on one of the attached displays we started, - * it's on the console, else it's not (it could be but - * we aren't sure and we don't want to be fooled) */ - parent = find_display (disp); - if (/* paranoia */xnest_disp[0] == ':' && - parent != NULL && - parent->attached) - display->attached = TRUE; - else - display->attached = FALSE; - g_free (disp); - - display->server_uid = server_uid; - } - - flexi_servers++; - - display->preset_user = g_strdup (username); - display->type = type; - display->socket_conn = conn; - display->parent_disp = g_strdup (xnest_disp); - display->parent_auth_file = g_strdup (xnest_auth_file); - if (conn != NULL) - gdm_connection_set_close_notify (conn, display, close_conn); - gdm_daemon_config_display_list_append (display); - - if ( ! gdm_display_manage (display)) { - gdm_display_unmanage (display); - if (conn != NULL) - gdm_connection_write (conn, - "ERROR 2 Startup errors\n"); - return; - } - /* Now we wait for the server to start up (or not) */ -} - -static void -handle_dynamic_server (GdmConnection *conn, int type, gchar *key) -{ - GdmDisplay *disp; - int disp_num; - gchar *msg; - gchar *full; - gchar *val; - - if (!(gdm_daemon_config_get_value_bool (GDM_KEY_DYNAMIC_XSERVERS))) { - gdm_connection_write (conn, "ERROR 200 Dynamic Displays not allowed\n"); - return; - } - - if ( ! GDM_CONN_AUTH_GLOBAL(conn)) { - gdm_info (_("DYNAMIC request denied: " "Not authenticated")); - gdm_connection_write (conn, "ERROR 100 Not authenticated\n"); - return; - } - - if (key == NULL) { - gdm_connection_write (conn, "ERROR 1 Bad display number <NULL>\n"); - return; - } else if ( !(isdigit (*key))) { - msg = g_strdup_printf ("ERROR 1 Bad display number <%s>\n", key); - gdm_connection_write (conn, msg); - g_free (msg); - return; - } - disp_num = atoi (key); - - if (type == DYNAMIC_ADD) { - /* prime an X server for launching */ - - if (mark_display_exists (disp_num)) { - /* need to skip starting this one again */ - gdm_connection_write (conn, "ERROR 2 Existing display\n"); - return; - } - - full = strchr (key, '='); - if (full == NULL || *(full + 1) == 0) { - gdm_connection_write (conn, "ERROR 3 No server string\n"); - return; - } - - val = full + 1; - disp = gdm_server_alloc (disp_num, val); - - if (disp == NULL) { - gdm_connection_write (conn, "ERROR 4 Display startup failure\n"); - return; - } - - gdm_daemon_config_display_list_insert (disp); - - disp->dispstat = DISPLAY_CONFIG; - disp->removeconf = FALSE; - - if (disp_num > gdm_daemon_config_get_high_display_num ()) - gdm_daemon_config_set_high_display_num (disp_num); - - gdm_connection_write (conn, "OK\n"); - return; - } - - if (type == DYNAMIC_REMOVE) { - GSList *li; - GSList *nli; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - /* shutdown a dynamic X server */ - - for (li = displays; li != NULL; li = nli) { - disp = li->data; - nli = li->next; - if (disp->dispnum == disp_num) { - disp->removeconf = TRUE; - gdm_display_unmanage (disp); - gdm_connection_write (conn, "OK\n"); - return; - } - } - - msg = g_strdup_printf ("ERROR 1 Bad display number <%d>\n", disp_num); - gdm_connection_write (conn, msg); - return; - } - - if (type == DYNAMIC_RELEASE) { - /* cause the newly configured X servers to actually run */ - GSList *li; - GSList *nli; - gboolean found = FALSE; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - for (li = displays; li != NULL; li = nli) { - GdmDisplay *disp = li->data; - nli = li->next; - if ((disp->dispnum == disp_num) && - (disp->dispstat == DISPLAY_CONFIG)) { - disp->dispstat = DISPLAY_UNBORN; - - if ( ! gdm_display_manage (disp)) { - gdm_display_unmanage (disp); - } - found = TRUE; - } - } - - if (found) - gdm_connection_write (conn, "OK\n"); - else { - msg = g_strdup_printf ("ERROR 1 Bad display number <%d>\n", disp_num); - gdm_connection_write (conn, msg); - } - - /* Now we wait for the server to start up (or not) */ - return; - } -} - -static void -sup_handle_auth_local (GdmConnection *conn, - const char *msg, - gpointer data) -{ - GSList *li; - char *cookie; - GSList *displays; - - cookie = g_strdup (&msg[strlen (GDM_SUP_AUTH_LOCAL " ")]); - - displays = gdm_daemon_config_get_display_list (); - - g_strstrip (cookie); - if (strlen (cookie) != 16*2) /* 16 bytes in hex form */ { - /* evil, just whack the connection in this case */ - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - gdm_connection_close (conn); - g_free (cookie); - return; - } - /* check if cookie matches one of the attached displays */ - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (disp->attached && - disp->cookie != NULL && - g_ascii_strcasecmp (disp->cookie, cookie) == 0) { - g_free (cookie); - GDM_CONNECTION_SET_USER_FLAG - (conn, GDM_SUP_FLAG_AUTHENTICATED); - gdm_connection_set_display (conn, disp); - gdm_connection_write (conn, "OK\n"); - return; - } - } - - if (gdm_global_cookie != NULL && - g_ascii_strcasecmp ((gchar *) gdm_global_cookie, cookie) == 0) { - g_free (cookie); - GDM_CONNECTION_SET_USER_FLAG - (conn, GDM_SUP_FLAG_AUTH_GLOBAL); - gdm_connection_write (conn, "OK\n"); - return; - } - - /* Hmmm, perhaps this is better defined behaviour */ - GDM_CONNECTION_UNSET_USER_FLAG - (conn, GDM_SUP_FLAG_AUTHENTICATED); - GDM_CONNECTION_UNSET_USER_FLAG - (conn, GDM_SUP_FLAG_AUTH_GLOBAL); - gdm_connection_set_display (conn, NULL); - gdm_connection_write (conn, "ERROR 100 Not authenticated\n"); - g_free (cookie); -} - -static void -sup_handle_attached_servers (GdmConnection *conn, - const char *msg, - gpointer data) -{ - GString *retMsg; - GSList *li; - const gchar *sep = " "; - char *key; - int msgLen=0; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - if (strncmp (msg, GDM_SUP_ATTACHED_SERVERS, - strlen (GDM_SUP_ATTACHED_SERVERS)) == 0) - msgLen = strlen (GDM_SUP_ATTACHED_SERVERS); - else if (strncmp (msg, GDM_SUP_CONSOLE_SERVERS, - strlen (GDM_SUP_CONSOLE_SERVERS)) == 0) - msgLen = strlen (GDM_SUP_CONSOLE_SERVERS); - - key = g_strdup (&msg[msgLen]); - g_strstrip (key); - - retMsg = g_string_new ("OK"); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - - if ( ! disp->attached) - continue; - if (!(strlen (key)) || (g_pattern_match_simple (key, disp->command))) { - g_string_append_printf (retMsg, "%s%s,%s,", sep, - ve_sure_string (disp->name), - ve_sure_string (disp->login)); - sep = ";"; - if (disp->type == TYPE_FLEXI_XNEST) { - g_string_append (retMsg, ve_sure_string (disp->parent_disp)); - } else { - g_string_append_printf (retMsg, "%d", disp->vt); - } - } - } - - g_string_append (retMsg, "\n"); - gdm_connection_write (conn, retMsg->str); - g_free (key); - g_string_free (retMsg, TRUE); -} - -static void -sup_handle_get_server_details (GdmConnection *conn, - const char *msg, - gpointer data) -{ - - const gchar *server = &msg[strlen (GDM_SUP_GET_SERVER_DETAILS " ")]; - gchar **splitstr = g_strsplit (server, " ", 2); - GdmXserver *svr = gdm_daemon_config_find_xserver ((gchar *)splitstr[0]); - - if (svr != NULL) { - if (g_strcasecmp (splitstr[1], "ID") == 0) - gdm_connection_printf (conn, "OK %s\n", svr->id); - else if (g_strcasecmp (splitstr[1], "NAME") == 0) - gdm_connection_printf (conn, "OK %s\n", svr->name); - else if (g_strcasecmp (splitstr[1], "COMMAND") == 0) - gdm_connection_printf (conn, "OK %s\n", svr->command); - else if (g_strcasecmp (splitstr[1], "PRIORITY") == 0) - gdm_connection_printf (conn, "OK %d\n", svr->priority); - else if (g_strcasecmp (splitstr[1], "FLEXIBLE") == 0 && - svr->flexible) - gdm_connection_printf (conn, "OK true\n"); - else if (g_strcasecmp (splitstr[1], "FLEXIBLE") == 0 && - !svr->flexible) - gdm_connection_printf (conn, "OK false\n"); - else if (g_strcasecmp (splitstr[1], "CHOOSABLE") == 0 && - svr->choosable) - gdm_connection_printf (conn, "OK true\n"); - else if (g_strcasecmp (splitstr[1], "CHOOSABLE") == 0 && - !svr->choosable) - gdm_connection_printf (conn, "OK false\n"); - else if (g_strcasecmp (splitstr[1], "HANDLED") == 0 && - svr->handled) - gdm_connection_printf (conn, "OK true\n"); - else if (g_strcasecmp (splitstr[1], "HANDLED") == 0 && - !svr->handled) - gdm_connection_printf (conn, "OK false\n"); - else if (g_strcasecmp (splitstr[1], "CHOOSER") == 0 && - svr->chooser) - gdm_connection_printf (conn, "OK true\n"); - else if (g_strcasecmp (splitstr[1], "CHOOSER") == 0 && - !svr->chooser) - gdm_connection_printf (conn, "OK false\n"); - else - gdm_connection_printf (conn, "ERROR 2 Key not valid\n"); - - g_strfreev (splitstr); - } else { - gdm_connection_printf (conn, "ERROR 1 Server not found\n"); - } -} - -static void -sup_handle_flexi_xserver (GdmConnection *conn, - const char *msg, - gpointer data) -{ - char *name; - const char *command = NULL; - GdmXserver *svr; - const char *rest; - char *username; - char *end; - gboolean has_user; - - has_user = strncmp (msg, GDM_SUP_FLEXI_XSERVER_USER " ", strlen (GDM_SUP_FLEXI_XSERVER_USER " ")) == 0; - - g_debug ("Handling flexi request has-user:%d", has_user); - - /* Only allow locally authenticated connections */ - if ( ! GDM_CONN_AUTHENTICATED (conn)) { - gdm_info (_("%s request denied: " - "Not authenticated"), "FLEXI_XSERVER"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - if (has_user) { - rest = msg + strlen (GDM_SUP_FLEXI_XSERVER_USER " "); - end = strchr (rest, ' '); - if (end) { - username = g_strndup (rest, end - rest); - rest = end + 1; - } else { - username = g_strdup (rest); - rest = rest + strlen (rest); - } - } else { - rest = msg + strlen (GDM_SUP_FLEXI_XSERVER " "); - username = NULL; - } - - name = g_strdup (rest); - g_strstrip (name); - if (ve_string_empty (name)) { - g_free (name); - name = g_strdup (GDM_STANDARD); - } - - svr = gdm_daemon_config_find_xserver (name); - - if G_UNLIKELY (svr == NULL) { - /* Don't print the name to syslog as it might be - * long and dangerous */ - gdm_error (_("Unknown server type requested; using " - "standard server.")); - command = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER); - } else if G_UNLIKELY ( ! svr->flexible) { - gdm_error (_("Requested server %s not allowed to be " - "used for flexible servers; using " - "standard server."), name); - command = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER); - } else { - command = svr->command; - } - g_free (name); - - handle_flexi_server (conn, - TYPE_FLEXI, - command, - /* It is kind of ugly that we don't use - the standard resolution for this, but - oh well, this makes other things simpler */ - svr->handled, - svr->chooser, - NULL, - 0, - NULL, - NULL, - username); - g_free (username); -} - -static void -sup_handle_flexi_xnest (GdmConnection *conn, - const char *msg, - gpointer data) -{ - char *dispname = NULL; - char *xauthfile = NULL; - char *cookie = NULL; - uid_t uid; - const char *rest; - char *username; - char *end; - gboolean has_user; - - has_user = strncmp (msg, GDM_SUP_FLEXI_XNEST_USER " ", strlen (GDM_SUP_FLEXI_XNEST_USER " ")) == 0; - - g_debug ("Handling flexi xnest request has-user:%d", has_user); - - if (has_user) { - rest = msg + strlen (GDM_SUP_FLEXI_XNEST_USER " "); - end = strchr (rest, ' '); - username = g_strndup (rest, end - rest); - } else { - rest = msg; - username = NULL; - } - - extract_dispname_uid_xauthfile_cookie (rest, - &dispname, - &uid, - &xauthfile, - &cookie); - - if (dispname == NULL) { - /* Something bogus is going on, so just whack the - * connection */ - g_free (xauthfile); - gdm_connection_close (conn); - g_warning ("Unable to get display name from request"); - return; - } - - /* This is probably a pre-2.2.4.2 client */ - if (xauthfile == NULL || cookie == NULL) { - /* evil, just whack the connection in this case */ - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - gdm_connection_close (conn); - g_free (cookie); - return; - } - - handle_flexi_server (conn, - TYPE_FLEXI_XNEST, - gdm_daemon_config_get_value_string (GDM_KEY_XNEST), - TRUE /* handled */, - FALSE /* chooser */, - dispname, - uid, - xauthfile, - cookie, - username); - - g_free (dispname); - g_free (xauthfile); - g_free (username); -} - -static void -sup_handle_get_config (GdmConnection *conn, - const char *msg, - gpointer data) -{ - const char *parms; - char **splitstr; - char *retval; - static gboolean done_prefetch = FALSE; - - retval = NULL; - parms = &msg[strlen (GDM_SUP_GET_CONFIG " ")]; - - splitstr = g_strsplit (parms, " ", 2); - - if (splitstr == NULL || splitstr[0] == NULL) { - goto out; - } - - /* - * It is not meaningful to manage this in a per-display - * fashion since the prefetch program is only run once the - * for the first display that requests the key. So process - * this first and return "Unsupported key" for requests - * after the first request. - */ - if (strcmp (splitstr[0], GDM_KEY_PRE_FETCH_PROGRAM) == 0) { - if (done_prefetch) { - gdm_connection_printf (conn, "OK \n"); - } else { - gdm_connection_printf (conn, "ERROR 50 Unsupported key <%s>\n", splitstr[0]); - done_prefetch = TRUE; - } - goto out; - } - - if (splitstr[0] != NULL) { - gboolean res; - - /* - * Note passing in the display is backwards compatible - * since if it is NULL, it won't try to load the display - * value at all. - */ - - g_debug ("Handling GET_CONFIG: %s for display %s", splitstr[0], splitstr[1]); - - res = gdm_daemon_config_to_string (splitstr[0], splitstr[1], &retval); - - if (res) { - gdm_connection_printf (conn, "OK %s\n", retval); - g_free (retval); - } else { - if (gdm_daemon_config_is_valid_key ((gchar *)splitstr[0])) - gdm_connection_printf (conn, "OK \n"); - else - gdm_connection_printf (conn, - "ERROR 50 Unsupported key <%s>\n", - splitstr[0]); - } - } - out: - g_strfreev (splitstr); -} - -static gboolean -is_action_available (GdmDisplay *disp, gchar *action) -{ - const gchar **allowsyscmd; - const gchar **rbackeys; - gboolean sysmenu; - gboolean ret = FALSE; - int i; - - allowsyscmd = gdm_daemon_config_get_value_string_array (GDM_KEY_ALLOW_LOGOUT_ACTIONS); - rbackeys = gdm_daemon_config_get_value_string_array (GDM_KEY_RBAC_SYSTEM_COMMAND_KEYS); - sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name); - - if (!disp->attached || !sysmenu) { - return FALSE; - } - - for (i = 0; allowsyscmd[i] != NULL; i++) { - if (strcmp (allowsyscmd[i], action) == 0) { - ret = TRUE; - break; - } - } - -#ifdef HAVE_CHKAUTHATTR - if (ret == TRUE && rbackeys) { - for (i = 0; rbackeys[i] != NULL; i++) { - gchar **rbackey = g_strsplit (rbackeys[i], ":", 2); - - if (! ve_string_empty (rbackey[0]) && - ! ve_string_empty (rbackey[1]) && - strcmp (rbackey[0], action) == 0) { - - if (!chkauthattr (rbackey[1], disp->login)) { - g_strfreev (rbackey); - ret = FALSE; - break; - } - - } - g_strfreev (rbackey); - } - } -#endif - - return ret; -} - -static void -sup_handle_query_logout_action (GdmConnection *conn, - const char *msg, - gpointer data) -{ - GdmLogoutAction logout_action; - GdmDisplay *disp; - GString *reply; - const gchar *sep = " "; - int i; - - disp = gdm_connection_get_display (conn); - - /* Only allow locally authenticated connections */ - if (! GDM_CONN_AUTHENTICATED (conn) || disp == NULL) { - gdm_info (_("%s request denied: " - "Not authenticated"), "QUERY_LOGOUT_ACTION"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - reply = g_string_new ("OK"); - - logout_action = disp->logout_action; - if (logout_action == GDM_LOGOUT_ACTION_NONE) - logout_action = safe_logout_action; - - if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_HALT)) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) { - g_string_append_printf (reply, "%s%s", sep, - GDM_SUP_LOGOUT_ACTION_HALT); - if (logout_action == GDM_LOGOUT_ACTION_HALT) - g_string_append (reply, "!"); - sep = ";"; - } - if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT)) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) { - g_string_append_printf (reply, "%s%s", sep, - GDM_SUP_LOGOUT_ACTION_REBOOT); - if (logout_action == GDM_LOGOUT_ACTION_REBOOT) - g_string_append (reply, "!"); - sep = ";"; - } - if (! ve_string_empty (gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND)) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) { - g_string_append_printf (reply, "%s%s", sep, - GDM_SUP_LOGOUT_ACTION_SUSPEND); - if (logout_action == GDM_LOGOUT_ACTION_SUSPEND) - g_string_append (reply, "!"); - sep = ";"; - } - - if (is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) { - for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) { - gchar *key_string = NULL; - key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, i); - - if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) { - - g_free (key_string); - key_string = g_strdup_printf("%s%d=", - GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i); - - if (gdm_daemon_config_get_value_bool (key_string)) { - g_string_append_printf (reply, "%s%s%d", sep, - GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE, i); - if (logout_action == (GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + i)) - g_string_append (reply, "!"); - sep = ";"; - } - } - g_free(key_string); - } - } - - g_string_append (reply, "\n"); - gdm_connection_write (conn, reply->str); - g_string_free (reply, TRUE); -} - -static void -sup_handle_query_custom_cmd_labels (GdmConnection *conn, - const char *msg, - gpointer data) -{ - - GdmDisplay *disp; - GString *reply; - const gchar *sep = " "; - gboolean sysmenu; - int i; - - disp = gdm_connection_get_display (conn); - sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name); - - /* Only allow locally authenticated connections */ - if ( ! GDM_CONN_AUTHENTICATED (conn) || - disp == NULL) { - gdm_info (_("%s request denied: " - "Not authenticated"), "QUERY_CUSTOM_CMD_LABELS"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - reply = g_string_new ("OK"); - - for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) { - gchar *key_string = NULL; - key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, i); - if (sysmenu && disp->attached && - ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) { - g_free (key_string); - key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i); - if (gdm_daemon_config_get_value_bool (key_string)) { - g_free (key_string); - key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE, i); - g_string_append_printf (reply, "%s%s", sep, gdm_daemon_config_get_value_string (key_string)); - sep = ";"; - } - } - g_free(key_string); - } - - g_string_append (reply, "\n"); - gdm_connection_write (conn, reply->str); - g_string_free (reply, TRUE); -} - -static void -sup_handle_all_servers (GdmConnection *conn, - const char *msg, - gpointer data) -{ - GString *reply; - GSList *li; - const gchar *sep = " "; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - reply = g_string_new ("OK"); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - g_string_append_printf (reply, "%s%s,%s", sep, - ve_sure_string (disp->name), - ve_sure_string (disp->login)); - sep = ";"; - } - g_string_append (reply, "\n"); - gdm_connection_write (conn, reply->str); - g_string_free (reply, TRUE); -} - -static void -sup_handle_get_server_list (GdmConnection *conn, - const char *msg, - gpointer data) -{ - gchar *retval = gdm_daemon_config_get_xservers (); - - if (retval != NULL) { - gdm_connection_printf (conn, "OK %s\n", retval); - g_free (retval); - } else { - gdm_connection_printf (conn, "ERROR 1 No servers found\n"); - } -} - -static void -sup_handle_get_custom_config_file (GdmConnection *conn, - const char *msg, - gpointer data) -{ - gchar *ret; - - ret = gdm_daemon_config_get_custom_config_file (); - if (ret) - gdm_connection_printf (conn, "OK %s\n", ret); - else - gdm_connection_write (conn, - "ERROR 1 File not found\n"); -} - -static void -sup_handle_greeterpids (GdmConnection *conn, - const char *msg, - gpointer data) -{ - GString *reply; - GSList *li; - const gchar *sep = " "; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - reply = g_string_new ("OK"); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (disp->greetpid > 0) { - g_string_append_printf (reply, "%s%ld", - sep, (long)disp->greetpid); - sep = ";"; - } - } - g_string_append (reply, "\n"); - gdm_connection_write (conn, reply->str); - g_string_free (reply, TRUE); -} - -static void -sup_handle_query_custom_cmd_no_restart_status (GdmConnection *conn, - const char *msg, - gpointer data) -{ - - GdmDisplay *disp; - GString *reply; - gboolean sysmenu; - unsigned long no_restart_status_flag = 0; /* we can store up-to 32 commands this way */ - int i; - - disp = gdm_connection_get_display (conn); - sysmenu = gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, disp->name); - - /* Only allow locally authenticated connections */ - if ( ! GDM_CONN_AUTHENTICATED (conn) || - disp == NULL) { - gdm_info (_("%s request denied: " - "Not authenticated"), "QUERY_CUSTOM_CMD_NO_RESTART_STATUS"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - reply = g_string_new ("OK "); - - for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) { - gchar *key_string = NULL; - key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, i); - if (sysmenu && disp->attached && - ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) { - g_free (key_string); - key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i); - if (gdm_daemon_config_get_value_bool (key_string)) { - g_free (key_string); - key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, i); - if(gdm_daemon_config_get_value_bool (key_string)) - no_restart_status_flag |= (1 << i); - } - } - g_free(key_string); - } - - g_string_append_printf (reply, "%ld\n", no_restart_status_flag); - gdm_connection_write (conn, reply->str); - g_string_free (reply, TRUE); -} - -static void -sup_handle_set_logout_action (GdmConnection *conn, - const char *msg, - gpointer data) - -{ - GdmDisplay *disp; - const gchar *action; - gboolean was_ok = FALSE; - - action = &msg[strlen (GDM_SUP_SET_LOGOUT_ACTION " ")]; - disp = gdm_connection_get_display (conn); - - /* Only allow locally authenticated connections */ - if ( ! GDM_CONN_AUTHENTICATED (conn) || - disp == NULL || - ! disp->logged_in) { - gdm_info (_("%s request denied: " - "Not authenticated"), "SET_LOGOUT_ACTION"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - if (strcmp (action, GDM_SUP_LOGOUT_ACTION_NONE) == 0) { - disp->logout_action = GDM_LOGOUT_ACTION_NONE; - was_ok = TRUE; - } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0 && - ! gdm_daemon_config_get_value_string_array (GDM_KEY_HALT) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) { - disp->logout_action = GDM_LOGOUT_ACTION_HALT; - was_ok = TRUE; - } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0 && - ! gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) { - disp->logout_action = GDM_LOGOUT_ACTION_REBOOT; - was_ok = TRUE; - } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0 && - ! gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) { - disp->logout_action = GDM_LOGOUT_ACTION_SUSPEND; - was_ok = TRUE; - } - else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE, - strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0 && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) { - - int cmd_index; - if (sscanf (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "%d", &cmd_index) == 1) { - gchar *key_string = NULL; - key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index); - if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) { - disp->logout_action = - GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index; - was_ok = TRUE; - } - g_free(key_string); - } - } - - if (was_ok) { - gdm_connection_write (conn, "OK\n"); - gdm_try_logout_action (disp); - } else { - gdm_connection_write (conn, "ERROR 7 Unknown logout action, or not available\n"); - } -} - -static void -sup_handle_set_safe_logout_action (GdmConnection *conn, - const char *msg, - gpointer data) - -{ - GdmDisplay *disp; - const gchar *action; - gboolean was_ok = FALSE; - - action = &msg[strlen (GDM_SUP_SET_SAFE_LOGOUT_ACTION " ")]; - disp = gdm_connection_get_display (conn); - - /* Only allow locally authenticated connections */ - if ( ! GDM_CONN_AUTHENTICATED (conn) || - disp == NULL || - ! disp->logged_in) { - gdm_info (_("%s request denied: " - "Not authenticated"), "SET_LOGOUT_ACTION"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - if (strcmp (action, GDM_SUP_LOGOUT_ACTION_NONE) == 0) { - safe_logout_action = GDM_LOGOUT_ACTION_NONE; - was_ok = TRUE; - } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0 && - ! gdm_daemon_config_get_value_string_array (GDM_KEY_HALT) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_HALT)) { - safe_logout_action = GDM_LOGOUT_ACTION_HALT; - was_ok = TRUE; - } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0 && - ! gdm_daemon_config_get_value_string_array (GDM_KEY_REBOOT) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_REBOOT)) { - safe_logout_action = GDM_LOGOUT_ACTION_REBOOT; - was_ok = TRUE; - } else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0 && - ! gdm_daemon_config_get_value_string_array (GDM_KEY_SUSPEND) && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_SUSPEND)) { - safe_logout_action = GDM_LOGOUT_ACTION_SUSPEND; - was_ok = TRUE; - } - else if (strncmp (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE, - strlen (GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) == 0 && - is_action_available (disp, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE)) { - - int cmd_index; - if (sscanf (action, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE "%d", &cmd_index) == 1) { - - gchar *key_string = NULL; - key_string = g_strdup_printf ("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index); - - if (! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) { - safe_logout_action = - GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index; - was_ok = TRUE; - } - g_free(key_string); - } - } - - if (was_ok) { - gdm_connection_write (conn, "OK\n"); - gdm_try_logout_action (disp); - } else { - gdm_connection_write (conn, "ERROR 7 Unknown logout action, or not available\n"); - } -} - -static void -sup_handle_query_vt (GdmConnection *conn, - const char *msg, - gpointer data) - -{ - - /* Only allow locally authenticated connections */ - if ( ! GDM_CONN_AUTHENTICATED (conn)) { - gdm_info (_("%s request denied: " - "Not authenticated"), "QUERY_VT"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - -#if defined (__linux__) || defined (__FreeBSD__) || defined (__DragonFly__) - gdm_connection_printf (conn, "OK %d\n", gdm_get_cur_vt ()); -#else - gdm_connection_write (conn, "ERROR 8 Virtual terminals not supported\n"); -#endif -} - -static void -sup_handle_set_vt (GdmConnection *conn, - const char *msg, - gpointer data) -{ - int vt; - GSList *li; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - if (sscanf (msg, GDM_SUP_SET_VT " %d", &vt) != 1 || - vt < 0) { - gdm_connection_write (conn, - "ERROR 9 Invalid virtual terminal number\n"); - return; - } - - /* Only allow locally authenticated connections */ - if ( ! GDM_CONN_AUTHENTICATED (conn)) { - gdm_info (_("%s request denied: " - "Not authenticated"), "QUERY_VT"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - -#if defined (__linux__) || defined (__FreeBSD__) || defined (__DragonFly__) - gdm_change_vt (vt); - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *disp = li->data; - if (disp->vt == vt) { - send_slave_command (disp, GDM_NOTIFY_TWIDDLE_POINTER); - break; - } - } - gdm_connection_write (conn, "OK\n"); -#else - gdm_connection_write (conn, "ERROR 8 Virtual terminals not supported\n"); -#endif -} - -static void -gdm_handle_user_message (GdmConnection *conn, - const char *msg, - gpointer data) -{ - - g_debug ("Handling user message: '%s'", msg); - - if (gdm_connection_get_message_count (conn) > GDM_SUP_MAX_MESSAGES) { - g_debug ("Closing connection, %d messages reached", GDM_SUP_MAX_MESSAGES); - gdm_connection_write (conn, "ERROR 200 Too many messages\n"); - gdm_connection_close (conn); - return; - } - - if (strncmp (msg, GDM_SUP_AUTH_LOCAL " ", - strlen (GDM_SUP_AUTH_LOCAL " ")) == 0) { - - sup_handle_auth_local (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_FLEXI_XSERVER) == 0) { - /* Only allow locally authenticated connections */ - if ( ! GDM_CONN_AUTHENTICATED (conn)) { - gdm_info (_("%s request denied: " - "Not authenticated"), "FLEXI_XSERVER"); - gdm_connection_write (conn, - "ERROR 100 Not authenticated\n"); - return; - } - - handle_flexi_server (conn, - TYPE_FLEXI, - gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER), - TRUE /* handled */, - FALSE /* chooser */, - NULL, - 0, - NULL, - NULL, - NULL); - } else if ((strncmp (msg, GDM_SUP_FLEXI_XSERVER_USER " ", - strlen (GDM_SUP_FLEXI_XSERVER_USER " ")) == 0) || - (strncmp (msg, GDM_SUP_FLEXI_XSERVER " ", - strlen (GDM_SUP_FLEXI_XSERVER " ")) == 0)) { - - sup_handle_flexi_xserver (conn, msg, data); - - } else if ((strncmp (msg, GDM_SUP_FLEXI_XNEST_USER " ", - strlen (GDM_SUP_FLEXI_XNEST_USER " ")) == 0) || - (strncmp (msg, GDM_SUP_FLEXI_XNEST " ", - strlen (GDM_SUP_FLEXI_XNEST " ")) == 0)) { - - sup_handle_flexi_xnest (conn, msg, data); - - } else if ((strncmp (msg, GDM_SUP_ATTACHED_SERVERS, - strlen (GDM_SUP_ATTACHED_SERVERS)) == 0) || - (strncmp (msg, GDM_SUP_CONSOLE_SERVERS, - strlen (GDM_SUP_CONSOLE_SERVERS)) == 0)) { - - sup_handle_attached_servers (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_ALL_SERVERS) == 0) { - - sup_handle_all_servers (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_GET_SERVER_LIST) == 0) { - - sup_handle_get_server_list (conn, msg, data); - - } else if (strncmp (msg, GDM_SUP_GET_SERVER_DETAILS " ", - strlen (GDM_SUP_GET_SERVER_DETAILS " ")) == 0) { - - sup_handle_get_server_details (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_GREETERPIDS) == 0) { - - sup_handle_greeterpids (conn, msg, data); - - } else if (strncmp (msg, GDM_SUP_UPDATE_CONFIG " ", - strlen (GDM_SUP_UPDATE_CONFIG " ")) == 0) { - const char *key; - - key = &msg[strlen (GDM_SUP_UPDATE_CONFIG " ")]; - - if (! gdm_daemon_config_update_key ((gchar *)key)) - gdm_connection_printf (conn, "ERROR 50 Unsupported key <%s>\n", key); - else - gdm_connection_write (conn, "OK\n"); - } else if (strncmp (msg, GDM_SUP_GET_CONFIG " ", - strlen (GDM_SUP_GET_CONFIG " ")) == 0) { - - sup_handle_get_config (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_GET_CONFIG_FILE) == 0) { - /* - * Value is only non-null if passed in on command line. - * Otherwise print compiled-in default file location. - */ - if (config_file == NULL) { - gdm_connection_printf (conn, "OK %s\n", - GDM_DEFAULTS_CONF); - } else { - gdm_connection_printf (conn, "OK %s\n", config_file); - } - } else if (strcmp (msg, GDM_SUP_GET_CUSTOM_CONFIG_FILE) == 0) { - - sup_handle_get_custom_config_file (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_QUERY_LOGOUT_ACTION) == 0) { - - sup_handle_query_logout_action (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_QUERY_CUSTOM_CMD_LABELS) == 0) { - - sup_handle_query_custom_cmd_labels (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_QUERY_CUSTOM_CMD_NO_RESTART_STATUS) == 0) { - - sup_handle_query_custom_cmd_no_restart_status (conn, msg, data); - - } else if (strncmp (msg, GDM_SUP_SET_LOGOUT_ACTION " ", - strlen (GDM_SUP_SET_LOGOUT_ACTION " ")) == 0) { - - sup_handle_set_logout_action (conn, msg, data); - - } else if (strncmp (msg, GDM_SUP_SET_SAFE_LOGOUT_ACTION " ", - strlen (GDM_SUP_SET_SAFE_LOGOUT_ACTION " ")) == 0) { - - sup_handle_set_safe_logout_action (conn, msg, data); - - } else if (strcmp (msg, GDM_SUP_QUERY_VT) == 0) { - - sup_handle_query_vt (conn, msg, data); - - } else if (strncmp (msg, GDM_SUP_SET_VT " ", - strlen (GDM_SUP_SET_VT " ")) == 0) { - - sup_handle_set_vt (conn, msg, data); - - } else if (strncmp (msg, GDM_SUP_ADD_DYNAMIC_DISPLAY " ", - strlen (GDM_SUP_ADD_DYNAMIC_DISPLAY " ")) == 0) { - gchar *key; - - key = g_strdup (&msg[strlen (GDM_SUP_ADD_DYNAMIC_DISPLAY " ")]); - g_strstrip (key); - handle_dynamic_server (conn, DYNAMIC_ADD, key); - g_free (key); - - } else if (strncmp (msg, GDM_SUP_REMOVE_DYNAMIC_DISPLAY " ", - strlen (GDM_SUP_REMOVE_DYNAMIC_DISPLAY " ")) == 0) { - gchar *key; - - key = g_strdup (&msg[strlen (GDM_SUP_REMOVE_DYNAMIC_DISPLAY " ")]); - g_strstrip (key); - handle_dynamic_server (conn, DYNAMIC_REMOVE, key); - g_free (key); - - } else if (strncmp (msg, GDM_SUP_RELEASE_DYNAMIC_DISPLAYS " ", - strlen (GDM_SUP_RELEASE_DYNAMIC_DISPLAYS " ")) == 0) { - - gchar *key; - - key = g_strdup (&msg[strlen (GDM_SUP_RELEASE_DYNAMIC_DISPLAYS " ")]); - g_strstrip (key); - handle_dynamic_server (conn, DYNAMIC_RELEASE, key); - g_free (key); - - } else if (strcmp (msg, GDM_SUP_VERSION) == 0) { - gdm_connection_write (conn, "GDM " VERSION "\n"); - } else if (strcmp (msg, GDM_SUP_SERVER_BUSY) == 0) { - if (gdm_connection_is_server_busy (unixconn)) - gdm_connection_write (conn, "OK true\n"); - else - gdm_connection_write (conn, "OK false\n"); - } else if (strcmp (msg, GDM_SUP_CLOSE) == 0) { - gdm_connection_close (conn); - } else { - gdm_connection_write (conn, "ERROR 0 Not implemented\n"); - gdm_connection_close (conn); - } -} diff --git a/daemon/gdm.h b/daemon/gdm.h deleted file mode 100644 index e13e4185..00000000 --- a/daemon/gdm.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_H -#define GDM_H - -#define GDM_MAX_PASS 256 /* Define a value for password length. Glibc - * leaves MAX_PASS undefined. */ - -/* DO NOTE USE 1, that's used as error if x connection fails usually */ -/* Note that there is no reason why these were a power of two, and note - * that they have to fit in 256 */ -/* These are the exit codes */ -#define DISPLAY_REMANAGE 2 /* Restart display */ -#define DISPLAY_ABORT 4 /* Houston, we have a problem */ -#define DISPLAY_REBOOT 8 /* Rebewt */ -#define DISPLAY_HALT 16 /* Halt */ -#define DISPLAY_SUSPEND 17 /* Suspend (don't use, use the interrupt) */ -#define DISPLAY_CHOSEN 20 /* successful chooser session, - restart display */ -#define DISPLAY_RUN_CHOOSER 30 /* Run chooser */ -#define DISPLAY_XFAILED 64 /* X failed */ -#define DISPLAY_GREETERFAILED 65 /* greeter failed (crashed) */ -#define DISPLAY_RESTARTGREETER 127 /* Restart greeter */ -#define DISPLAY_RESTARTGDM 128 /* Restart GDM */ - -enum { - DISPLAY_UNBORN /* Not yet started */, - DISPLAY_ALIVE /* Yay! we're alive (non-XDMCP) */, - XDMCP_PENDING /* Pending XDMCP display */, - XDMCP_MANAGED /* Managed XDMCP display */, - DISPLAY_DEAD /* Left for dead */, - DISPLAY_CONFIG /* in process of being configured */ -}; - -/* The dreaded miscellaneous category */ -#define PIPE_SIZE 4096 - -/* - * For backwards compatibility, do not set values for DEFAULT_WELCOME or - * DEFAULT_REMOTEWELCOME. This will cause these values to always be - * read from the config file, and will cause them to return FALSE if - * no value is set in the config file. We want the value "FALSE" if - * the values don't exist in the config file. The daemon will compare - * the Welcome/RemoveWelcome value with the default string and - * automatically translate the text if the string is the same as the - * default string. We set the default values of GDM_KEY_WELCOME and - * GDM_KEY_REMOTEWELCOME so that the default value is returned when - * you run GET_CONFIG on these keys. - */ -#define GDM_DEFAULT_WELCOME_MSG "Welcome" -#define GDM_DEFAULT_REMOTE_WELCOME_MSG "Welcome to %n" - -#define GDM_SESSION_FAILSAFE_GNOME "GDM_Failsafe.GNOME" -#define GDM_SESSION_FAILSAFE_XTERM "GDM_Failsafe.XTERM" - -/* FIXME: will support these builtin types later */ -#define GDM_SESSION_DEFAULT "default" -#define GDM_SESSION_CUSTOM "custom" -#define GDM_SESSION_FAILSAFE "failsafe" - -#define GDM_STANDARD "Standard" - -#define GDM_RESPONSE_CANCEL "GDM_RESPONSE_CANCEL" - -#define GDM_CUSTOM_COMMAND_MAX 10 /* maximum number of supported custom commands */ - -#ifdef sun -#define SDTLOGIN_DIR "/var/dt/sdtlogin" -#endif - -/* If id == NULL, then get the first X server */ -void gdm_final_cleanup (void); - -#endif /* GDM_H */ - -/* EOF */ diff --git a/daemon/gdm.in b/daemon/gdm.in deleted file mode 100644 index adf9cf03..00000000 --- a/daemon/gdm.in +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# -# A script so that -# 1) we read the standard system env vars -# 2) syadmins/integrators can add their own private options etc... - -test -f /etc/profile && . /etc/profile - -# Try to set LC_MESSAGES to LANG if neither LC_MESSAGES or LC_ALL is set. -# This ensures that gdm can display in a system's default language if only -# LANG is set. - -# Make sure LANG is set -# -if [ -z "$LANG" ] -then - if [ -f /etc/sysconfig/language ] - then - LANG=`. /etc/sysconfig/language; echo $RC_LANG` - export LANG - fi -fi - -if [ -z "$LC_MESSAGES" ] -then - if [ -z "$LC_ALL" ] - then - LC_MESSAGES=$LANG - export LC_MESSAGES - fi -fi - -exec @sbindir@/gdm-binary "$@" - diff --git a/daemon/gdmconsolekit.c b/daemon/gdmconsolekit.c deleted file mode 100644 index ce366ae7..00000000 --- a/daemon/gdmconsolekit.c +++ /dev/null @@ -1,538 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2006-2007 William Jon McCann <mccann@jhu.edu> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include "config.h" - -#include <stdlib.h> -#include <string.h> -#include <pwd.h> - -#include <glib.h> - -#define DBUS_API_SUBJECT_TO_CHANGE -#include <dbus/dbus.h> -#include <dbus/dbus-glib-lowlevel.h> - -#include "gdm-log.h" /* for gdm_debug */ -#include "gdmconsolekit.h" - - -#define CK_NAME "org.freedesktop.ConsoleKit" -#define CK_PATH "/org/freedesktop/ConsoleKit" -#define CK_INTERFACE "org.freedesktop.ConsoleKit" -#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager" -#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager" -#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" - -static DBusConnection *private_connection = NULL; - -static void -add_param_int (DBusMessageIter *iter_struct, - const char *key, - int value) -{ - DBusMessageIter iter_struct_entry; - DBusMessageIter iter_var; - - dbus_message_iter_open_container (iter_struct, - DBUS_TYPE_STRUCT, - NULL, - &iter_struct_entry); - - dbus_message_iter_append_basic (&iter_struct_entry, - DBUS_TYPE_STRING, - &key); - - dbus_message_iter_open_container (&iter_struct_entry, - DBUS_TYPE_VARIANT, - DBUS_TYPE_INT32_AS_STRING, - &iter_var); - - dbus_message_iter_append_basic (&iter_var, - DBUS_TYPE_INT32, - &value); - - dbus_message_iter_close_container (&iter_struct_entry, - &iter_var); - - dbus_message_iter_close_container (iter_struct, &iter_struct_entry); -} - -static void -add_param_boolean (DBusMessageIter *iter_struct, - const char *key, - gboolean value) -{ - DBusMessageIter iter_struct_entry; - DBusMessageIter iter_var; - - dbus_message_iter_open_container (iter_struct, - DBUS_TYPE_STRUCT, - NULL, - &iter_struct_entry); - - dbus_message_iter_append_basic (&iter_struct_entry, - DBUS_TYPE_STRING, - &key); - - dbus_message_iter_open_container (&iter_struct_entry, - DBUS_TYPE_VARIANT, - DBUS_TYPE_BOOLEAN_AS_STRING, - &iter_var); - - dbus_message_iter_append_basic (&iter_var, - DBUS_TYPE_BOOLEAN, - &value); - - dbus_message_iter_close_container (&iter_struct_entry, - &iter_var); - - dbus_message_iter_close_container (iter_struct, &iter_struct_entry); -} - -static void -add_param_string (DBusMessageIter *iter_struct, - const char *key, - const char *value) -{ - DBusMessageIter iter_struct_entry; - DBusMessageIter iter_var; - - dbus_message_iter_open_container (iter_struct, - DBUS_TYPE_STRUCT, - NULL, - &iter_struct_entry); - - dbus_message_iter_append_basic (&iter_struct_entry, - DBUS_TYPE_STRING, - &key); - - dbus_message_iter_open_container (&iter_struct_entry, - DBUS_TYPE_VARIANT, - DBUS_TYPE_STRING_AS_STRING, - &iter_var); - - dbus_message_iter_append_basic (&iter_var, - DBUS_TYPE_STRING, - &value); - - dbus_message_iter_close_container (&iter_struct_entry, - &iter_var); - - dbus_message_iter_close_container (iter_struct, &iter_struct_entry); -} - -static gboolean -session_get_x11_display (DBusConnection *connection, - const char *ssid, - char **str) -{ - DBusError error; - DBusMessage *message; - DBusMessage *reply; - DBusMessageIter iter; - const char *value; - - if (str != NULL) { - *str = NULL; - } - - message = dbus_message_new_method_call (CK_NAME, - ssid, - CK_SESSION_INTERFACE, - "GetX11Display"); - if (message == NULL) { - gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); - return FALSE; - } - - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (connection, - message, - -1, &error); - if (dbus_error_is_set (&error)) { - gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); - reply = NULL; - } - - dbus_connection_flush (connection); - dbus_message_unref (message); - - if (reply == NULL) { - return FALSE; - } - - dbus_message_iter_init (reply, &iter); - dbus_message_iter_get_basic (&iter, &value); - if (str != NULL) { - *str = g_strdup (value); - } - dbus_message_unref (reply); - - return TRUE; -} - -static gboolean -session_unlock (DBusConnection *connection, - const char *ssid) -{ - DBusError error; - DBusMessage *message; - DBusMessage *reply; - - gdm_debug ("ConsoleKit: Unlocking session %s", ssid); - message = dbus_message_new_method_call (CK_NAME, - ssid, - CK_SESSION_INTERFACE, - "Unlock"); - if (message == NULL) { - gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); - return FALSE; - } - - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (connection, - message, - -1, &error); - dbus_message_unref (message); - dbus_message_unref (reply); - dbus_connection_flush (connection); - - if (dbus_error_is_set (&error)) { - gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); - return FALSE; - } - - return TRUE; -} - -/* from libhal */ -static char ** -get_path_array_from_iter (DBusMessageIter *iter, - int *num_elements) -{ - int count; - char **buffer; - - count = 0; - buffer = (char **)malloc (sizeof (char *) * 8); - - if (buffer == NULL) - goto oom; - - buffer[0] = NULL; - while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_OBJECT_PATH) { - const char *value; - char *str; - - if ((count % 8) == 0 && count != 0) { - buffer = realloc (buffer, sizeof (char *) * (count + 8)); - if (buffer == NULL) - goto oom; - } - - dbus_message_iter_get_basic (iter, &value); - str = strdup (value); - if (str == NULL) - goto oom; - - buffer[count] = str; - - dbus_message_iter_next (iter); - count++; - } - - if ((count % 8) == 0) { - buffer = realloc (buffer, sizeof (char *) * (count + 1)); - if (buffer == NULL) - goto oom; - } - - buffer[count] = NULL; - if (num_elements != NULL) - *num_elements = count; - return buffer; - -oom: - g_warning ("%s %d : error allocating memory\n", __FILE__, __LINE__); - return NULL; - -} - -static char ** -get_sessions_for_user (DBusConnection *connection, - const char *user, - const char *x11_display) -{ - DBusError error; - DBusMessage *message; - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter iter_reply; - DBusMessageIter iter_array; - struct passwd *pwent; - char **sessions; - - sessions = NULL; - message = NULL; - reply = NULL; - - pwent = getpwnam (user); - - dbus_error_init (&error); - message = dbus_message_new_method_call (CK_NAME, - CK_MANAGER_PATH, - CK_MANAGER_INTERFACE, - "GetSessionsForUser"); - if (message == NULL) { - gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); - goto out; - } - - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_append_basic (&iter, - DBUS_TYPE_UINT32, - &pwent->pw_uid); - - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block (connection, - message, - -1, &error); - dbus_connection_flush (connection); - - if (dbus_error_is_set (&error)) { - gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); - goto out; - } - - if (reply == NULL) { - gdm_debug ("ConsoleKit: No reply for GetSessionsForUser"); - goto out; - } - - dbus_message_iter_init (reply, &iter_reply); - if (dbus_message_iter_get_arg_type (&iter_reply) != DBUS_TYPE_ARRAY) { - gdm_debug ("ConsoleKit: Wrong reply for GetSessionsForUser - expecting an array."); - goto out; - } - - dbus_message_iter_recurse (&iter_reply, &iter_array); - sessions = get_path_array_from_iter (&iter_array, NULL); - - out: - if (message != NULL) { - dbus_message_unref (message); - } - if (reply != NULL) { - dbus_message_unref (reply); - } - - return sessions; -} - -void -unlock_ck_session (const char *user, - const char *x11_display) -{ - DBusError error; - DBusConnection *connection; - char **sessions; - int i; - - gdm_debug ("ConsoleKit: Unlocking session for %s on %s", user, x11_display); - - dbus_error_init (&error); - connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if (connection == NULL) { - gdm_debug ("ConsoleKit: Failed to connect to the D-Bus daemon: %s", error.message); - dbus_error_free (&error); - return; - } - - sessions = get_sessions_for_user (connection, user, x11_display); - if (sessions == NULL || sessions[0] == NULL) { - gdm_debug ("ConsoleKit: no sessions found"); - return; - } - - for (i = 0; sessions[i] != NULL; i++) { - char *ssid; - char *xdisplay; - - ssid = sessions[i]; - session_get_x11_display (connection, ssid, &xdisplay); - gdm_debug ("ConsoleKit: session %s has DISPLAY %s", ssid, xdisplay); - - if (xdisplay != NULL - && x11_display != NULL - && strcmp (xdisplay, x11_display) == 0) { - gboolean res; - - res = session_unlock (connection, ssid); - if (! res) { - gdm_error ("ConsoleKit: Unable to unlock %s", ssid); - } - } - - g_free (xdisplay); - } - - g_strfreev (sessions); -} - -char * -open_ck_session (struct passwd *pwent, - GdmDisplay *d, - const char *session) -{ - DBusConnection *connection; - DBusError error; - DBusMessage *message; - DBusMessage *reply; - DBusMessageIter iter; - DBusMessageIter iter_struct; - char *cookie; - - cookie = NULL; - - gdm_debug ("ConsoleKit: Opening session for %s", pwent->pw_name); - - dbus_error_init (&error); - connection = dbus_bus_get_private (DBUS_BUS_SYSTEM, &error); - private_connection = connection; - - if (connection == NULL) { - gdm_debug ("ConsoleKit: Failed to connect to the D-Bus daemon: %s", error.message); - dbus_error_free (&error); - return NULL; - } - - dbus_connection_set_exit_on_disconnect (connection, FALSE); - dbus_connection_setup_with_g_main (connection, NULL); - - dbus_error_init (&error); - message = dbus_message_new_method_call (CK_NAME, - CK_MANAGER_PATH, - CK_MANAGER_INTERFACE, - "OpenSessionWithParameters"); - if (message == NULL) { - gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); - return NULL; - } - - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_open_container (&iter, - DBUS_TYPE_ARRAY, - DBUS_STRUCT_BEGIN_CHAR_AS_STRING - DBUS_TYPE_STRING_AS_STRING - DBUS_TYPE_VARIANT_AS_STRING - DBUS_STRUCT_END_CHAR_AS_STRING, - &iter_struct); - - add_param_int (&iter_struct, "user", pwent->pw_uid); - add_param_string (&iter_struct, "x11-display", d->name); - add_param_boolean (&iter_struct, "is-local", d->attached); - if (! d->attached) { - add_param_string (&iter_struct, "remote-host-name", d->hostname); - } - - if (d->vt > 0) { - char *device; - - /* FIXME: how does xorg construct this */ - device = g_strdup_printf ("/dev/tty%d", d->vt); - add_param_string (&iter_struct, "x11-display-device", device); - g_free (device); - } - - dbus_message_iter_close_container (&iter, &iter_struct); - - reply = dbus_connection_send_with_reply_and_block (connection, - message, - -1, &error); - if (dbus_error_is_set (&error)) { - gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); - reply = NULL; - } - - dbus_connection_flush (connection); - - dbus_message_unref (message); - dbus_error_free (&error); - - if (reply != NULL) { - const char *value; - - dbus_message_iter_init (reply, &iter); - dbus_message_iter_get_basic (&iter, &value); - cookie = g_strdup (value); - dbus_message_unref (reply); - } - - return cookie; -} - -void -close_ck_session (const char *cookie) -{ - DBusError error; - DBusMessage *message; - DBusMessage *reply; - DBusMessageIter iter; - - if (cookie == NULL) { - return; - } - - if (private_connection == NULL) { - return; - } - - dbus_error_init (&error); - message = dbus_message_new_method_call (CK_NAME, - CK_MANAGER_PATH, - CK_MANAGER_INTERFACE, - "CloseSession"); - if (message == NULL) { - gdm_debug ("ConsoleKit: Couldn't allocate the D-Bus message"); - return; - } - - dbus_message_iter_init_append (message, &iter); - dbus_message_iter_append_basic (&iter, - DBUS_TYPE_STRING, - &cookie); - - reply = dbus_connection_send_with_reply_and_block (private_connection, - message, - -1, &error); - if (dbus_error_is_set (&error)) { - gdm_debug ("ConsoleKit: %s raised:\n %s\n\n", error.name, error.message); - reply = NULL; - } - - dbus_connection_flush (private_connection); - - dbus_message_unref (message); - dbus_error_free (&error); - - dbus_connection_close (private_connection); - private_connection = NULL; -} diff --git a/daemon/gdmconsolekit.h b/daemon/gdmconsolekit.h deleted file mode 100644 index 69f9ce39..00000000 --- a/daemon/gdmconsolekit.h +++ /dev/null @@ -1,40 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - - -#ifndef __GDM_CONSOLE_KIT_H -#define __GDM_CONSOLE_KIT_H - -#include <pwd.h> - -#include "display.h" /* for GdmDisplay */ - -G_BEGIN_DECLS - -char * open_ck_session (struct passwd *pwent, - GdmDisplay *display, - const char *session); -void close_ck_session (const char *cookie); -void unlock_ck_session (const char *user, - const char *x11_display); - -G_END_DECLS - -#endif /* __GDM_CONSOLE_KIT_H */ diff --git a/daemon/getvt.c b/daemon/getvt.c deleted file mode 100644 index 941ab8b9..00000000 --- a/daemon/getvt.c +++ /dev/null @@ -1,312 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <dirent.h> -#include <errno.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "gdm.h" -#include "misc.h" -#include "getvt.h" - -#include "gdm-common.h" -#include "gdm-daemon-config.h" - -/* Virtual terminals only supported on Linux, FreeBSD, or DragonFly */ - -#if defined (__linux__) || defined (__FreeBSD__) || defined (__DragonFly__) - -#if defined (__linux__) -#include <sys/vt.h> -#elif defined (__FreeBSD__) || defined (__DragonFly__) -#include <sys/consio.h> - -static const char* -__itovty (int val) -{ - static char str[8]; - char* next = str + sizeof (str) - 1; - - *next = '\0'; - do { - *--next = "0123456789abcdefghigklmnopqrstuv"[val % 32]; - } while (val /= 32); - - return next; -} -#endif - -static int -open_vt (int vtno) -{ - char *vtname; - int fd; - -#if defined (__linux__) - vtname = g_strdup_printf ("/dev/tty%d", vtno); -#elif defined (__FreeBSD__) || defined (__DragonFly__) - vtname = g_strdup_printf ("/dev/ttyv%s", __itovty (vtno - 1)); -#endif - do { - errno = 0; - fd = open (vtname, O_RDWR -#ifdef O_NOCTTY - |O_NOCTTY -#endif - , 0); - } while G_UNLIKELY (errno == EINTR); - g_free (vtname); - return fd; -} - -#if defined (__linux__) - -static int -get_free_vt_linux (int *vtfd) -{ - int fd, fdv; - int vtno; - unsigned short vtmask; - struct vt_stat vtstat; - - *vtfd = -1; - - do { - errno = 0; - fd = open ("/dev/console", O_WRONLY -#ifdef O_NOCTTY - |O_NOCTTY -#endif - , 0); - } while G_UNLIKELY (errno == EINTR); - if (fd < 0) - return -1; - - if (ioctl (fd, VT_GETSTATE, &vtstat) < 0) { - VE_IGNORE_EINTR (close (fd)); - return -1; - } - - for (vtno = gdm_daemon_config_get_value_int (GDM_KEY_FIRST_VT), vtmask = 1 << vtno; - vtstat.v_state & vtmask; vtno++, vtmask <<= 1); - if (!vtmask) { - VE_IGNORE_EINTR (close (fd)); - return -1; - } - - fdv = open_vt (vtno); - if (fdv < 0) { - VE_IGNORE_EINTR (close (fd)); - return -1; - } - *vtfd = fdv; - return vtno; -} - -#elif defined (__FreeBSD__) || defined (__DragonFly__) - -static int -get_free_vt_freebsd_dragonfly (int *vtfd) -{ - int fd, fdv; - int vtno; - GList *to_close_vts = NULL, *li; - - *vtfd = -1; - - do { - errno = 0; - fd = open ("/dev/console", O_WRONLY -#ifdef O_NOCTTY - |O_NOCTTY -#endif - , 0); - } while G_UNLIKELY (errno == EINTR); - if (fd < 0) - return -1; - - if ((ioctl (fd, VT_OPENQRY, &vtno) < 0) || (vtno == -1)) { - VE_IGNORE_EINTR (close (fd)); - return -1; - } - - fdv = open_vt (vtno); - if (fdv < 0) { - VE_IGNORE_EINTR (close (fd)); - return -1; - } - - while (vtno < gdm_daemon_config_get_value_int (GDM_KEY_FIRST_VT)) { - int oldvt = vtno; - to_close_vts = g_list_prepend (to_close_vts, - GINT_TO_POINTER (fdv)); - - if (ioctl (fd, VT_OPENQRY, &vtno) == -1) { - vtno = -1; - goto cleanup; - } - - if (oldvt == vtno) { - vtno = -1; - goto cleanup; - } - - fdv = open_vt (vtno); - if (fdv < 0) { - vtno = -1; - goto cleanup; - } - } - - *vtfd = fdv; - -cleanup: - for (li = to_close_vts; li != NULL; li = li->next) { - VE_IGNORE_EINTR (close (GPOINTER_TO_INT (li->data))); - } - return vtno; -} - -#endif - -char * -gdm_get_empty_vt_argument (int *fd, int *vt) -{ - if ( ! gdm_daemon_config_get_value_bool (GDM_KEY_VT_ALLOCATION)) { - *fd = -1; - return NULL; - } - -#if defined (__linux__) - *vt = get_free_vt_linux (fd); -#elif defined (__FreeBSD__) || defined (__DragonFly__) - *vt = get_free_vt_freebsd_dragonfly (fd); -#endif - - if (*vt < 0) - return NULL; - else - return g_strdup_printf ("vt%d", *vt); -} - -/* change to an existing vt */ -void -gdm_change_vt (int vt) -{ - int fd; - if (vt < 0) - return; - - do { - errno = 0; - fd = open ("/dev/console", O_WRONLY -#ifdef O_NOCTTY - |O_NOCTTY -#endif - , 0); - } while G_UNLIKELY (errno == EINTR); - if (fd < 0) - return; - - ioctl (fd, VT_ACTIVATE, vt); - ioctl (fd, VT_WAITACTIVE, vt); - - VE_IGNORE_EINTR (close (fd)); -} - -int -gdm_get_cur_vt (void) -{ -#if defined (__linux__) - struct vt_stat s; -#elif defined (__FreeBSD__) || defined (__DragonFly__) - int vtno; -#endif - int fd; - - do { - errno = 0; - fd = open ("/dev/console", O_WRONLY -#ifdef O_NOCTTY - |O_NOCTTY -#endif - , 0); - } while G_UNLIKELY (errno == EINTR); - if (fd < 0) - return -1; -#if defined (__linux__) - ioctl (fd, VT_GETSTATE, &s); - - VE_IGNORE_EINTR (close (fd)); - - /* debug */ - /* - printf ("current_Active %d\n", (int)s.v_active); - */ - - return s.v_active; -#elif defined (__FreeBSD__) || defined (__DragonFly__) - if (ioctl (fd, VT_GETACTIVE, &vtno) == -1) { - VE_IGNORE_EINTR (close (fd)); - return -1; - } - - VE_IGNORE_EINTR (close (fd)); - - /* debug */ - /* - printf ("current_Active %d\n", vtno); - */ - - return vtno; -#endif -} - -#else /* here this is just a stub, we don't know how to do this outside - of linux really */ - -char * -gdm_get_empty_vt_argument (int *fd, int *vt) -{ - *fd = -1; - *vt = -1; - return NULL; -} - -void -gdm_change_vt (int vt) -{ - return; -} - -int -gdm_get_cur_vt (void) -{ - return -1; -} - -#endif diff --git a/daemon/getvt.h b/daemon/getvt.h deleted file mode 100644 index fdb1c02d..00000000 --- a/daemon/getvt.h +++ /dev/null @@ -1,41 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 2002 Queen of England - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GETVT_H -#define GETVT_H - -/* gets an argument we should pass to the X server, on - * linux for example we get the first empty vt (higher than - * or equal to GDM_KEY_FIRST_VT) and then return vt<number> - * (e.g. "vt7") as a newly allocated string. - * Can return NULL if we can't figure out what to do - * or if GDM_KEY_VT_ALLOCATION is false. */ -/* fd is opened so that we are saying we have opened this - * vt. This should be closed after the server has started. - * This is to avoid race with other stuff openning this vt. - * It can be set to -1 if nothing could be opened. */ -char * gdm_get_empty_vt_argument (int *fd, - int *vt); - -/* Change to the specified virtual terminal */ -void gdm_change_vt (int vt); - -/* Get the current virtual terminal number or -1 if we can't */ -int gdm_get_cur_vt (void); - -#endif /* GETVT_H */ diff --git a/daemon/md5.c b/daemon/md5.c deleted file mode 100644 index 3faf29a0..00000000 --- a/daemon/md5.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * GdmMD5Context structure, pass it to gdm_md5_init, call - * gdm_md5_update as needed on buffers full of bytes, and then call - * gdm_md5_final, which will fill a supplied 16-byte array with the - * digest. - * - * Changed all names to avoid glibc namespace pollution -- mkp - * - */ - -#include "config.h" -#include <string.h> /* for memcpy () */ -#include <glib.h> - -#ifdef __LINUX__ -#include <endian.h> -#endif - -#include "md5.h" - -#if BYTE_ORDER == LITTLE_ENDIAN -#define byteReverse(buf, len) /* Nothing */ -#else - -/* - * Note: this code is harmless on little-endian machines. - */ -static void -byteReverse(unsigned char *buf, unsigned longs) -{ - guint32 t; - do { - t = (guint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(guint32 *) buf = t; - buf += 4; - } while (--longs); -} - -#endif - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void -gdm_md5_init (struct GdmMD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void -gdm_md5_update (struct GdmMD5Context *ctx, unsigned char const *buf, unsigned len) -{ - guint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((guint32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memcpy (p, buf, len); - return; - } - memcpy (p, buf, t); - byteReverse(ctx->in, 16); - gdm_md5_transform (ctx->buf, (guint32 *) ctx->in); - buf += t; - len -= t; - } - - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy (ctx->in, buf, 64); - byteReverse(ctx->in, 16); - gdm_md5_transform (ctx->buf, (guint32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy (ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void -gdm_md5_final (unsigned char digest[16], struct GdmMD5Context *ctx) -{ - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset (p, 0, count); - byteReverse(ctx->in, 16); - gdm_md5_transform (ctx->buf, (guint32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset (ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset (p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((guint32 *) ctx->in)[14] = ctx->bits[0]; - ((guint32 *) ctx->in)[15] = ctx->bits[1]; - - gdm_md5_transform (ctx->buf, (guint32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memcpy (digest, ctx->buf, 16); - memset (ctx, 0, sizeof (ctx)); /* In case it's sensitive */ -} - - -/* The four core functions - F1 is optimized somewhat */ - -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1 (z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define gdm_md5_step(f, w, x, y, z, data, s) \ - ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. GdmMD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -void -gdm_md5_transform (guint32 buf[4], guint32 const in[16]) -{ - register guint32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - gdm_md5_step(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - gdm_md5_step(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - gdm_md5_step(F1, c, d, a, b, in[2] + 0x242070db, 17); - gdm_md5_step(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - gdm_md5_step(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - gdm_md5_step(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - gdm_md5_step(F1, c, d, a, b, in[6] + 0xa8304613, 17); - gdm_md5_step(F1, b, c, d, a, in[7] + 0xfd469501, 22); - gdm_md5_step(F1, a, b, c, d, in[8] + 0x698098d8, 7); - gdm_md5_step(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - gdm_md5_step(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - gdm_md5_step(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - gdm_md5_step(F1, a, b, c, d, in[12] + 0x6b901122, 7); - gdm_md5_step(F1, d, a, b, c, in[13] + 0xfd987193, 12); - gdm_md5_step(F1, c, d, a, b, in[14] + 0xa679438e, 17); - gdm_md5_step(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - gdm_md5_step(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - gdm_md5_step(F2, d, a, b, c, in[6] + 0xc040b340, 9); - gdm_md5_step(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - gdm_md5_step(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - gdm_md5_step(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - gdm_md5_step(F2, d, a, b, c, in[10] + 0x02441453, 9); - gdm_md5_step(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - gdm_md5_step(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - gdm_md5_step(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - gdm_md5_step(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - gdm_md5_step(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - gdm_md5_step(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - gdm_md5_step(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - gdm_md5_step(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - gdm_md5_step(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - gdm_md5_step(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - gdm_md5_step(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - gdm_md5_step(F3, d, a, b, c, in[8] + 0x8771f681, 11); - gdm_md5_step(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - gdm_md5_step(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - gdm_md5_step(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - gdm_md5_step(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - gdm_md5_step(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - gdm_md5_step(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - gdm_md5_step(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - gdm_md5_step(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - gdm_md5_step(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - gdm_md5_step(F3, b, c, d, a, in[6] + 0x04881d05, 23); - gdm_md5_step(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - gdm_md5_step(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - gdm_md5_step(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - gdm_md5_step(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - gdm_md5_step(F4, a, b, c, d, in[0] + 0xf4292244, 6); - gdm_md5_step(F4, d, a, b, c, in[7] + 0x432aff97, 10); - gdm_md5_step(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - gdm_md5_step(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - gdm_md5_step(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - gdm_md5_step(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - gdm_md5_step(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - gdm_md5_step(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - gdm_md5_step(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - gdm_md5_step(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - gdm_md5_step(F4, c, d, a, b, in[6] + 0xa3014314, 15); - gdm_md5_step(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - gdm_md5_step(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - gdm_md5_step(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - gdm_md5_step(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - gdm_md5_step(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - - - diff --git a/daemon/md5.h b/daemon/md5.h deleted file mode 100644 index 38b992b0..00000000 --- a/daemon/md5.h +++ /dev/null @@ -1,41 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GdmMD5_H -#define GdmMD5_H - -#include <glib.h> - -struct GdmMD5Context { - guint32 buf[4]; - guint32 bits[2]; - unsigned char in[64]; -}; - -void gdm_md5_init (struct GdmMD5Context *context); -void gdm_md5_update (struct GdmMD5Context *context, unsigned char const *buf, - unsigned len); -void gdm_md5_final (unsigned char digest[16], struct GdmMD5Context *context); -void gdm_md5_transform (guint32 buf[4], guint32 const in[16]); - -/* - * This is needed to make RSAREF happy on some MS-DOS compilers. - */ -/* typedef struct gdm_md5_Context gdm_md5__CTX; */ - -#endif /* !GdmMD5_H */ diff --git a/daemon/misc.c b/daemon/misc.c deleted file mode 100644 index a4080795..00000000 --- a/daemon/misc.c +++ /dev/null @@ -1,2165 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <unistd.h> -#include <stdlib.h> -#include <dirent.h> -#include <signal.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <sys/ioctl.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <fcntl.h> -#include <netinet/in.h> -#include <net/if.h> -#include <arpa/inet.h> -#include <netdb.h> -#include <errno.h> -#include <grp.h> -#include <pwd.h> -#include <sys/types.h> -#ifdef HAVE_SYS_SOCKIO_H -#include <sys/sockio.h> -#endif -#ifdef HAVE_DEFOPEN -#include <deflt.h> -#endif - -#include <X11/Xlib.h> - -#include <glib/gi18n.h> - -#include "gdm.h" -#include "misc.h" -#include "xdmcp.h" -#include "slave.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -extern char **environ; - -#ifdef ENABLE_IPV6 - -#ifdef __sun -static gboolean -have_ipv6_solaris (void) -{ - int s, i; - int ret; - struct lifnum ln; - struct lifconf ifc; - struct lifreq *ifr; - char *ifreqs; - - /* First, try the <AB>classic<BB> way */ - s = socket (AF_INET6, SOCK_DGRAM, 0); - if (s < 0) return FALSE; - close (s); - - s = socket (AF_INET6, SOCK_DGRAM, IPPROTO_UDP); - - /* - * Ok, the system is able to create IPv6 sockets, so - * lets check if IPv6 is configured in the machine - */ - ln.lifn_family=AF_UNSPEC; - ln.lifn_flags=ln.lifn_count=0; - - ret = ioctl (s, SIOCGLIFNUM, &ln); - if (ret == -1) { - perror ("ioctl SIOCGLIFNUM"); - return FALSE; - } - - /* Alloc the memory and get the configuration */ - ifc.lifc_flags = 0; - ifc.lifc_family = AF_UNSPEC; - ifc.lifc_len = ln.lifn_count * sizeof (struct lifreq); - - ifreqs = (char *) malloc (ifc.lifc_len); - ifc.lifc_buf = ifreqs; - - if (ioctl (s, SIOCGLIFCONF, &ifc) < 0) { - perror ("ioctl SIOCGLIFCONF"); - return FALSE; - } - - /* Check each interface */ - ifr = ifc.lifc_req; - ret = FALSE; - - for (i = ifc.lifc_len/sizeof (struct lifreq); --i >= 0; ifr++) { - struct sockaddr_in *sin; - - /* Check the address */ - if (ioctl (s, SIOCGLIFFLAGS, ifr) < 0) { - /* perror ("ioctl SIOCGLIFADDR"); */ - continue; - } - - sin = (struct sockaddr_in *)&ifr->lifr_addr; - - if (sin->sin_family == AF_INET6) { - ret = TRUE; - break; - } - - /* Check the interface flags */ - if (ioctl (s, SIOCGLIFFLAGS, (char *) ifr) < 0) { - /* perror ("ioctl SIOCGLIFFLAGS"); */ - continue; - } - - if (ifr->lifr_flags & IFF_IPV6) { - ret = TRUE; - break; - } - } - - /* Clean up */ - free (ifreqs); - close (s); - - return ret; -} -#endif - -static gboolean -have_ipv6 (void) -{ - int s; - static gboolean has_ipv6 = -1; - -#ifdef __sun - has_ipv6 = have_ipv6_solaris (); -#else - if (has_ipv6 != -1) return has_ipv6; - - s = socket (AF_INET6, SOCK_STREAM, 0); - if (s < 0) { - has_ipv6 = FALSE; - return FALSE; - } - - VE_IGNORE_EINTR (close (s)); -#endif - return has_ipv6; -} -#endif - -void -gdm_fdprintf (int fd, const gchar *format, ...) -{ - va_list args; - gchar *s; - int written, len; - - va_start (args, format); - s = g_strdup_vprintf (format, args); - va_end (args); - - len = strlen (s); - - if (len == 0) { - g_free (s); - return; - } - - written = 0; - while (written < len) { - int w; - VE_IGNORE_EINTR (w = write (fd, &s[written], len - written)); - if (w < 0) - /* evil! */ - break; - written += w; - } - - g_free (s); -} - -/* - * Clear environment, but keep the i18n ones, - * note that this leaks memory so only use before exec - */ -void -gdm_clearenv_no_lang (void) -{ - int i; - GList *li, *envs = NULL; - - for (i = 0; environ[i] != NULL; i++) { - char *env = environ[i]; - if (strncmp (env, "LC_", 3) == 0 || - strncmp (env, "LANG", 4) == 0 || - strncmp (env, "LINGUAS", 7) == 0) { - envs = g_list_prepend (envs, g_strdup (env)); - } - } - - ve_clearenv (); - - for (li = envs; li != NULL; li = li->next) { - putenv (li->data); - } - - g_list_free (envs); -} - -static GList *stored_env = NULL; - -void -gdm_saveenv (void) -{ - int i; - - g_list_foreach (stored_env, (GFunc)g_free, NULL); - g_list_free (stored_env); - stored_env = NULL; - - for (i = 0; environ[i] != NULL; i++) { - char *env = environ[i]; - stored_env = g_list_prepend (stored_env, g_strdup (env)); - } -} - -const char * -gdm_saved_getenv (const char *var) -{ - int len; - GList *li; - - len = strlen (var); - - for (li = stored_env; li != NULL; li = li->next) { - const char *e = li->data; - if (strncmp (var, e, len) == 0 && - e[len] == '=') { - return &(e[len+1]); - } - } - return NULL; -} - -/* leaks */ -void -gdm_restoreenv (void) -{ - GList *li; - - ve_clearenv (); - - for (li = stored_env; li != NULL; li = li->next) { - putenv (g_strdup (li->data)); - } -} - -/* Evil function to figure out which display number is free */ -int -gdm_get_free_display (int start, uid_t server_uid) -{ - int sock; - int i; - struct sockaddr_in serv_addr = { 0 }; - - serv_addr.sin_family = AF_INET; - serv_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - - /* - * Cap this at 3000, I'm not sure we can ever seriously - * go that far - */ - for (i = start; i < 3000; i++) { - GSList *li; - struct stat s; - char buf[256]; - FILE *fp; - int r; - GSList *displays; - - displays = gdm_daemon_config_get_display_list (); - - for (li = displays; li != NULL; li = li->next) { - GdmDisplay *dsp = li->data; - if (SERVER_IS_LOCAL (dsp) && - dsp->dispnum == i) - break; - } - if (li != NULL) { - /* found one */ - continue; - } - -#ifdef ENABLE_IPV6 - if (have_ipv6 ()) { - struct sockaddr_in6 serv6_addr = { 0 }; - - sock = socket (AF_INET6, SOCK_STREAM,0); - - serv6_addr.sin6_family = AF_INET6; - serv6_addr.sin6_addr = in6addr_loopback; - serv6_addr.sin6_port = htons (6000 + i); - errno = 0; - VE_IGNORE_EINTR (connect (sock, - (struct sockaddr *)&serv6_addr, - sizeof (serv6_addr))); - } - else -#endif - { - sock = socket (AF_INET, SOCK_STREAM, 0); - - serv_addr.sin_port = htons (6000 + i); - - errno = 0; - VE_IGNORE_EINTR (connect (sock, - (struct sockaddr *)&serv_addr, - sizeof (serv_addr))); - } - if (errno != 0 && errno != ECONNREFUSED) { - VE_IGNORE_EINTR (close (sock)); - continue; - } - VE_IGNORE_EINTR (close (sock)); - - /* if lock file exists and the process exists */ - g_snprintf (buf, sizeof (buf), "/tmp/.X%d-lock", i); - VE_IGNORE_EINTR (r = g_stat (buf, &s)); - if (r == 0 && - ! S_ISREG (s.st_mode)) { - /* - * Eeeek! not a regular file? Perhaps someone - * is trying to play tricks on us - */ - continue; - } - VE_IGNORE_EINTR (fp = fopen (buf, "r")); - if (fp != NULL) { - char buf2[100]; - char *getsret; - VE_IGNORE_EINTR (getsret = fgets (buf2, sizeof (buf2), fp)); - if (getsret != NULL) { - gulong pid; - if (sscanf (buf2, "%lu", &pid) == 1 && - kill (pid, 0) == 0) { - VE_IGNORE_EINTR (fclose (fp)); - continue; - } - - } - VE_IGNORE_EINTR (fclose (fp)); - - /* whack the file, it's a stale lock file */ - VE_IGNORE_EINTR (g_unlink (buf)); - } - - /* If starting as root, we'll be able to overwrite any - * stale sockets or lock files, but a user may not be - * able to */ - if (server_uid > 0) { - g_snprintf (buf, sizeof (buf), - "/tmp/.X11-unix/X%d", i); - VE_IGNORE_EINTR (r = g_stat (buf, &s)); - if (r == 0 && - s.st_uid != server_uid) { - continue; - } - - g_snprintf (buf, sizeof (buf), - "/tmp/.X%d-lock", i); - VE_IGNORE_EINTR (r = g_stat (buf, &s)); - if (r == 0 && - s.st_uid != server_uid) { - continue; - } - } - - return i; - } - - return -1; -} - -gboolean -gdm_text_message_dialog (const char *msg) -{ - char *dialog; /* do we have dialog? */ - char *msg_quoted; - - if ( ! gdm_daemon_config_get_value_bool (GDM_KEY_CONSOLE_NOTIFY)) - return FALSE; - - if (g_access (LIBEXECDIR "/gdmopen", X_OK) != 0) - return FALSE; - - if (msg[0] == '-') { - char *tmp = g_strconcat (" ", msg, NULL); - msg_quoted = g_shell_quote (tmp); - g_free (tmp); - } else { - msg_quoted = g_shell_quote (msg); - } - - dialog = g_find_program_in_path ("dialog"); - if (dialog == NULL) - dialog = g_find_program_in_path ("whiptail"); - if (dialog != NULL) { - char *argv[6]; - - if ( ! gdm_ok_console_language ()) { - g_unsetenv ("LANG"); - g_unsetenv ("LC_ALL"); - g_unsetenv ("LC_MESSAGES"); - g_setenv ("LANG", "C", TRUE); - g_setenv ("UNSAFE_TO_TRANSLATE", "yes", TRUE); - } - - argv[0] = LIBEXECDIR "/gdmopen"; - argv[1] = "-l"; - argv[2] = "/bin/sh"; - argv[3] = "-c"; - argv[4] = g_strdup_printf ("%s --msgbox %s 16 70", - dialog, msg_quoted); - argv[5] = NULL; - - /* Make sure gdialog wouldn't get confused */ - if (gdm_exec_wait (argv, TRUE /* no display */, - TRUE /* de_setuid */) < 0) { - g_free (dialog); - g_free (msg_quoted); - g_free (argv[4]); - return FALSE; - } - - g_free (dialog); - g_free (argv[4]); - } else { - char *argv[6]; - - argv[0] = LIBEXECDIR "/gdmopen"; - argv[1] = "-l"; - argv[2] = "/bin/sh"; - argv[3] = "-c"; - argv[4] = g_strdup_printf - ("clear ; " - "echo %s ; read ; clear", - msg_quoted); - argv[5] = NULL; - - if (gdm_exec_wait (argv, TRUE /* no display */, - TRUE /* de_setuid */) < 0) { - g_free (argv[4]); - g_free (msg_quoted); - return FALSE; - } - g_free (argv[4]); - } - g_free (msg_quoted); - return TRUE; -} - -gboolean -gdm_text_yesno_dialog (const char *msg, gboolean *ret) -{ - char *dialog; /* do we have dialog? */ - char *msg_quoted; - - if ( ! gdm_daemon_config_get_value_bool (GDM_KEY_CONSOLE_NOTIFY)) - return FALSE; - - if (g_access (LIBEXECDIR "/gdmopen", X_OK) != 0) - return FALSE; - - if (ret != NULL) - *ret = FALSE; - - if (msg[0] == '-') { - char *tmp = g_strconcat (" ", msg, NULL); - msg_quoted = g_shell_quote (tmp); - g_free (tmp); - } else { - msg_quoted = g_shell_quote (msg); - } - - dialog = g_find_program_in_path ("dialog"); - if (dialog == NULL) - dialog = g_find_program_in_path ("whiptail"); - if (dialog != NULL) { - char *argv[6]; - int retint; - - if ( ! gdm_ok_console_language ()) { - g_unsetenv ("LANG"); - g_unsetenv ("LC_ALL"); - g_unsetenv ("LC_MESSAGES"); - g_setenv ("LANG", "C", TRUE); - g_setenv ("UNSAFE_TO_TRANSLATE", "yes", TRUE); - } - - argv[0] = LIBEXECDIR "/gdmopen"; - argv[1] = "-l"; - argv[2] = "/bin/sh"; - argv[3] = "-c"; - argv[4] = g_strdup_printf ("%s --yesno %s 16 70", - dialog, msg_quoted); - argv[5] = NULL; - - /* - * Will unset DISPLAY and XAUTHORITY if they exist - * so that gdialog (if used) doesn't get confused - */ - retint = gdm_exec_wait (argv, TRUE /* no display */, - TRUE /* de_setuid */); - if (retint < 0) { - g_free (argv[4]); - g_free (dialog); - g_free (msg_quoted); - return FALSE; - } - - if (ret != NULL) - *ret = (retint == 0) ? TRUE : FALSE; - - g_free (dialog); - g_free (msg_quoted); - g_free (argv[4]); - - return TRUE; - } else { - char tempname[] = "/tmp/gdm-yesno-XXXXXX"; - int tempfd; - FILE *fp; - char buf[256]; - char *argv[6]; - - tempfd = g_mkstemp (tempname); - if (tempfd < 0) { - g_free (msg_quoted); - return FALSE; - } - - VE_IGNORE_EINTR (close (tempfd)); - - argv[0] = LIBEXECDIR "/gdmopen"; - argv[1] = "-l"; - argv[2] = "/bin/sh"; - argv[3] = "-c"; - argv[4] = g_strdup_printf - ("clear ; " - "echo %s ; echo ; echo \"%s\" ; " - "read RETURN ; echo $RETURN > %s ; clear'", - msg_quoted, - /* Translators, don't translate the 'y' and 'n' */ - _("y = Yes or n = No? >"), - tempname); - argv[5] = NULL; - - if (gdm_exec_wait (argv, TRUE /* no display */, - TRUE /* de_setuid */) < 0) { - g_free (argv[4]); - g_free (msg_quoted); - return FALSE; - } - g_free (argv[4]); - - if (ret != NULL) { - VE_IGNORE_EINTR (fp = fopen (tempname, "r")); - if (fp != NULL) { - if (fgets (buf, sizeof (buf), fp) != NULL && - (buf[0] == 'y' || buf[0] == 'Y')) - *ret = TRUE; - VE_IGNORE_EINTR (fclose (fp)); - } else { - g_free (msg_quoted); - return FALSE; - } - } - - VE_IGNORE_EINTR (g_unlink (tempname)); - - g_free (msg_quoted); - return TRUE; - } -} - -int -gdm_exec_wait (char * const *argv, - gboolean no_display, - gboolean de_setuid) -{ - int status; - pid_t pid; - - if (argv == NULL || - argv[0] == NULL || - g_access (argv[0], X_OK) != 0) - return -1; - - g_debug ("Forking extra process: %s", argv[0]); - - pid = gdm_fork_extra (); - if (pid == 0) { - gdm_log_shutdown (); - - gdm_close_all_descriptors (0 /* from */, -1 /* except */, -1 /* except2 */); - - /* - * No error checking here - if it's messed the best response - * is to ignore & try to continue - */ - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - if (de_setuid) { - gdm_desetuid (); - } - - gdm_log_init (); - - if (no_display) { - g_unsetenv ("DISPLAY"); - g_unsetenv ("XAUTHORITY"); - } - - VE_IGNORE_EINTR (execv (argv[0], argv)); - - _exit (-1); - } - - if (pid < 0) - return -1; - - gdm_wait_for_extra (pid, &status); - - if (WIFEXITED (status)) - return WEXITSTATUS (status); - else - return -1; -} - -static int sigchld_blocked = 0; -static sigset_t sigchldblock_mask, sigchldblock_oldmask; - -static int sigterm_blocked = 0; -static sigset_t sigtermblock_mask, sigtermblock_oldmask; - -static int sigusr2_blocked = 0; -static sigset_t sigusr2block_mask, sigusr2block_oldmask; - -void -gdm_sigchld_block_push (void) -{ - sigchld_blocked++; - - if (sigchld_blocked == 1) { - /* Set signal mask */ - sigemptyset (&sigchldblock_mask); - sigaddset (&sigchldblock_mask, SIGCHLD); - sigprocmask (SIG_BLOCK, &sigchldblock_mask, &sigchldblock_oldmask); - } -} - -void -gdm_sigchld_block_pop (void) -{ - sigchld_blocked --; - - if (sigchld_blocked == 0) { - /* Reset signal mask back */ - sigprocmask (SIG_SETMASK, &sigchldblock_oldmask, NULL); - } -} - -void -gdm_sigterm_block_push (void) -{ - sigterm_blocked++; - - if (sigterm_blocked == 1) { - /* Set signal mask */ - sigemptyset (&sigtermblock_mask); - sigaddset (&sigtermblock_mask, SIGTERM); - sigaddset (&sigtermblock_mask, SIGINT); - sigaddset (&sigtermblock_mask, SIGHUP); - sigprocmask (SIG_BLOCK, &sigtermblock_mask, &sigtermblock_oldmask); - } -} - -void -gdm_sigterm_block_pop (void) -{ - sigterm_blocked --; - - if (sigterm_blocked == 0) { - /* Reset signal mask back */ - sigprocmask (SIG_SETMASK, &sigtermblock_oldmask, NULL); - } -} - -void -gdm_sigusr2_block_push (void) -{ - sigset_t oldmask; - - if (sigusr2_blocked == 0) { - /* Set signal mask */ - sigemptyset (&sigusr2block_mask); - sigaddset (&sigusr2block_mask, SIGUSR2); - sigprocmask (SIG_BLOCK, &sigusr2block_mask, &oldmask); - } - - sigusr2_blocked++; - - sigusr2block_oldmask = oldmask; -} - -void -gdm_sigusr2_block_pop (void) -{ - sigset_t oldmask; - - oldmask = sigusr2block_oldmask; - - sigusr2_blocked--; - - if (sigusr2_blocked == 0) { - /* Reset signal mask back */ - sigprocmask (SIG_SETMASK, &sigusr2block_oldmask, NULL); - } -} - -pid_t -gdm_fork_extra (void) -{ - pid_t pid; - - gdm_sigchld_block_push (); - gdm_sigterm_block_push (); - - pid = fork (); - if (pid < 0) - return 0; - else if (pid == 0) - /* - * Unset signals here, and yet again - * later as the block_pop will whack - * our signal mask - */ - gdm_unset_signals (); - - gdm_sigterm_block_pop (); - gdm_sigchld_block_pop (); - - if (pid == 0) { - /* - * In the child setup empty mask and set all signals to - * default values - */ - gdm_unset_signals (); - - /* - * Also make a new process group so that we may use - * kill -(extra_process) to kill extra process and all it's - * possible children - */ - setsid (); - - /* Harmless in children, but in case we'd run - extra processes from main daemon would fix - problems ... */ - if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP)) - gdm_xdmcp_close (); - } - - return pid; -} - -void -gdm_wait_for_extra (pid_t pid, - int *statusp) -{ - int status; - - gdm_sigchld_block_push (); - - if (pid > 1) { - ve_waitpid_no_signal (pid, &status, 0); - } - - if (statusp != NULL) - *statusp = status; - - gdm_sigchld_block_pop (); -} - -static void -ensure_tmp_socket_dir (const char *dir) -{ - mode_t old_umask; - - /* - * The /tmp/.ICE-unix / .X11-unix check, note that we do - * ignore errors, since it's not deadly to run - * if we can't perform this task :) - */ - old_umask = umask (0); - - if G_UNLIKELY (g_mkdir (dir, 01777) != 0) { - /* - * If we can't create it, perhaps it - * already exists, in which case ensure the - * correct permissions - */ - struct stat s; - int r; - VE_IGNORE_EINTR (r = g_lstat (dir, &s)); - if G_LIKELY (r == 0 && S_ISDIR (s.st_mode)) { - /* Make sure it is root and sticky */ - VE_IGNORE_EINTR (chown (dir, 0, 0)); - VE_IGNORE_EINTR (g_chmod (dir, 01777)); - } else { - /* - * There is a file/link/whatever of the same name? - * whack and try mkdir - */ - VE_IGNORE_EINTR (g_unlink (dir)); - g_mkdir (dir, 01777); - } - } - - umask (old_umask); -} - -/* - * Done on startup and when running display_manage - * This can do some sanity ensuring, one of the things it does now is make - * sure /tmp/.ICE-unix and /tmp/.X11-unix exist and have the correct - * permissions - */ -void -gdm_ensure_sanity (void) -{ - uid_t old_euid; - gid_t old_egid; - - old_euid = geteuid (); - old_egid = getegid (); - - NEVER_FAILS_root_set_euid_egid (0, 0); - - ensure_tmp_socket_dir ("/tmp/.ICE-unix"); - ensure_tmp_socket_dir ("/tmp/.X11-unix"); - - NEVER_FAILS_root_set_euid_egid (old_euid, old_egid); -} - -const GList * -gdm_address_peek_local_list (void) -{ - static GList *the_list = NULL; - static time_t last_time = 0; - char hostbuf[BUFSIZ]; - struct addrinfo hints; - struct addrinfo *result; - struct addrinfo *res; - - /* Don't check more then every 5 seconds */ - if (last_time + 5 > time (NULL)) { - return the_list; - } - - g_list_foreach (the_list, (GFunc)g_free, NULL); - g_list_free (the_list); - the_list = NULL; - - last_time = time (NULL); - - hostbuf[BUFSIZ-1] = '\0'; - if (gethostname (hostbuf, BUFSIZ-1) != 0) { - gdm_debug ("%s: Could not get server hostname, using localhost", "gdm_peek_local_address_list"); - snprintf (hostbuf, BUFSIZ-1, "localhost"); - } - - memset (&hints, 0, sizeof (hints)); - hints.ai_family = AF_INET; -#ifdef ENABLE_IPV6 - hints.ai_family |= AF_INET6; -#endif - - if (getaddrinfo (hostbuf, NULL, &hints, &result) != 0) { - gdm_debug ("%s: Could not get address from hostname!", "gdm_peek_local_address_list"); - - return NULL; - } - - for (res = result; res != NULL; res = res->ai_next) { - struct sockaddr_storage *sa; - - sa = g_memdup (res->ai_addr, res->ai_addrlen); - the_list = g_list_append (the_list, sa); - } - - if (result) { - freeaddrinfo (result); - result = NULL; - } - - return the_list; -} - - -gboolean -gdm_address_is_local (struct sockaddr_storage *sa) -{ - const GList *list; - - if (gdm_address_is_loopback (sa)) { - return TRUE; - } - - list = gdm_address_peek_local_list (); - - while (list != NULL) { - struct sockaddr_storage *addr = list->data; - - if (gdm_address_equal (sa, addr)) { - return TRUE; - } - - list = list->next; - } - - return FALSE; -} - -gboolean -gdm_setup_gids (const char *login, gid_t gid) -{ - /* - * FIXME: perhaps for *BSD there should be setusercontext - * stuff here - */ - if G_UNLIKELY (setgid (gid) < 0) { - gdm_error (_("Could not setgid %d. Aborting."), (int)gid); - return FALSE; - } - - if G_UNLIKELY (initgroups (login, gid) < 0) { - gdm_error (_("initgroups () failed for %s. Aborting."), login); - return FALSE; - } - - return TRUE; -} - -void -gdm_desetuid (void) -{ - uid_t uid = getuid (); - gid_t gid = getgid (); - -#ifdef HAVE_SETRESUID - { - int setresuid (uid_t ruid, uid_t euid, uid_t suid); - int setresgid (gid_t rgid, gid_t egid, gid_t sgid); - setresgid (gid, gid, gid); - setresuid (uid, uid, uid); - } -#else - setegid (getgid ()); - seteuid (getuid ()); -#endif -} - -gboolean -gdm_test_opt (const char *cmd, const char *help, const char *option) -{ - char *q; - char *full; - char buf[1024]; - FILE *fp; - static GString *cache = NULL; - static char *cached_cmd = NULL; - gboolean got_it; - - if (cached_cmd != NULL && - strcmp (cached_cmd, cmd) == 0) { - char *p = strstr (ve_sure_string (cache->str), option); - char end; - if (p == NULL) - return FALSE; - /* Must be a full word */ - end = *(p + strlen (option)); - if ((end >= 'a' && end <= 'z') || - (end >= 'A' && end <= 'Z') || - (end >= '0' && end <= '9') || - end == '_') - return FALSE; - return TRUE; - } - - g_free (cached_cmd); - cached_cmd = g_strdup (cmd); - if (cache != NULL) - g_string_assign (cache, ""); - else - cache = g_string_new (NULL); - - q = g_shell_quote (cmd); - - full = g_strdup_printf ("%s %s 2>&1", q, help); - g_free (q); - - fp = popen (full, "r"); - g_free (full); - - if (fp == NULL) - return FALSE; - - got_it = FALSE; - - while (fgets (buf, sizeof (buf), fp) != NULL) { - char *p; - char end; - - g_string_append (cache, buf); - - if (got_it) - continue; - - p = strstr (buf, option); - if (p == NULL) - continue; - /* Must be a full word */ - end = *(p + strlen (option)); - if ((end >= 'a' && end <= 'z') || - (end >= 'A' && end <= 'Z') || - (end >= '0' && end <= '9') || - end == '_') - continue; - - got_it = TRUE; - } - VE_IGNORE_EINTR (fclose (fp)); - return got_it; -} - -int -gdm_fdgetc (int fd) -{ - char buf[1]; - int bytes; - - VE_IGNORE_EINTR (bytes = read (fd, buf, 1)); - if (bytes != 1) - return EOF; - else - return (int)buf[0]; -} - -char * -gdm_fdgets (int fd) -{ - int c; - int bytes = 0; - GString *gs = g_string_new (NULL); - for (;;) { - c = gdm_fdgetc (fd); - if (c == '\n') - return g_string_free (gs, FALSE); - /* on EOF */ - if (c < 0) { - if (bytes == 0) { - g_string_free (gs, TRUE); - return NULL; - } else { - return g_string_free (gs, FALSE); - } - } else { - bytes++; - g_string_append_c (gs, c); - } - } -} - -void -gdm_close_all_descriptors (int from, int except, int except2) -{ - DIR *dir; - struct dirent *ent; - GSList *openfds = NULL; - - /* - * Evil, but less evil then going to _SC_OPEN_MAX - * which can be very VERY large - */ - dir = opendir ("/proc/self/fd/"); /* This is the Linux dir */ - if (dir == NULL) - dir = opendir ("/dev/fd/"); /* This is the FreeBSD dir */ - if G_LIKELY (dir != NULL) { - GSList *li; - while ((ent = readdir (dir)) != NULL) { - int fd; - if (ent->d_name[0] == '.') - continue; - fd = atoi (ent->d_name); - if (fd >= from && fd != except && fd != except2) - openfds = g_slist_prepend (openfds, GINT_TO_POINTER (fd)); - } - closedir (dir); - for (li = openfds; li != NULL; li = li->next) { - int fd = GPOINTER_TO_INT (li->data); - VE_IGNORE_EINTR (close (fd)); - } - g_slist_free (openfds); - } else { - int i; - int max = sysconf (_SC_OPEN_MAX); - /* - * Don't go higher then this. This is - * a safety measure to not hang on crazy - * systems - */ - if G_UNLIKELY (max > 4096) { - /* FIXME: warn about this perhaps */ - /* - * Try an open, in case we're really - * leaking fds somewhere badly, this - * should be very high - */ - i = gdm_open_dev_null (O_RDONLY); - max = MAX (i+1, 4096); - } - for (i = from; i < max; i++) { - if G_LIKELY (i != except && i != except2) - VE_IGNORE_EINTR (close (i)); - } - } -} - -int -gdm_open_dev_null (mode_t mode) -{ - int ret; - VE_IGNORE_EINTR (ret = open ("/dev/null", mode)); - if G_UNLIKELY (ret < 0) { - /* - * Never output anything, we're likely in some - * strange state right now - */ - gdm_signal_ignore (SIGPIPE); - VE_IGNORE_EINTR (close (2)); - gdm_fail ("Cannot open /dev/null, system on crack!"); - } - - return ret; -} - -void -gdm_unset_signals (void) -{ - sigset_t mask; - - sigemptyset (&mask); - sigprocmask (SIG_SETMASK, &mask, NULL); - - gdm_signal_default (SIGUSR1); - gdm_signal_default (SIGUSR2); - gdm_signal_default (SIGCHLD); - gdm_signal_default (SIGTERM); - gdm_signal_default (SIGINT); - gdm_signal_default (SIGPIPE); - gdm_signal_default (SIGALRM); - gdm_signal_default (SIGHUP); - gdm_signal_default (SIGABRT); -#ifdef SIGXFSZ - gdm_signal_default (SIGXFSZ); -#endif -#ifdef SIGXCPU - gdm_signal_default (SIGXCPU); -#endif -} - -void -gdm_signal_ignore (int signal) -{ - struct sigaction ign_signal; - - ign_signal.sa_handler = SIG_IGN; - ign_signal.sa_flags = SA_RESTART; - sigemptyset (&ign_signal.sa_mask); - - if G_UNLIKELY (sigaction (signal, &ign_signal, NULL) < 0) - gdm_error (_("%s: Error setting signal %d to %s"), - "gdm_signal_ignore", signal, "SIG_IGN"); -} - -void -gdm_signal_default (int signal) -{ - struct sigaction def_signal; - - def_signal.sa_handler = SIG_DFL; - def_signal.sa_flags = SA_RESTART; - sigemptyset (&def_signal.sa_mask); - - if G_UNLIKELY (sigaction (signal, &def_signal, NULL) < 0) - gdm_error (_("%s: Error setting signal %d to %s"), - "gdm_signal_ignore", signal, "SIG_DFL"); -} - -static GdmHostent * -fillout_addrinfo (struct addrinfo *res, - struct sockaddr *ia, - const char *name) -{ - GdmHostent *he; - gint i; - gint addr_count = 0; - struct addrinfo *tempaddrinfo; - - he = g_new0 (GdmHostent, 1); - - he->addrs = NULL; - he->addr_count = 0; - - if (res != NULL && res->ai_canonname != NULL) { - he->hostname = g_strdup (res->ai_canonname); - he->not_found = FALSE; - } else { - he->not_found = TRUE; - if (name != NULL) - he->hostname = g_strdup (name); - else { - static char buffer6[INET6_ADDRSTRLEN]; - static char buffer[INET_ADDRSTRLEN]; - const char *new = NULL; - - if (ia->sa_family == AF_INET6) { - if (IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)ia)->sin6_addr)) { - new = inet_ntop (AF_INET, &(((struct sockaddr_in6 *)ia)->sin6_addr.s6_addr[12]), buffer, sizeof (buffer)); - } else { - new = inet_ntop (AF_INET6, &((struct sockaddr_in6 *)ia)->sin6_addr, buffer6, sizeof (buffer6)); - } - } else if (ia->sa_family == AF_INET) { - new = inet_ntop (AF_INET, &((struct sockaddr_in *)ia)->sin_addr, buffer, sizeof (buffer)); - } - - if (new != NULL) { - he->hostname = g_strdup (new); - } else { - he->hostname = NULL; - } - } - } - - tempaddrinfo = res; - - while (res != NULL) { - addr_count++; - res = res->ai_next; - } - - he->addrs = g_new0 (struct sockaddr_storage, addr_count); - he->addr_count = addr_count; - res = tempaddrinfo; - for (i = 0; ; i++) { - if (res == NULL) - break; - - if ((res->ai_family == AF_INET) || (res->ai_family == AF_INET6)) { - (he->addrs)[i] = *(struct sockaddr_storage *)(res->ai_addr); - } - - res = res->ai_next; - } - - /* We don't want the ::ffff: that could arise here */ - if (he->hostname != NULL && - strncmp (he->hostname, "::ffff:", 7) == 0) { - strcpy (he->hostname, he->hostname + 7); - } - - return he; -} - -static gboolean do_jumpback = FALSE; -static Jmp_buf signal_jumpback; -static struct sigaction oldterm, oldint, oldhup; - -static void -jumpback_sighandler (int signal) -{ - /* - * This avoids a race see Note below. - * We want to jump back only on the first - * signal invocation, even if the signal - * handler didn't return. - */ - gboolean old_do_jumpback = do_jumpback; - do_jumpback = FALSE; - - if (signal == SIGINT) - oldint.sa_handler (signal); - else if (signal == SIGTERM) - oldint.sa_handler (signal); - else if (signal == SIGHUP) - oldint.sa_handler (signal); - /* No others should be set up */ - - /* Note that we may not get here since - the SIGTERM handler in slave.c - might have in fact done the big Longjmp - to the slave's death */ - - if (old_do_jumpback) { - Longjmp (signal_jumpback, 1); - } -} - -/* - * This sets up interruptes to be proxied and the - * gethostbyname/addr to be whacked using longjmp, - * in case INT/TERM/HUP was gotten in which case - * we no longer care for the result of the - * resolution. - */ -#define SETUP_INTERRUPTS_FOR_TERM_DECLS \ - struct sigaction term; - -#define SETUP_INTERRUPTS_FOR_TERM_SETUP \ - do_jumpback = FALSE; \ - \ - term.sa_handler = jumpback_sighandler; \ - term.sa_flags = SA_RESTART; \ - sigemptyset (&term.sa_mask); \ - \ - if G_UNLIKELY (sigaction (SIGTERM, &term, &oldterm) < 0) \ - gdm_fail (_("%s: Error setting up %s signal handler: %s"), \ - "SETUP_INTERRUPTS_FOR_TERM", "TERM", strerror (errno)); \ - \ - if G_UNLIKELY (sigaction (SIGINT, &term, &oldint) < 0) \ - gdm_fail (_("%s: Error setting up %s signal handler: %s"), \ - "SETUP_INTERRUPTS_FOR_TERM", "INT", strerror (errno)); \ - \ - if G_UNLIKELY (sigaction (SIGHUP, &term, &oldhup) < 0) \ - gdm_fail (_("%s: Error setting up %s signal handler: %s"), \ - "SETUP_INTERRUPTS_FOR_TERM", "HUP", strerror (errno)); \ - -#define SETUP_INTERRUPTS_FOR_TERM_TEARDOWN \ - do_jumpback = FALSE; \ - \ - if G_UNLIKELY (sigaction (SIGTERM, &oldterm, NULL) < 0) \ - gdm_fail (_("%s: Error setting up %s signal handler: %s"), \ - "SETUP_INTERRUPTS_FOR_TERM", "TERM", strerror (errno)); \ - \ - if G_UNLIKELY (sigaction (SIGINT, &oldint, NULL) < 0) \ - gdm_fail (_("%s: Error setting up %s signal handler: %s"), \ - "SETUP_INTERRUPTS_FOR_TERM", "INT", strerror (errno)); \ - \ - if G_UNLIKELY (sigaction (SIGHUP, &oldhup, NULL) < 0) \ - gdm_fail (_("%s: Error setting up %s signal handler: %s"), \ - "SETUP_INTERRUPTS_FOR_TERM", "HUP", strerror (errno)); - -GdmHostent * -gdm_gethostbyname (const char *name) -{ - struct addrinfo hints; - /* static because of Setjmp */ - static struct addrinfo *result; - - SETUP_INTERRUPTS_FOR_TERM_DECLS - - /* The cached address */ - static GdmHostent *he = NULL; - static time_t last_time = 0; - static char *cached_hostname = NULL; - - if (cached_hostname != NULL && - strcmp (cached_hostname, name) == 0) { - /* Don't check more then every 60 seconds */ - if (last_time + 60 > time (NULL)) - return gdm_hostent_copy (he); - } - - SETUP_INTERRUPTS_FOR_TERM_SETUP - - if (Setjmp (signal_jumpback) == 0) { - do_jumpback = TRUE; - - /* Find client hostname */ - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_CANONNAME; - - if (result) { - freeaddrinfo (result); - result = NULL; - } - - getaddrinfo (name, NULL, &hints, &result); - do_jumpback = FALSE; - } else { - /* Here we got interrupted */ - result = NULL; - } - - SETUP_INTERRUPTS_FOR_TERM_TEARDOWN - - g_free (cached_hostname); - cached_hostname = g_strdup (name); - - gdm_hostent_free (he); - - he = fillout_addrinfo (result, NULL, name); - - last_time = time (NULL); - return gdm_hostent_copy (he); -} - -GdmHostent * -gdm_gethostbyaddr (struct sockaddr_storage *ia) -{ - struct addrinfo hints; - /* static because of Setjmp */ - static struct addrinfo *result = NULL; - struct sockaddr_in6 sin6; - struct sockaddr_in sin; - static struct in6_addr cached_addr6; - - SETUP_INTERRUPTS_FOR_TERM_DECLS - - /* The cached address */ - static GdmHostent *he = NULL; - static time_t last_time = 0; - static struct in_addr cached_addr; - - if (last_time != 0) { - if ((ia->ss_family == AF_INET6) && (memcmp (cached_addr6.s6_addr, ((struct sockaddr_in6 *) ia)->sin6_addr.s6_addr, sizeof (struct in6_addr)) == 0)) { - /* Don't check more then every 60 seconds */ - if (last_time + 60 > time (NULL)) - return gdm_hostent_copy (he); - } else if (ia->ss_family == AF_INET) { - if (memcmp (&cached_addr, &(((struct sockaddr_in *)ia)->sin_addr), sizeof (struct in_addr)) == 0) { - /* Don't check more then every 60 seconds */ - if (last_time + 60 > time (NULL)) - return gdm_hostent_copy (he); - } - } - } - - SETUP_INTERRUPTS_FOR_TERM_SETUP - - if (Setjmp (signal_jumpback) == 0) { - do_jumpback = TRUE; - - /* Find client hostname */ - memset (&hints, 0, sizeof (hints)); - hints.ai_socktype = SOCK_DGRAM; - hints.ai_flags = AI_CANONNAME; - - if (result) { - freeaddrinfo (result); - result = NULL; - } - - if (ia->ss_family == AF_INET6) { - char buffer6[INET6_ADDRSTRLEN]; - - inet_ntop (AF_INET6, &((struct sockaddr_in6 *)ia)->sin6_addr, buffer6, sizeof (buffer6)); - - /* - * In the case of IPv6 mapped address strip the - * ::ffff: and lookup as an IPv4 address - */ - if (strncmp (buffer6, "::ffff:", 7) == 0) { - char *temp= (buffer6 + 7); - strcpy (buffer6, temp); - } - getaddrinfo (buffer6, NULL, &hints, &result); - - } else if (ia->ss_family == AF_INET) { - char buffer[INET_ADDRSTRLEN]; - - inet_ntop (AF_INET, &((struct sockaddr_in *)ia)->sin_addr, buffer, sizeof (buffer)); - - getaddrinfo (buffer, NULL, &hints, &result); - } - - do_jumpback = FALSE; - } else { - /* Here we got interrupted */ - result = NULL; - } - - SETUP_INTERRUPTS_FOR_TERM_TEARDOWN - - if (ia->ss_family == AF_INET6) { - memcpy (cached_addr6.s6_addr, ((struct sockaddr_in6 *)ia)->sin6_addr.s6_addr, sizeof (struct in6_addr)); - memset (&sin6, 0, sizeof (sin6)); - memcpy (sin6.sin6_addr.s6_addr, cached_addr6.s6_addr, sizeof (struct in6_addr)); - sin6.sin6_family = AF_INET6; - he = fillout_addrinfo (result, (struct sockaddr *)&sin6, NULL); - } - else if (ia->ss_family == AF_INET) { - memcpy (&(cached_addr.s_addr), &(((struct sockaddr_in *)ia)->sin_addr.s_addr), sizeof (struct in_addr)); - memset (&sin, 0, sizeof (sin)); - memcpy (&sin.sin_addr, &cached_addr, sizeof (struct in_addr)); - sin.sin_family = AF_INET; - he = fillout_addrinfo (result, (struct sockaddr *)&sin, NULL); - } - - last_time = time (NULL); - return gdm_hostent_copy (he); -} - -GdmHostent * -gdm_hostent_copy (GdmHostent *he) -{ - GdmHostent *cpy; - - if (he == NULL) - return NULL; - - cpy = g_new0 (GdmHostent, 1); - cpy->not_found = he->not_found; - cpy->hostname = g_strdup (he->hostname); - if (he->addr_count == 0) { - cpy->addr_count = 0; - cpy->addrs = NULL; - } else { - cpy->addr_count = he->addr_count; - cpy->addrs = g_new0 (struct sockaddr_storage, he->addr_count); - memcpy (cpy->addrs, he->addrs, sizeof (struct sockaddr_storage) * he->addr_count); - } - return cpy; -} - -void -gdm_hostent_free (GdmHostent *he) -{ - if (he == NULL) - return; - g_free (he->hostname); - he->hostname = NULL; - - g_free (he->addrs); - he->addrs = NULL; - he->addr_count = 0; - - g_free (he); -} - -/* Like fopen with "w" */ -FILE * -gdm_safe_fopen_w (const char *file) -{ - int fd; - FILE *ret; - VE_IGNORE_EINTR (g_unlink (file)); - do { - errno = 0; - fd = open (file, O_EXCL|O_CREAT|O_TRUNC|O_WRONLY -#ifdef O_NOCTTY - |O_NOCTTY -#endif -#ifdef O_NOFOLLOW - |O_NOFOLLOW -#endif - , 0644); - } while G_UNLIKELY (errno == EINTR); - if (fd < 0) - return NULL; - VE_IGNORE_EINTR (ret = fdopen (fd, "w")); - return ret; -} - -/* Like fopen with "a+" */ -FILE * -gdm_safe_fopen_ap (const char *file) -{ - int fd; - FILE *ret; - - if (g_access (file, F_OK) == 0) { - do { - errno = 0; - fd = open (file, O_APPEND|O_RDWR -#ifdef O_NOCTTY - |O_NOCTTY -#endif -#ifdef O_NOFOLLOW - |O_NOFOLLOW -#endif - ); - } while G_UNLIKELY (errno == EINTR); - } else { - /* Doesn't exist, open with O_EXCL */ - do { - errno = 0; - fd = open (file, O_EXCL|O_CREAT|O_RDWR -#ifdef O_NOCTTY - |O_NOCTTY -#endif -#ifdef O_NOFOLLOW - |O_NOFOLLOW -#endif - , 0644); - } while G_UNLIKELY (errno == EINTR); - } - if (fd < 0) - return NULL; - VE_IGNORE_EINTR (ret = fdopen (fd, "a+")); - return ret; -} - -#ifdef RLIM_NLIMITS -#define NUM_OF_LIMITS RLIM_NLIMITS -#else /* ! RLIM_NLIMITS */ -#ifdef RLIMIT_NLIMITS -#define NUM_OF_LIMITS RLIMIT_NLIMITS -#endif /* RLIMIT_NLIMITS */ -#endif /* RLIM_NLIMITS */ - -/* If we can count limits then the reset code is simple */ -#ifdef NUM_OF_LIMITS - -static struct rlimit limits[NUM_OF_LIMITS]; - -void -gdm_get_initial_limits (void) -{ - int i; - - for (i = 0; i < NUM_OF_LIMITS; i++) { - /* Some sane defaults */ - limits[i].rlim_cur = RLIM_INFINITY; - limits[i].rlim_max = RLIM_INFINITY; - /* Get the limits */ - getrlimit (i, &(limits[i])); - } -} - -void -gdm_reset_limits (void) -{ - int i; - - for (i = 0; i < NUM_OF_LIMITS; i++) { - /* Get the limits */ - setrlimit (i, &(limits[i])); - } -} - -#define CHECK_LC(value, category) \ - (g_str_has_prefix (line->str, value "=")) \ - { \ - character = g_utf8_get_char (line->str + strlen (value "=")); \ -\ - if ((character == '\'') || (character == '\"')) \ - { \ - q = g_utf8_find_prev_char (line->str, line->str + line->len); \ -\ - if ((q == NULL) || (g_utf8_get_char (q) != character)) \ - { \ - g_string_set_size (line, 0); \ - continue; \ - } \ -\ - g_string_set_size (line, line->len - 1); \ - g_setenv (value, line->str + strlen (value "=") + 1, TRUE); \ - if (category) \ - setlocale ((category), line->str + strlen (value "=") + 1); \ - } \ - else \ - { \ - g_setenv (value, line->str + strlen (value "="), TRUE); \ - if (category) \ - setlocale ((category), line->str + strlen (value "=")); \ - } \ -\ - g_string_set_size (line, 0); \ - continue; \ - } - -void -gdm_reset_locale (void) -{ - char *i18n_file_contents; - gsize i18n_file_length, i; - GString *line; - const gchar *p, *q; - const gchar *gdmlang = g_getenv ("GDM_LANG"); - - if (gdmlang) - { - g_setenv ("LANG", gdmlang, TRUE); - g_unsetenv ("LC_ALL"); - g_unsetenv ("LC_MESSAGES"); - setlocale (LC_ALL, ""); - setlocale (LC_MESSAGES, ""); - return; - } - - i18n_file_contents = NULL; - line = NULL; - p = NULL; - if (!g_file_get_contents (LANG_CONFIG_FILE, &i18n_file_contents, - &i18n_file_length, NULL)) - goto out; - - if (!g_utf8_validate (i18n_file_contents, i18n_file_length, NULL)) - goto out; - - line = g_string_new (""); - p = i18n_file_contents; - for (i = 0; i < i18n_file_length; - p = g_utf8_next_char (p), i = p - i18n_file_contents) - { - gunichar character; - character = g_utf8_get_char (p); - - if ((character != '\n') && (character != '\0')) - { - g_string_append_unichar (line, character); - continue; - } - - if CHECK_LC("LC_ALL", LC_ALL) - else if CHECK_LC("LC_COLLATE", LC_COLLATE) - else if CHECK_LC("LC_MESSAGES", LC_MESSAGES) - else if CHECK_LC("LC_MONETARY", LC_MONETARY) - else if CHECK_LC("LC_NUMERIC", LC_NUMERIC) - else if CHECK_LC("LC_TIME", LC_TIME) - else if CHECK_LC("LANG", 0) - - g_string_set_size (line, 0); - } - - g_string_free (line, TRUE); - - setlocale (LC_ALL, ""); - - out: - g_free (i18n_file_contents); -} - -#undef CHECK_LC - -#else /* ! NUM_OF_LIMITS */ -/* We have to go one by one here */ - -#ifdef RLIMIT_CPU -static struct rlimit limit_cpu = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_DATA -static struct rlimit limit_data = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_FSIZE -static struct rlimit limit_fsize = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_LOCKS -static struct rlimit limit_locks = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_MEMLOCK -static struct rlimit limit_memlock = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_NOFILE -static struct rlimit limit_nofile = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_OFILE -static struct rlimit limit_ofile = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_NPROC -static struct rlimit limit_nproc = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_RSS -static struct rlimit limit_rss = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_STACK -static struct rlimit limit_stack = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_CORE -static struct rlimit limit_core = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_AS -static struct rlimit limit_as = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_VMEM -static struct rlimit limit_vmem = { RLIM_INFINITY, RLIM_INFINITY }; -#endif -#ifdef RLIMIT_PTHREAD -static struct rlimit limit_pthread = { RLIM_INFINITY, RLIM_INFINITY }; -#endif - -void -gdm_get_initial_limits (void) -{ - /* Note: I don't really know which ones are really very standard - and which ones are not, so I just test for them all one by one */ - -#ifdef RLIMIT_CPU - getrlimit (RLIMIT_CPU, &limit_cpu); -#endif -#ifdef RLIMIT_DATA - getrlimit (RLIMIT_DATA, &limit_data); -#endif -#ifdef RLIMIT_FSIZE - getrlimit (RLIMIT_FSIZE, &limit_fsize); -#endif -#ifdef RLIMIT_LOCKS - getrlimit (RLIMIT_LOCKS, &limit_locks); -#endif -#ifdef RLIMIT_MEMLOCK - getrlimit (RLIMIT_MEMLOCK, &limit_memlock); -#endif -#ifdef RLIMIT_NOFILE - getrlimit (RLIMIT_NOFILE, &limit_nofile); -#endif -#ifdef RLIMIT_OFILE - getrlimit (RLIMIT_OFILE, &limit_ofile); -#endif -#ifdef RLIMIT_NPROC - getrlimit (RLIMIT_NPROC, &limit_nproc); -#endif -#ifdef RLIMIT_RSS - getrlimit (RLIMIT_RSS, &limit_rss); -#endif -#ifdef RLIMIT_STACK - getrlimit (RLIMIT_STACK, &limit_stack); -#endif -#ifdef RLIMIT_CORE - getrlimit (RLIMIT_CORE, &limit_core); -#endif -#ifdef RLIMIT_AS - getrlimit (RLIMIT_AS, &limit_as); -#endif -#ifdef RLIMIT_VMEM - getrlimit (RLIMIT_VMEM, &limit_vmem); -#endif -#ifdef RLIMIT_PTHREAD - getrlimit (RLIMIT_PTHREAD, &limit_pthread); -#endif -} - -void -gdm_reset_limits (void) -{ - /* Note: I don't really know which ones are really very standard - and which ones are not, so I just test for them all one by one */ - -#ifdef RLIMIT_CPU - setrlimit (RLIMIT_CPU, &limit_cpu); -#endif -#ifdef RLIMIT_DATA - setrlimit (RLIMIT_DATA, &limit_data); -#endif -#ifdef RLIMIT_FSIZE - setrlimit (RLIMIT_FSIZE, &limit_fsize); -#endif -#ifdef RLIMIT_LOCKS - setrlimit (RLIMIT_LOCKS, &limit_locks); -#endif -#ifdef RLIMIT_MEMLOCK - setrlimit (RLIMIT_MEMLOCK, &limit_memlock); -#endif -#ifdef RLIMIT_NOFILE - setrlimit (RLIMIT_NOFILE, &limit_nofile); -#endif -#ifdef RLIMIT_OFILE - setrlimit (RLIMIT_OFILE, &limit_ofile); -#endif -#ifdef RLIMIT_NPROC - setrlimit (RLIMIT_NPROC, &limit_nproc); -#endif -#ifdef RLIMIT_RSS - setrlimit (RLIMIT_RSS, &limit_rss); -#endif -#ifdef RLIMIT_STACK - setrlimit (RLIMIT_STACK, &limit_stack); -#endif -#ifdef RLIMIT_CORE - setrlimit (RLIMIT_CORE, &limit_core); -#endif -#ifdef RLIMIT_AS - setrlimit (RLIMIT_AS, &limit_as); -#endif -#ifdef RLIMIT_VMEM - setrlimit (RLIMIT_VMEM, &limit_vmem); -#endif -#ifdef RLIMIT_PTHREAD - setrlimit (RLIMIT_PTHREAD, &limit_pthread); -#endif -} - -#endif /* NUM_OF_LIMITS */ - -const char * -gdm_root_user (void) -{ - static char *root_user = NULL; - struct passwd *pwent; - - if (root_user != NULL) - return root_user; - - pwent = getpwuid (0); - if (pwent == NULL) /* huh? */ - root_user = g_strdup ("root"); - else - root_user = g_strdup (pwent->pw_name); - return root_user; -} - -void -gdm_sleep_no_signal (int secs) -{ - time_t endtime = time (NULL)+secs; - - while (secs > 0) { - struct timeval tv; - tv.tv_sec = secs; - tv.tv_usec = 0; - select (0, NULL, NULL, NULL, &tv); - /* Don't want to use sleep since we're using alarm - for pinging */ - secs = endtime - time (NULL); - } -} - -char * -gdm_make_filename (const char *dir, const char *name, const char *extension) -{ - char *base = g_strconcat (name, extension, NULL); - char *full = g_build_filename (dir, base, NULL); - g_free (base); - return full; -} - -char * -gdm_ensure_extension (const char *name, const char *extension) -{ - const char *p; - - if (ve_string_empty (name)) - return g_strdup (name); - - p = strrchr (name, '.'); - if (p != NULL && - strcmp (p, extension) == 0) { - return g_strdup (name); - } else { - return g_strconcat (name, extension, NULL); - } -} - -char * -gdm_strip_extension (const char *name, const char *extension) -{ - const char *p = strrchr (name, '.'); - if (p != NULL && - strcmp (p, extension) == 0) { - char *r = g_strdup (name); - char *rp = strrchr (r, '.'); - *rp = '\0'; - return r; - } else { - return g_strdup (name); - } -} - -void -gdm_twiddle_pointer (GdmDisplay *disp) -{ - if (disp == NULL || - disp->dsp == NULL) - return; - - XWarpPointer (disp->dsp, - None /* src_w */, - None /* dest_w */, - 0 /* src_x */, - 0 /* src_y */, - 0 /* src_width */, - 0 /* src_height */, - 1 /* dest_x */, - 1 /* dest_y */); - XSync (disp->dsp, False); - XWarpPointer (disp->dsp, - None /* src_w */, - None /* dest_w */, - 0 /* src_x */, - 0 /* src_y */, - 0 /* src_width */, - 0 /* src_height */, - -1 /* dest_x */, - -1 /* dest_y */); - XSync (disp->dsp, False); -} - -static char * -compress_string (const char *s) -{ - GString *gs = g_string_new (NULL); - const char *p; - gboolean in_whitespace = TRUE; - - for (p = s; *p != '\0'; p++) { - if (*p == ' ' || *p == '\t') { - if ( ! in_whitespace) - g_string_append_c (gs, *p); - in_whitespace = TRUE; - } else { - g_string_append_c (gs, *p); - in_whitespace = FALSE; - } - } - - return g_string_free (gs, FALSE); -} - - -char * -gdm_get_last_info (const char *username) -{ - char *info = NULL; - const char *cmd = NULL; - - if G_LIKELY (g_access ("/usr/bin/last", X_OK) == 0) - cmd = "/usr/bin/last"; - else if (g_access ("/bin/last", X_OK) == 0) - cmd = "/bin/last"; - - if G_LIKELY (cmd != NULL) { - char *user_quoted = g_shell_quote (username); - char *newcmd; - FILE *fp; - - newcmd = g_strdup_printf ("%s %s", cmd, user_quoted); - - VE_IGNORE_EINTR (fp = popen (newcmd, "r")); - - g_free (user_quoted); - g_free (newcmd); - - if G_LIKELY (fp != NULL) { - char buf[256]; - char *r; - VE_IGNORE_EINTR (r = fgets (buf, sizeof (buf), fp)); - if G_LIKELY (r != NULL) { - char *s = compress_string (buf); - if ( ! ve_string_empty (s)) - info = g_strdup_printf (_("Last login:\n%s"), s); - g_free (s); - } - VE_IGNORE_EINTR (pclose (fp)); - } - } - - return info; -} - -gboolean -gdm_ok_console_language (void) -{ - int i; - char **v; - static gboolean cached = FALSE; - static gboolean is_ok; - const char *loc; - const char *consolecannothandle = gdm_daemon_config_get_value_string (GDM_KEY_CONSOLE_CANNOT_HANDLE); - - if (cached) - return is_ok; - - /* So far we should be paranoid, we're not set yet */ - if (consolecannothandle == NULL) - return FALSE; - - cached = TRUE; - - loc = setlocale (LC_MESSAGES, NULL); - if (loc == NULL) { - is_ok = TRUE; - return TRUE; - } - - is_ok = TRUE; - - v = g_strsplit (consolecannothandle, ",", -1); - for (i = 0; v != NULL && v[i] != NULL; i++) { - if ( ! ve_string_empty (v[i]) && - strncmp (v[i], loc, strlen (v[i])) == 0) { - is_ok = FALSE; - break; - } - } - if (v != NULL) - g_strfreev (v); - - return is_ok; -} - -const char * -gdm_console_translate (const char *str) -{ - if (gdm_ok_console_language ()) - return _(str); - else - return str; -} - -/* - * gdm_read_default - * - * This function is used to support systems that have the /etc/default/login - * interface to control programs that affect security. This is a Solaris - * thing, though some users on other systems may find it useful. - */ -gchar * -gdm_read_default (gchar *key) -{ -#ifdef HAVE_DEFOPEN - gchar *retval = NULL; - - if (defopen ("/etc/default/login") == 0) { - int flags = defcntl (DC_GETFLAGS, 0); - - TURNOFF (flags, DC_CASE); - (void) defcntl (DC_SETFLAGS, flags); /* ignore case */ - retval = g_strdup (defread (key)); - (void) defopen ((char *)NULL); - } - return retval; -#else - return NULL; -#endif -} - -/* EOF */ diff --git a/daemon/misc.h b/daemon/misc.h deleted file mode 100644 index 96a4fa56..00000000 --- a/daemon/misc.h +++ /dev/null @@ -1,175 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_MISC_H -#define GDM_MISC_H - -#include <stdio.h> -#include <sys/types.h> - -#include "gdm.h" -#include "display.h" - -void gdm_fdprintf (int fd, const gchar *format, ...) G_GNUC_PRINTF (2, 3); -int gdm_fdgetc (int fd); -char *gdm_fdgets (int fd); - -/* clear environment, but keep the i18n ones (LANG, LC_ALL, etc...), - * note that this leak memory so only use before exec */ -void gdm_clearenv_no_lang (void); - -int gdm_get_free_display (int start, uid_t server_uid); - -gboolean gdm_text_message_dialog (const char *msg); -gboolean gdm_text_yesno_dialog (const char *msg, gboolean *ret); -int gdm_exec_wait (char * const *argv, gboolean no_display, - gboolean de_setuid); - -/* done before each login. This can do so sanity ensuring, - * one of the things it does now is make sure /tmp/.ICE-unix - * exists and has the correct permissions */ -void gdm_ensure_sanity (void); - -/* This is for race free forks */ -void gdm_sigchld_block_push (void); -void gdm_sigchld_block_pop (void); -void gdm_sigterm_block_push (void); -void gdm_sigterm_block_pop (void); -void gdm_sigusr2_block_push (void); -void gdm_sigusr2_block_pop (void); - -pid_t gdm_fork_extra (void); -void gdm_wait_for_extra (pid_t pid, int *status); - -const GList * gdm_address_peek_local_list (void); -gboolean gdm_address_is_local (struct sockaddr_storage *sa); - -typedef struct { - gboolean not_found; /* hostname below set to fallback, - as gethostbyaddr/name failed */ - char *hostname; /* never a bogus dot, if - invalid/unknown, then set to the - ip address in string form */ - - struct sockaddr_storage *addrs; - int addr_count; -} GdmHostent; - -GdmHostent * gdm_gethostbyname (const char *name); - -GdmHostent *gdm_gethostbyaddr (struct sockaddr_storage *ia); -GdmHostent * gdm_hostent_copy (GdmHostent *he); -void gdm_hostent_free (GdmHostent *he); - -gboolean gdm_setup_gids (const char *login, gid_t gid); - -void gdm_desetuid (void); - -gboolean gdm_test_opt (const char *cmd, const char *help, const char *option); - -void gdm_close_all_descriptors (int from, int except, int except2); - -int gdm_open_dev_null (mode_t mode); - -void gdm_unset_signals (void); - -void gdm_saveenv (void); -const char * gdm_saved_getenv (const char *var); -/* leaks */ -void gdm_restoreenv (void); - -/* like fopen with "w" but unlinks and uses O_EXCL */ -FILE * gdm_safe_fopen_w (const char *file); -/* like fopen with "a+" and uses O_EXCL and O_NOFOLLOW */ -FILE * gdm_safe_fopen_ap (const char *file); - -/* first must get initial limits before attempting to ever reset those - limits */ -void gdm_get_initial_limits (void); -void gdm_reset_limits (void); -void gdm_reset_locale (void); - -const char *gdm_root_user (void); - -#include <setjmp.h> - -/* stolen from xdm sources */ -#if defined(X_NOT_POSIX) || defined(__EMX__) || defined(__NetBSD__) && defined(__sparc__) -#define Setjmp(e) setjmp(e) -#define Longjmp(e,v) longjmp(e,v) -#define Jmp_buf jmp_buf -#else -#define Setjmp(e) sigsetjmp(e,1) -#define Longjmp(e,v) siglongjmp(e,v) -#define Jmp_buf sigjmp_buf -#endif - -void gdm_signal_ignore (int signal); -void gdm_signal_default (int signal); - -void gdm_sleep_no_signal (int secs); - -/* somewhat like g_build_filename, but does somet hing like - * <dir> "/" <name> <extension> - */ -char * gdm_make_filename (const char *dir, const char *name, const char *extension); -char * gdm_ensure_extension (const char *name, const char *extension); -char * gdm_strip_extension (const char *name, const char *extension); - -void gdm_twiddle_pointer (GdmDisplay *disp); - -char * gdm_get_last_info (const char *username); - -gboolean gdm_ok_console_language (void); -const char * gdm_console_translate (const char *str); -/* Use with C_(N_("foo")) to make gettext work it out right */ -#define C_(x) (gdm_console_translate(x)) - -gchar * gdm_read_default (gchar *key); - -#define NEVER_FAILS_seteuid(uid) \ - { int r = 0; \ - if (geteuid () != uid) \ - r = seteuid (uid); \ - if G_UNLIKELY (r != 0) \ - gdm_fail ("GDM file %s: line %d (%s): Cannot run seteuid to %d: %s", \ - __FILE__, \ - __LINE__, \ - G_GNUC_PRETTY_FUNCTION, \ - (int)uid, \ - strerror (errno)); } -#define NEVER_FAILS_setegid(gid) \ - { int r = 0; \ - if (getegid () != gid) \ - r = setegid (gid); \ - if G_UNLIKELY (r != 0) \ - gdm_fail ("GDM file %s: line %d (%s): Cannot run setegid to %d: %s", \ - __FILE__, \ - __LINE__, \ - G_GNUC_PRETTY_FUNCTION, \ - (int)gid, \ - strerror (errno)); } - -/* first goes to euid-root and then sets the egid and euid, to make sure - * this succeeds */ -#define NEVER_FAILS_root_set_euid_egid(uid,gid) \ - { NEVER_FAILS_seteuid (0); \ - NEVER_FAILS_setegid (gid); \ - if (uid != 0) { NEVER_FAILS_seteuid (uid); } } - -#endif /* GDM_MISC_H */ diff --git a/daemon/server.c b/daemon/server.c deleted file mode 100644 index 989f9621..00000000 --- a/daemon/server.c +++ /dev/null @@ -1,1636 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* This file contains functions for controlling local X servers */ - -#include "config.h" - -#include <glib/gi18n.h> -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <fcntl.h> -#include <pwd.h> -#include <grp.h> -#include <sys/types.h> -#include <sys/resource.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/resource.h> -#include <strings.h> -#include <string.h> -#include <signal.h> -#include <errno.h> -#include <time.h> -#include <ctype.h> -#include <X11/Xlib.h> - -#include "gdm.h" -#include "server.h" -#include "misc.h" -#include "xdmcp.h" -#include "display.h" -#include "auth.h" -#include "slave.h" -#include "getvt.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -#include "gdm-socket-protocol.h" - -/* Local prototypes */ -static void gdm_server_spawn (GdmDisplay *d, const char *vtarg); -static void gdm_server_usr1_handler (gint); -static void gdm_server_child_handler (gint); -static char * get_font_path (const char *display); - -/* Global vars */ -static GdmDisplay *d = NULL; -static gboolean server_signal_notified = FALSE; -static int server_signal_pipe[2]; -static int gdm_in_signal = 0; - -static void do_server_wait (GdmDisplay *d); -static gboolean setup_server_wait (GdmDisplay *d); - -void -gdm_server_whack_lockfile (GdmDisplay *disp) -{ - char buf[256]; - - /* X seems to be sometimes broken with its lock files and - doesn't seem to remove them always, and if you manage - to get into the weird state where the old pid now - corresponds to some new pid, X will just die with - a stupid error. */ - - /* Yes there could be a race here if another X server starts - at this exact instant. Oh well such is life. Very unlikely - to happen though as we should really be the only ones - trying to start X servers, and we aren't starting an - X server on this display yet. */ - - /* if lock file exists and it is our process, whack it! */ - g_snprintf (buf, sizeof (buf), "/tmp/.X%d-lock", disp->dispnum); - VE_IGNORE_EINTR (g_unlink (buf)); - - /* whack the unix socket as well */ - g_snprintf (buf, sizeof (buf), - "/tmp/.X11-unix/X%d", disp->dispnum); - VE_IGNORE_EINTR (g_unlink (buf)); -} - - -/* Wipe cookie files */ -void -gdm_server_wipe_cookies (GdmDisplay *disp) -{ - if ( ! ve_string_empty (disp->authfile)) { - VE_IGNORE_EINTR (g_unlink (disp->authfile)); - } - g_free (disp->authfile); - disp->authfile = NULL; - if ( ! ve_string_empty (disp->authfile_gdm)) { - VE_IGNORE_EINTR (g_unlink (disp->authfile_gdm)); - } - g_free (disp->authfile_gdm); - disp->authfile_gdm = NULL; -} - -static Jmp_buf reinitjmp; - -/* ignore handlers */ -static int -ignore_xerror_handler (Display *disp, XErrorEvent *evt) -{ - return 0; -} - -static int -jumpback_xioerror_handler (Display *disp) -{ - Longjmp (reinitjmp, 1); -} - -#ifdef HAVE_FBCONSOLE -#define FBCONSOLE "/usr/openwin/bin/fbconsole" - -static void -gdm_exec_fbconsole (GdmDisplay *disp) -{ - pid_t pid; - char *argv[6]; - - argv[0] = FBCONSOLE; - argv[1] = "-d"; - argv[2] = disp->name; - argv[3] = NULL; - - g_debug ("Forking fbconsole"); - - pid = fork (); - if (pid == 0) { - gdm_close_all_descriptors (0 /* from */, -1 /* except */, -1 /* except2 */) -; - VE_IGNORE_EINTR (execv (argv[0], argv)); - } - if (pid == -1) { - gdm_error (_("Can not start fallback console")); - } -} -#endif - -/** - * gdm_server_reinit: - * @disp: Pointer to a GdmDisplay structure - * - * Reinit the display, basically sends a HUP signal - * but only if the display exists - */ - -gboolean -gdm_server_reinit (GdmDisplay *disp) -{ - if (disp == NULL) - return FALSE; - - if (disp->servpid <= 0) { - /* Kill our connection if one existed, likely to result - * in some bizzaro error right now */ - if (disp->dsp != NULL) { - XCloseDisplay (disp->dsp); - disp->dsp = NULL; - } - return FALSE; - } - - gdm_debug ("gdm_server_reinit: Server for %s is about to be reinitialized!", disp->name); - - if ( ! setup_server_wait (disp)) - return FALSE; - - d->servstat = SERVER_PENDING; - - if (disp->dsp != NULL) { - /* static because of the Setjmp */ - static int (*old_xerror_handler)(Display *, XErrorEvent *) = NULL; - static int (*old_xioerror_handler)(Display *) = NULL; - - old_xerror_handler = NULL; - old_xioerror_handler = NULL; - - /* Do note the interaction of this Setjmp and the signal - handlers and the Setjmp in slave.c */ - - /* Long live Setjmp, DIE DIE DIE XSetIOErrorHandler */ - - if (Setjmp (reinitjmp) == 0) { - /* come here and we'll whack the server and wait to get - an xio error */ - old_xerror_handler = XSetErrorHandler (ignore_xerror_handler); - old_xioerror_handler = XSetIOErrorHandler (jumpback_xioerror_handler); - - /* Now whack the server with a SIGHUP */ - gdm_sigchld_block_push (); - if (disp->servpid > 1) - kill (disp->servpid, SIGHUP); - else - d->servstat = SERVER_DEAD; - gdm_sigchld_block_pop (); - - /* the server is dead, weird */ - if (disp->dsp != NULL) { - XCloseDisplay (disp->dsp); - disp->dsp = NULL; - } - } - /* no more display */ - disp->dsp = NULL; - XSetErrorHandler (old_xerror_handler); - XSetIOErrorHandler (old_xioerror_handler); - } else { - /* Now whack the server with a SIGHUP */ - gdm_sigchld_block_push (); - if (disp->servpid > 1) - kill (disp->servpid, SIGHUP); - else - d->servstat = SERVER_DEAD; - gdm_sigchld_block_pop (); - } - - /* Wait for the SIGUSR1 */ - do_server_wait (d); - - if (d->servstat == SERVER_RUNNING) { -#ifdef HAVE_FBCONSOLE - gdm_exec_fbconsole (d); -#endif - return TRUE; - } else { - /* if something really REALLY screwed up, then whack the - lockfiles for safety */ - gdm_server_whack_lockfile (d); - return FALSE; - } -} - -/** - * gdm_server_stop: - * @disp: Pointer to a GdmDisplay structure - * - * Stops a local X server, but only if it exists - */ - -void -gdm_server_stop (GdmDisplay *disp) -{ - static gboolean waiting_for_server = FALSE; - int old_servstat; - - if (disp == NULL) - return; - - /* Kill our connection if one existed */ - if (disp->dsp != NULL) { - /* on XDMCP servers first kill everything in sight */ - if (disp->type == TYPE_XDMCP) - gdm_server_whack_clients (disp->dsp); - XCloseDisplay (disp->dsp); - disp->dsp = NULL; - } - - /* Kill our parent connection if one existed */ - if (disp->parent_dsp != NULL) { - /* on XDMCP servers first kill everything in sight */ - if (disp->type == TYPE_XDMCP_PROXY) - gdm_server_whack_clients (disp->parent_dsp); - XCloseDisplay (disp->parent_dsp); - disp->parent_dsp = NULL; - } - - if (disp->servpid <= 0) - return; - - gdm_debug ("gdm_server_stop: Server for %s going down!", disp->name); - - old_servstat = disp->servstat; - disp->servstat = SERVER_DEAD; - - if (disp->servpid > 0) { - pid_t servpid; - - gdm_debug ("gdm_server_stop: Killing server pid %d", - (int)disp->servpid); - - /* avoid SIGCHLD race */ - gdm_sigchld_block_push (); - servpid = disp->servpid; - - if (waiting_for_server) { - gdm_error ("gdm_server_stop: Some problem killing server, whacking with SIGKILL"); - if (disp->servpid > 1) - kill (disp->servpid, SIGKILL); - - } else { - if (disp->servpid > 1 && - kill (disp->servpid, SIGTERM) == 0) { - waiting_for_server = TRUE; - ve_waitpid_no_signal (disp->servpid, NULL, 0); - waiting_for_server = FALSE; - } - } - disp->servpid = 0; - - gdm_sigchld_block_pop (); - - if (old_servstat == SERVER_RUNNING) - gdm_server_whack_lockfile (disp); - - gdm_debug ("gdm_server_stop: Server pid %d dead", (int)servpid); - - /* just in case we restart again wait at least - one sec to avoid races */ - if (d->sleep_before_run < 1) - d->sleep_before_run = 1; - } - - gdm_server_wipe_cookies (disp); - - gdm_slave_whack_temp_auth_file (); -} - -static gboolean -busy_ask_user (GdmDisplay *disp) -{ - /* if we have "open" we can talk to the user */ - if (g_access (LIBEXECDIR "/gdmopen", X_OK) == 0) { - char *error = g_strdup_printf - (C_(N_("There already appears to be an X server " - "running on display %s. Should another " - "display number by tried? Answering no will " - "cause GDM to attempt starting the server " - "on %s again.%s")), - disp->name, - disp->name, -#ifdef __linux__ - C_(N_(" (You can change consoles by pressing Ctrl-Alt " - "plus a function key, such as Ctrl-Alt-F7 to go " - "to console 7. X servers usually run on consoles " - "7 and higher.)")) -#else /* ! __linux__ */ - /* no info for non linux users */ - "" -#endif /* __linux__ */ - ); - gboolean ret = TRUE; - /* default ret to TRUE */ - if ( ! gdm_text_yesno_dialog (error, &ret)) - ret = TRUE; - g_free (error); - return ret; - } else { - /* Well we'll just try another display number */ - return TRUE; - } -} - -/* Checks only output, no XFree86 v4 logfile */ -static gboolean -display_parent_no_connect (GdmDisplay *disp) -{ - char *logname = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log"); - FILE *fp; - char buf[256]; - char *getsret; - - VE_IGNORE_EINTR (fp = fopen (logname, "r")); - g_free (logname); - - if (fp == NULL) - return FALSE; - - for (;;) { - VE_IGNORE_EINTR (getsret = fgets (buf, sizeof (buf), fp)); - if (getsret == NULL) { - VE_IGNORE_EINTR (fclose (fp)); - return FALSE; - } - /* Note: this is probably XFree86 specific, and perhaps even - * version 3 specific (I don't have xfree v4 to test this), - * of course additions are welcome to make this more robust */ - if (strstr (buf, "Unable to open display \"") == buf) { - gdm_error (_("Display '%s' cannot be opened by nested display"), - ve_sure_string (disp->parent_disp)); - VE_IGNORE_EINTR (fclose (fp)); - return TRUE; - } - } -} - -static gboolean -display_busy (GdmDisplay *disp) -{ - char *logname = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log"); - FILE *fp; - char buf[256]; - char *getsret; - - VE_IGNORE_EINTR (fp = fopen (logname, "r")); - g_free (logname); - - if (fp == NULL) - return FALSE; - - for (;;) { - VE_IGNORE_EINTR (getsret = fgets (buf, sizeof (buf), fp)); - if (getsret == NULL) { - VE_IGNORE_EINTR (fclose (fp)); - return FALSE; - } - /* Note: this is probably XFree86 specific */ - if (strstr (buf, "Server is already active for display") - == buf) { - gdm_error (_("Display %s is busy. There is another " - "X server running already."), - disp->name); - VE_IGNORE_EINTR (fclose (fp)); - return TRUE; - } - } -} - -/* if we find 'Log file: "foo"' switch fp to foo and - return TRUE */ -/* Note: assumes buf is of size 256 and is writable */ -static gboolean -open_another_logfile (char buf[256], FILE **fp) -{ - if (strncmp (&buf[5], "Log file: \"", strlen ("Log file: \"")) == 0) { - FILE *ffp; - char *fname = &buf[5+strlen ("Log file: \"")]; - char *p = strchr (fname, '"'); - if (p == NULL) - return FALSE; - *p = '\0'; - VE_IGNORE_EINTR (ffp = fopen (fname, "r")); - if (ffp == NULL) - return FALSE; - VE_IGNORE_EINTR (fclose (*fp)); - *fp = ffp; - return TRUE; - } - return FALSE; -} - -static int -display_vt (GdmDisplay *disp) -{ - char *logname = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log"); - FILE *fp; - char buf[256]; - gboolean switched = FALSE; - char *getsret; - - VE_IGNORE_EINTR (fp = fopen (logname, "r")); - g_free (logname); - - if (fp == NULL) - return FALSE; - - for (;;) { - int vt; - char *p; - - VE_IGNORE_EINTR (getsret = fgets (buf, sizeof (buf), fp)); - if (getsret == NULL) { - VE_IGNORE_EINTR (fclose (fp)); - return -1; - } - - if ( ! switched && - /* this is XFree v4 specific */ - open_another_logfile (buf, &fp)) { - switched = TRUE; - continue; - } - /* Note: this is probably XFree86 specific (works with - * both v3 and v4 though */ - p = strstr (buf, "using VT number "); - if (p != NULL && - sscanf (p, "using VT number %d", &vt) == 1) { - VE_IGNORE_EINTR (fclose (fp)); - return vt; - } - } -} - -static struct sigaction old_svr_wait_chld; -static sigset_t old_svr_wait_mask; - -static gboolean -setup_server_wait (GdmDisplay *d) -{ - struct sigaction usr1, chld; - sigset_t mask; - - if (pipe (server_signal_pipe) != 0) { - gdm_error (_("%s: Error opening a pipe: %s"), - "setup_server_wait", strerror (errno)); - return FALSE; - } - server_signal_notified = FALSE; - - /* Catch USR1 from X server */ - usr1.sa_handler = gdm_server_usr1_handler; - usr1.sa_flags = SA_RESTART; - sigemptyset (&usr1.sa_mask); - - if (sigaction (SIGUSR1, &usr1, NULL) < 0) { - gdm_error (_("%s: Error setting up %s signal handler: %s"), - "gdm_server_start", "USR1", strerror (errno)); - VE_IGNORE_EINTR (close (server_signal_pipe[0])); - VE_IGNORE_EINTR (close (server_signal_pipe[1])); - return FALSE; - } - - /* Catch CHLD from X server */ - chld.sa_handler = gdm_server_child_handler; - chld.sa_flags = SA_RESTART|SA_NOCLDSTOP; - sigemptyset (&chld.sa_mask); - - if (sigaction (SIGCHLD, &chld, &old_svr_wait_chld) < 0) { - gdm_error (_("%s: Error setting up %s signal handler: %s"), - "gdm_server_start", "CHLD", strerror (errno)); - gdm_signal_ignore (SIGUSR1); - VE_IGNORE_EINTR (close (server_signal_pipe[0])); - VE_IGNORE_EINTR (close (server_signal_pipe[1])); - return FALSE; - } - - /* Set signal mask */ - sigemptyset (&mask); - sigaddset (&mask, SIGUSR1); - sigaddset (&mask, SIGCHLD); - sigprocmask (SIG_UNBLOCK, &mask, &old_svr_wait_mask); - - return TRUE; -} - -static void -do_server_wait (GdmDisplay *d) -{ - /* Wait for X server to send ready signal */ - if (d->servstat == SERVER_PENDING) { - if (d->server_uid != 0 && ! d->handled && ! d->chosen_hostname) { - /* FIXME: If not handled, we just don't know, so - * just wait a few seconds and hope things just work, - * fortunately there is no such case yet and probably - * never will, but just for code anality's sake */ - gdm_sleep_no_signal (gdm_daemon_config_get_value_int(GDM_KEY_XSERVER_TIMEOUT)); - } else if (d->server_uid != 0) { - int i; - - /* FIXME: This is not likely to work in reinit, - but we never reinit Nested servers nowdays, - so that's fine */ - - /* if we're running the server as a non-root, we can't - * use USR1 of course, so try openning the display - * as a test, but the */ - - /* just in case it's set */ - g_unsetenv ("XAUTHORITY"); - - gdm_auth_set_local_auth (d); - - for (i = 0; - d->dsp == NULL && - d->servstat == SERVER_PENDING && - i < gdm_daemon_config_get_value_int(GDM_KEY_XSERVER_TIMEOUT); - i++) { - d->dsp = XOpenDisplay (d->name); - if (d->dsp == NULL) - gdm_sleep_no_signal (1); - else - d->servstat = SERVER_RUNNING; - } - if (d->dsp == NULL && - /* Note: we could have still gotten a SIGCHLD */ - d->servstat == SERVER_PENDING) { - d->servstat = SERVER_TIMEOUT; - } - } else { - time_t t = time (NULL); - - gdm_debug ("do_server_wait: Before mainloop waiting for server"); - - do { - fd_set rfds; - struct timeval tv; - - /* Wait up to GDM_KEY_XSERVER_TIMEOUT seconds. */ - tv.tv_sec = MAX (1, gdm_daemon_config_get_value_int(GDM_KEY_XSERVER_TIMEOUT) - - (time (NULL) - t)); - tv.tv_usec = 0; - - FD_ZERO (&rfds); - FD_SET (server_signal_pipe[0], &rfds); - - if (select (server_signal_pipe[0]+1, &rfds, NULL, NULL, &tv) > 0) { - char buf[4]; - /* read the Yay! */ - VE_IGNORE_EINTR (read (server_signal_pipe[0], buf, 4)); - } - if ( ! server_signal_notified && - t + gdm_daemon_config_get_value_int(GDM_KEY_XSERVER_TIMEOUT) < time (NULL)) { - gdm_debug ("do_server_wait: Server timeout"); - d->servstat = SERVER_TIMEOUT; - server_signal_notified = TRUE; - } - if (d->servpid <= 1) { - d->servstat = SERVER_ABORT; - server_signal_notified = TRUE; - } - } while ( ! server_signal_notified); - - gdm_debug ("gdm_server_start: After mainloop waiting for server"); - } - } - - /* restore default handlers */ - gdm_signal_ignore (SIGUSR1); - sigaction (SIGCHLD, &old_svr_wait_chld, NULL); - sigprocmask (SIG_SETMASK, &old_svr_wait_mask, NULL); - - VE_IGNORE_EINTR (close (server_signal_pipe[0])); - VE_IGNORE_EINTR (close (server_signal_pipe[1])); - - if (d->servpid <= 1) { - d->servstat = SERVER_ABORT; - } - - if (d->servstat != SERVER_RUNNING) { - /* bad things are happening */ - if (d->servpid > 0) { - pid_t pid; - - d->dsp = NULL; - - gdm_sigchld_block_push (); - pid = d->servpid; - d->servpid = 0; - if (pid > 1 && - kill (pid, SIGTERM) == 0) - ve_waitpid_no_signal (pid, NULL, 0); - gdm_sigchld_block_pop (); - } - - /* We will rebake cookies anyway, so wipe these */ - gdm_server_wipe_cookies (d); - } -} - -/* We keep a connection (parent_dsp) open with the parent X server - * before running a proxy on it to prevent the X server resetting - * as we open and close other connections. - * Note that XDMCP servers, by default, reset when the seed X - * connection closes whereas usually the X server only quits when - * all X connections have closed. - */ -static gboolean -connect_to_parent (GdmDisplay *d) -{ - int maxtries; - int openretries; - - gdm_debug ("gdm_server_start: Connecting to parent display \'%s\'", - d->parent_disp); - - d->parent_dsp = NULL; - - maxtries = SERVER_IS_XDMCP (d) ? 10 : 2; - - openretries = 0; - while (openretries < maxtries && - d->parent_dsp == NULL) { - d->parent_dsp = XOpenDisplay (d->parent_disp); - - if G_UNLIKELY (d->parent_dsp == NULL) { - gdm_debug ("gdm_server_start: Sleeping %d on a retry", 1+openretries*2); - gdm_sleep_no_signal (1+openretries*2); - openretries++; - } - } - - if (d->parent_dsp == NULL) - gdm_error (_("%s: failed to connect to parent display \'%s\'"), - "gdm_server_start", d->parent_disp); - - return d->parent_dsp != NULL; -} - -/** - * gdm_server_start: - * @disp: Pointer to a GdmDisplay structure - * - * Starts a local X server. Handles retries and fatal errors properly. - */ - -gboolean -gdm_server_start (GdmDisplay *disp, - gboolean try_again_if_busy /* only affects non-flexi servers */, - gboolean treat_as_flexi, - int min_flexi_disp, - int flexi_retries) -{ - int flexi_disp = 20; - char *vtarg = NULL; - int vtfd = -1, vt = -1; - - if (disp == NULL) - return FALSE; - - d = disp; - - /* if an X server exists, wipe it */ - gdm_server_stop (d); - - /* First clear the VT number */ - if (d->type == TYPE_STATIC || - d->type == TYPE_FLEXI) { - d->vt = -1; - gdm_slave_send_num (GDM_SOP_VT_NUM, -1); - } - - if (SERVER_IS_FLEXI (d) || - treat_as_flexi) { - flexi_disp = gdm_get_free_display - (MAX (gdm_daemon_config_get_high_display_num () + 1, min_flexi_disp) /* start */, - d->server_uid /* server uid */); - - g_free (d->name); - d->name = g_strdup_printf (":%d", flexi_disp); - d->dispnum = flexi_disp; - - gdm_slave_send_num (GDM_SOP_DISP_NUM, flexi_disp); - } - - if (d->type == TYPE_XDMCP_PROXY && - ! connect_to_parent (d)) - return FALSE; - - gdm_debug ("gdm_server_start: %s", d->name); - - /* Create new cookie */ - if ( ! gdm_auth_secure_display (d)) - return FALSE; - gdm_slave_send_string (GDM_SOP_COOKIE, d->cookie); - gdm_slave_send_string (GDM_SOP_AUTHFILE, d->authfile); - g_setenv ("DISPLAY", d->name, TRUE); - - if ( ! setup_server_wait (d)) - return FALSE; - - d->servstat = SERVER_DEAD; - - if (d->type == TYPE_STATIC || - d->type == TYPE_FLEXI) { - vtarg = gdm_get_empty_vt_argument (&vtfd, &vt); - } - - /* fork X server process */ - gdm_server_spawn (d, vtarg); - - /* we can now use d->handled since that's set up above */ - do_server_wait (d); - - /* If we were holding a vt open for the server, close it now as it has - * already taken the bait. */ - if (vtfd > 0) { - VE_IGNORE_EINTR (close (vtfd)); - } - - switch (d->servstat) { - - case SERVER_TIMEOUT: - gdm_debug ("gdm_server_start: Temporary server failure (%s)", d->name); - break; - - case SERVER_ABORT: - gdm_debug ("gdm_server_start: Server %s died during startup!", d->name); - break; - - case SERVER_RUNNING: - gdm_debug ("gdm_server_start: Completed %s!", d->name); - - if (SERVER_IS_FLEXI (d)) - gdm_slave_send_num (GDM_SOP_FLEXI_OK, 0 /* bogus */); - if (d->type == TYPE_STATIC || - d->type == TYPE_FLEXI) { - if (vt >= 0) - d->vt = vt; - - if (d->vt < 0) - d->vt = display_vt (d); - if (d->vt >= 0) - gdm_slave_send_num (GDM_SOP_VT_NUM, d->vt); - } - -#ifdef HAVE_FBCONSOLE - gdm_exec_fbconsole (d); -#endif - - return TRUE; - default: - break; - } - - if (SERVER_IS_PROXY (disp) && - display_parent_no_connect (disp)) { - gdm_slave_send_num (GDM_SOP_FLEXI_ERR, - 5 /* proxy can't connect */); - _exit (DISPLAY_REMANAGE); - } - - /* if this was a busy fail, that is, there is already - * a server on that display, we'll display an error and after - * this we'll exit with DISPLAY_REMANAGE to try again if the - * user wants to, or abort this display */ - if (display_busy (disp)) { - if (SERVER_IS_FLEXI (disp) || - treat_as_flexi) { - /* for flexi displays, try again a few times with different - * display numbers */ - if (flexi_retries <= 0) { - /* Send X too busy */ - gdm_error (_("%s: Cannot find a free " - "display number"), - "gdm_server_start"); - if (SERVER_IS_FLEXI (disp)) { - gdm_slave_send_num (GDM_SOP_FLEXI_ERR, - 4 /* X too busy */); - } - /* eki eki */ - _exit (DISPLAY_REMANAGE); - } - return gdm_server_start (d, FALSE /*try_again_if_busy */, - treat_as_flexi, - flexi_disp + 1, - flexi_retries - 1); - } else { - if (try_again_if_busy) { - gdm_debug ("%s: Display %s busy. Trying once again " - "(after 2 sec delay)", - "gdm_server_start", d->name); - gdm_sleep_no_signal (2); - return gdm_server_start (d, - FALSE /* try_again_if_busy */, - treat_as_flexi, - flexi_disp, - flexi_retries); - } - if (busy_ask_user (disp)) { - gdm_error (_("%s: Display %s busy. Trying " - "another display number."), - "gdm_server_start", - d->name); - d->busy_display = TRUE; - return gdm_server_start (d, - FALSE /*try_again_if_busy */, - TRUE /* treat as flexi */, - gdm_daemon_config_get_high_display_num () + 1, - flexi_retries - 1); - } - _exit (DISPLAY_REMANAGE); - } - } - - _exit (DISPLAY_XFAILED); - - return FALSE; -} - -/* Do things that require checking the log, - * we really do need to get called a bit later, after all init is done - * as things aren't written to disk before that */ -void -gdm_server_checklog (GdmDisplay *disp) -{ - if (d->vt < 0 && - (d->type == TYPE_STATIC || - d->type == TYPE_FLEXI)) { - d->vt = display_vt (d); - if (d->vt >= 0) - gdm_slave_send_num (GDM_SOP_VT_NUM, d->vt); - } -} - -/* somewhat safer rename (safer if the log dir is unsafe), may in fact - lose the file though, it guarantees that a is gone, but not that - b exists */ -static void -safer_rename (const char *a, const char *b) -{ - errno = 0; - if (link (a, b) < 0) { - if (errno == EEXIST) { - VE_IGNORE_EINTR (g_unlink (a)); - return; - } - VE_IGNORE_EINTR (g_unlink (b)); - /* likely this system doesn't support hard links */ - g_rename (a, b); - VE_IGNORE_EINTR (g_unlink (a)); - return; - } - VE_IGNORE_EINTR (g_unlink (a)); -} - -static void -rotate_logs (const char *dname) -{ - const gchar *logdir = gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR); - - /* I'm too lazy to write a loop */ - char *fname4 = gdm_make_filename (logdir, dname, ".log.4"); - char *fname3 = gdm_make_filename (logdir, dname, ".log.3"); - char *fname2 = gdm_make_filename (logdir, dname, ".log.2"); - char *fname1 = gdm_make_filename (logdir, dname, ".log.1"); - char *fname = gdm_make_filename (logdir, dname, ".log"); - - /* Rotate the logs (keep 4 last) */ - VE_IGNORE_EINTR (g_unlink (fname4)); - safer_rename (fname3, fname4); - safer_rename (fname2, fname3); - safer_rename (fname1, fname2); - safer_rename (fname, fname1); - - g_free (fname4); - g_free (fname3); - g_free (fname2); - g_free (fname1); - g_free (fname); -} - -GdmXserver * -gdm_server_resolve (GdmDisplay *disp) -{ - char *bin; - GdmXserver *svr = NULL; - - bin = ve_first_word (disp->command); - if (bin != NULL && bin[0] != '/') { - svr = gdm_daemon_config_find_xserver (bin); - } - g_free (bin); - return svr; -} - - -static char ** -vector_merge (char * const *v1, - int len1, - char * const *v2, - int len2) -{ - int argc, i; - char **argv; - - if (v1 == NULL && v2 == NULL) - return NULL; - - argc = len1 + len2; - - argv = g_new (char *, argc + 1); - for (i = 0; i < len1; i++) - argv[i] = g_strdup (v1[i]); - for (; i < argc; i++) - argv[i] = g_strdup (v2[i - len1]); - argv[i] = NULL; - - return argv; -} - -gboolean -gdm_server_resolve_command_line (GdmDisplay *disp, - gboolean resolve_flags, - const char *vtarg, - int *argcp, - char ***argvp) -{ - char *bin; - int argc; - char **argv; - int len; - int i; - gboolean gotvtarg = FALSE; - gboolean query_in_arglist = FALSE; - - argv = NULL; - - bin = ve_first_word (disp->command); - if (bin == NULL) { - const char *str; - - gdm_error (_("Invalid server command '%s'"), disp->command); - str = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER); - g_shell_parse_argv (str, &argc, &argv, NULL); - } else if (bin[0] != '/') { - GdmXserver *svr = gdm_daemon_config_find_xserver (bin); - if (svr == NULL) { - const char *str; - - gdm_error (_("Server name '%s' not found; " - "using standard server"), bin); - str = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER); - g_shell_parse_argv (str, &argc, &argv, NULL); - - } else { - char **svr_command; - const char *str; - int svr_argc; - - str = ve_sure_string (svr->command); - svr_command = NULL; - g_shell_parse_argv (str, &svr_argc, &svr_command, NULL); - - g_shell_parse_argv (disp->command, &argc, &argv, NULL); - - if (argv[0] == NULL || argv[1] == NULL) { - g_strfreev (argv); - argv = svr_command; - argc = svr_argc; - } else { - char **old_argv = argv; - argv = vector_merge (svr_command, - svr_argc, - &old_argv[1], - argc); - g_strfreev (svr_command); - g_strfreev (old_argv); - - argc += svr_argc; - } - - if (resolve_flags) { - /* Setup the handled function */ - disp->handled = svr->handled; - /* never make use_chooser FALSE, - it may have been set temporarily for - us by the master */ - if (svr->chooser) - disp->use_chooser = TRUE; - disp->priority = svr->priority; - } - } - } else { - g_shell_parse_argv (disp->command, &argc, &argv, NULL); - } - - for (len = 0; argv != NULL && argv[len] != NULL; len++) { - char *arg = argv[len]; - /* HACK! Not to add vt argument to servers that already force - * allocation. Mostly for backwards compat only */ - if (strncmp (arg, "vt", 2) == 0 && - isdigit (arg[2]) && - (arg[3] == '\0' || - (isdigit (arg[3]) && arg[4] == '\0'))) - gotvtarg = TRUE; - if (strcmp (arg, "-query") == 0 || - strcmp (arg, "-indirect") == 0) - query_in_arglist = TRUE; - } - - argv = g_renew (char *, argv, len + 10); - /* shift args down one */ - for (i = len - 1; i >= 1; i--) { - argv[i+1] = argv[i]; - } - /* server number is the FIRST argument, before any others */ - argv[1] = g_strdup (disp->name); - len++; - - if (disp->authfile != NULL) { - argv[len++] = g_strdup ("-auth"); - argv[len++] = g_strdup (disp->authfile); - } - - if (resolve_flags && disp->chosen_hostname) { - /* this display is NOT handled */ - disp->handled = FALSE; - /* never ever ever use chooser here */ - disp->use_chooser = FALSE; - disp->priority = 0; - /* run just one session */ - argv[len++] = g_strdup ("-terminate"); - argv[len++] = g_strdup ("-query"); - argv[len++] = g_strdup (disp->chosen_hostname); - query_in_arglist = TRUE; - } - - if (resolve_flags && gdm_daemon_config_get_value_bool (GDM_KEY_DISALLOW_TCP) && ! query_in_arglist) { - argv[len++] = g_strdup ("-nolisten"); - argv[len++] = g_strdup ("tcp"); - d->tcp_disallowed = TRUE; - } - - if (vtarg != NULL && - ! gotvtarg) { - argv[len++] = g_strdup (vtarg); - } - - argv[len++] = NULL; - - *argvp = argv; - *argcp = len; - - g_free (bin); - - return TRUE; -} - -/** - * gdm_server_spawn: - * @disp: Pointer to a GdmDisplay structure - * - * forks an actual X server process - * - * Note that we can only use d->handled once we call this function - * since otherwise the server might not yet be looked up yet. - */ - -static void -gdm_server_spawn (GdmDisplay *d, const char *vtarg) -{ - struct sigaction ign_signal; - sigset_t mask; - int argc; - gchar **argv = NULL; - char *logfile; - int logfd; - char *command; - pid_t pid; - - if (d == NULL || - ve_string_empty (d->command)) { - return; - } - - d->servstat = SERVER_PENDING; - - gdm_sigchld_block_push (); - - /* eek, some previous copy, just wipe it */ - if (d->servpid > 0) { - pid_t pid = d->servpid; - d->servpid = 0; - if (pid > 1 && - kill (pid, SIGTERM) == 0) - ve_waitpid_no_signal (pid, NULL, 0); - } - - /* Figure out the server command */ - argv = NULL; - argc = 0; - gdm_server_resolve_command_line (d, - TRUE /* resolve flags */, - vtarg, - &argc, - &argv); - - command = g_strjoinv (" ", argv); - - /* Fork into two processes. Parent remains the gdm process. Child - * becomes the X server. */ - - g_debug ("Forking X server process"); - - gdm_sigterm_block_push (); - pid = d->servpid = fork (); - if (pid == 0) - gdm_unset_signals (); - gdm_sigterm_block_pop (); - gdm_sigchld_block_pop (); - - switch (pid) { - - case 0: - /* the pops whacked mask again */ - gdm_unset_signals (); - - gdm_log_shutdown (); - - /* close things */ - gdm_close_all_descriptors (0 /* from */, -1 /* except */, -1 /* except2 */); - - /* No error checking here - if it's messed the best response - * is to ignore & try to continue */ - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - gdm_log_init (); - - /* Rotate the X server logs */ - rotate_logs (d->name); - - /* Log all output from spawned programs to a file */ - logfile = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log"); - VE_IGNORE_EINTR (g_unlink (logfile)); - VE_IGNORE_EINTR (logfd = open (logfile, O_CREAT|O_TRUNC|O_WRONLY|O_EXCL, 0644)); - - if (logfd != -1) { - VE_IGNORE_EINTR (dup2 (logfd, 1)); - VE_IGNORE_EINTR (dup2 (logfd, 2)); - close (logfd); - } else { - gdm_error (_("%s: Could not open logfile for display %s!"), - "gdm_server_spawn", d->name); - } - - /* The X server expects USR1/TTIN/TTOU to be SIG_IGN */ - ign_signal.sa_handler = SIG_IGN; - ign_signal.sa_flags = SA_RESTART; - sigemptyset (&ign_signal.sa_mask); - - if (d->server_uid == 0) { - /* only set this if we can actually listen */ - if (sigaction (SIGUSR1, &ign_signal, NULL) < 0) { - gdm_error (_("%s: Error setting %s to %s"), - "gdm_server_spawn", "USR1", "SIG_IGN"); - _exit (SERVER_ABORT); - } - } - if (sigaction (SIGTTIN, &ign_signal, NULL) < 0) { - gdm_error (_("%s: Error setting %s to %s"), - "gdm_server_spawn", "TTIN", "SIG_IGN"); - _exit (SERVER_ABORT); - } - if (sigaction (SIGTTOU, &ign_signal, NULL) < 0) { - gdm_error (_("%s: Error setting %s to %s"), - "gdm_server_spawn", "TTOU", "SIG_IGN"); - _exit (SERVER_ABORT); - } - - /* And HUP and TERM are at SIG_DFL from gdm_unset_signals, - we also have an empty mask and all that fun stuff */ - - /* unblock signals (especially HUP/TERM/USR1) so that we - * can control the X server */ - sigemptyset (&mask); - sigprocmask (SIG_SETMASK, &mask, NULL); - - if (SERVER_IS_PROXY (d)) { - gboolean add_display = TRUE; - - g_unsetenv ("DISPLAY"); - if (d->parent_auth_file != NULL) - g_setenv ("XAUTHORITY", d->parent_auth_file, TRUE); - else - g_unsetenv ("XAUTHORITY"); - - if (d->type == TYPE_FLEXI_XNEST) { - char *font_path = NULL; - /* Add -fp with the current font path, but only if not - * already among the arguments */ - if (strstr (command, "-fp") == NULL) - font_path = get_font_path (d->parent_disp); - if (font_path != NULL) { - argv = g_renew (char *, argv, argc + 2); - argv[argc++] = "-fp"; - argv[argc++] = font_path; - command = g_strconcat (command, " -fp ", - font_path, NULL); - } - add_display = FALSE; - } - - /* - * Set the DISPLAY environment variable when calling - * nested server since some Xnest commands like Xephyr - * do not support the -display argument. - */ - if (add_display == TRUE) { - argv = g_renew (char *, argv, argc + 3); - argv[argc++] = "-display"; - argv[argc++] = d->parent_disp; - argv[argc++] = NULL; - command = g_strconcat (command, " -display ", - d->parent_disp, NULL); - } else { - argv = g_renew (char *, argv, argc + 1); - argv[argc++] = NULL; - g_setenv ("DISPLAY", d->parent_disp, TRUE); - } - } - - if (argv[0] == NULL) { - gdm_error (_("%s: Empty server command for display %s"), - "gdm_server_spawn", - d->name); - _exit (SERVER_ABORT); - } - - gdm_debug ("gdm_server_spawn: '%s'", command); - - if (d->priority != 0) { - if (setpriority (PRIO_PROCESS, 0, d->priority)) { - gdm_error (_("%s: Server priority couldn't be set to %d: %s"), - "gdm_server_spawn", d->priority, - strerror (errno)); - } - } - - setpgid (0, 0); - - if (d->server_uid != 0) { - struct passwd *pwent; - pwent = getpwuid (d->server_uid); - if (pwent == NULL) { - gdm_error (_("%s: Server was to be spawned by uid %d but " - "that user doesn't exist"), - "gdm_server_spawn", - (int)d->server_uid); - _exit (SERVER_ABORT); - } - if (pwent->pw_dir != NULL && - g_file_test (pwent->pw_dir, G_FILE_TEST_EXISTS)) - g_setenv ("HOME", pwent->pw_dir, TRUE); - else - g_setenv ("HOME", "/", TRUE); /* Hack */ - g_setenv ("SHELL", pwent->pw_shell, TRUE); - g_unsetenv ("MAIL"); - - if (setgid (pwent->pw_gid) < 0) { - gdm_error (_("%s: Couldn't set groupid to %d"), - "gdm_server_spawn", (int)pwent->pw_gid); - _exit (SERVER_ABORT); - } - - if (initgroups (pwent->pw_name, pwent->pw_gid) < 0) { - gdm_error (_("%s: initgroups () failed for %s"), - "gdm_server_spawn", pwent->pw_name); - _exit (SERVER_ABORT); - } - - if (setuid (d->server_uid) < 0) { - gdm_error (_("%s: Couldn't set userid to %d"), - "gdm_server_spawn", (int)d->server_uid); - _exit (SERVER_ABORT); - } - } else { - gid_t groups[1] = { 0 }; - if (setgid (0) < 0) { - gdm_error (_("%s: Couldn't set groupid to 0"), - "gdm_server_spawn"); - /* Don't error out, it's not fatal, if it fails we'll - * just still be */ - } - /* this will get rid of any suplementary groups etc... */ - setgroups (1, groups); - } - -#if sun - { - /* Remove old communication pipe, if present */ - char old_pipe[MAXPATHLEN]; - - sprintf (old_pipe, "%s/%d", SDTLOGIN_DIR, d->name); - g_unlink (old_pipe); - } -#endif - - VE_IGNORE_EINTR (execv (argv[0], argv)); - - gdm_fdprintf (2, "GDM: Xserver not found: %s\n" - "Error: Command could not be executed!\n" - "Please install the X server or correct " - "GDM configuration and restart GDM.", - command); - - gdm_error (_("%s: Xserver not found: %s"), - "gdm_server_spawn", command); - - _exit (SERVER_ABORT); - - case -1: - g_strfreev (argv); - g_free (command); - gdm_error (_("%s: Can't fork Xserver process!"), - "gdm_server_spawn"); - d->servpid = 0; - d->servstat = SERVER_DEAD; - - break; - - default: - g_strfreev (argv); - g_free (command); - gdm_debug ("%s: Forked server on pid %d", - "gdm_server_spawn", (int)pid); - break; - } -} - -/** - * gdm_server_usr1_handler: - * @sig: Signal value - * - * Received when the server is ready to accept connections - */ - -static void -gdm_server_usr1_handler (gint sig) -{ - gdm_in_signal++; - - d->servstat = SERVER_RUNNING; /* Server ready to accept connections */ - d->starttime = time (NULL); - - server_signal_notified = TRUE; - /* this will quit the select */ - VE_IGNORE_EINTR (write (server_signal_pipe[1], "Yay!", 4)); - - gdm_in_signal--; -} - - -/** - * gdm_server_child_handler: - * @sig: Signal value - * - * Received when server died during startup - */ - -static void -gdm_server_child_handler (int signal) -{ - gdm_in_signal++; - - /* go to the main child handler */ - gdm_slave_child_handler (signal); - - /* this will quit the select */ - VE_IGNORE_EINTR (write (server_signal_pipe[1], "Yay!", 4)); - - gdm_in_signal--; -} - - -/** - * gdm_server_alloc: - * @id: Local display number - * @command: Command line for starting the X server - * - * Allocate display structure for a local X server - */ - -GdmDisplay * -gdm_server_alloc (gint id, const gchar *command) -{ - gchar hostname[1024]; - GdmDisplay *d; - - hostname[1023] = '\0'; - if (gethostname (hostname, 1023) == -1) - strcpy (hostname, "localhost.localdomain"); - - d = g_new0 (GdmDisplay, 1); - - d->logout_action = GDM_LOGOUT_ACTION_NONE; - - d->authfile = NULL; - d->authfile_gdm = NULL; - d->auths = NULL; - d->userauth = NULL; - d->command = g_strdup (command); - d->cookie = NULL; - d->dispstat = DISPLAY_UNBORN; - d->greetpid = 0; - d->name = g_strdup_printf (":%d", id); - d->hostname = g_strdup (hostname); - /* Not really used for not XDMCP */ - memset (&(d->addr), 0, sizeof (d->addr)); - d->dispnum = id; - d->servpid = 0; - d->servstat = SERVER_DEAD; - d->sesspid = 0; - d->slavepid = 0; - d->type = TYPE_STATIC; - d->attached = TRUE; - d->sessionid = 0; - d->acctime = 0; - d->dsp = NULL; - d->screenx = 0; /* xinerama offset */ - d->screeny = 0; - - d->handled = TRUE; - d->tcp_disallowed = FALSE; - - d->priority = 0; - d->vt = -1; - - d->x_servers_order = -1; - - d->last_loop_start_time = 0; - d->last_start_time = 0; - d->retry_count = 0; - d->sleep_before_run = 0; - d->login = NULL; - d->preset_user = NULL; - - d->timed_login_ok = FALSE; - - d->slave_notify_fd = -1; - d->master_notify_fd = -1; - - d->xsession_errors_bytes = 0; - d->xsession_errors_fd = -1; - d->session_output_fd = -1; - - d->chooser_output_fd = -1; - d->chooser_last_line = NULL; - - d->theme_name = NULL; - - return d; -} - -void -gdm_server_whack_clients (Display *dsp) -{ - int i, screen_count; - int (* old_xerror_handler) (Display *, XErrorEvent *); - - if (dsp == NULL) - return; - - old_xerror_handler = XSetErrorHandler (ignore_xerror_handler); - - XGrabServer (dsp); - - screen_count = ScreenCount (dsp); - - for (i = 0; i < screen_count; i++) { - Window root_ret, parent_ret; - Window *childs = NULL; - unsigned int childs_count = 0; - Window root = RootWindow (dsp, i); - - while (XQueryTree (dsp, root, &root_ret, &parent_ret, - &childs, &childs_count) && - childs_count > 0) { - int ii; - - for (ii = 0; ii < childs_count; ii++) { - XKillClient (dsp, childs[ii]); - } - - XFree (childs); - } - } - - XUngrabServer (dsp); - - XSync (dsp, False); - XSetErrorHandler (old_xerror_handler); -} - -static char * -get_font_path (const char *display) -{ - Display *disp; - char **font_path; - int n_fonts; - int i; - GString *gs; - - disp = XOpenDisplay (display); - if (disp == NULL) - return NULL; - - font_path = XGetFontPath (disp, &n_fonts); - if (font_path == NULL) { - XCloseDisplay (disp); - return NULL; - } - - gs = g_string_new (NULL); - for (i = 0; i < n_fonts; i++) { - if (i != 0) - g_string_append_c (gs, ','); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_XNEST_UNSCALED_FONT_PATH) == TRUE) - g_string_append (gs, font_path[i]); - else { - gchar *unscaled_ptr = NULL; - - /* - * When using Xsun Xnest, it doesn't support the - * ":unscaled" suffix in fontpath entries, so strip it. - */ - unscaled_ptr = g_strrstr (font_path[i], ":unscaled"); - if (unscaled_ptr != NULL) { - gchar *temp_string; - - temp_string = g_strndup (font_path[i], - strlen (font_path[i]) - - strlen (":unscaled")); - -gdm_debug ("font_path[i] is %s, temp_string is %s", font_path[i], temp_string); - g_string_append (gs, temp_string); - g_free (temp_string); - } else { -gdm_debug ("font_path[i] is %s", font_path[i]); - g_string_append (gs, font_path[i]); - } - } - } - - XFreeFontPath (font_path); - - XCloseDisplay (disp); - - return g_string_free (gs, FALSE); -} - -/* EOF */ diff --git a/daemon/server.h b/daemon/server.h deleted file mode 100644 index 1b753486..00000000 --- a/daemon/server.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_SERVER_H -#define GDM_SERVER_H - -#include "display.h" - -typedef struct _GdmXserver GdmXserver; - -struct _GdmXserver -{ - char *id; - char *name; - char *command; - gboolean flexible; - gboolean choosable; /* not implemented yet */ - gboolean chooser; /* instead of greeter, run chooser */ - gboolean handled; - int number; - int priority; -}; - -/* These are the servstat values, also used as server - * process exit codes */ -#define SERVER_TIMEOUT 2 /* Server didn't start */ -#define SERVER_DEAD 250 /* Server stopped */ -#define SERVER_PENDING 251 /* Server started but not ready for connections yet */ -#define SERVER_RUNNING 252 /* Server running and ready for connections */ -#define SERVER_ABORT 253 /* Server failed badly. Suspending display. */ - -/* Wipe cookie files */ -void gdm_server_wipe_cookies (GdmDisplay *disp); - -/* Wipe X server's butt */ -void gdm_server_whack_lockfile (GdmDisplay *disp); - -gboolean gdm_server_start (GdmDisplay *d, - gboolean try_again_if_busy, - gboolean treat_as_flexi, - int min_flexi_disp, - int flexi_retries); -void gdm_server_stop (GdmDisplay *d); -gboolean gdm_server_reinit (GdmDisplay *d); -GdmDisplay * gdm_server_alloc (gint id, - const gchar *command); -void gdm_server_whack_clients (Display *dsp); -void gdm_server_checklog (GdmDisplay *disp); - -gboolean gdm_server_resolve_command_line (GdmDisplay *disp, - gboolean resolve_flags, - const char *vtarg, - int *argc, - char ***argv); -GdmXserver * gdm_server_resolve (GdmDisplay *disp); - - - -#endif /* GDM_SERVER_H */ - -/* EOF */ diff --git a/daemon/slave.c b/daemon/slave.c deleted file mode 100644 index da3b876b..00000000 --- a/daemon/slave.c +++ /dev/null @@ -1,5917 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* This is the gdm slave process. gdmslave runs the chooser, greeter - * and the user's session scripts. */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <dirent.h> -#include <unistd.h> -#include <utime.h> -#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD) -#include <sched.h> -#endif -#ifdef HAVE_LOGINCAP -#include <login_cap.h> -#endif -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <strings.h> -#include <netinet/in.h> -#include <netdb.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <string.h> - -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#ifdef HAVE_XFREE_XINERAMA -#include <X11/extensions/Xinerama.h> -#elif HAVE_SOLARIS_XINERAMA -#include <X11/extensions/xinerama.h> -#endif - -#if defined (CAN_USE_SETPENV) && defined (HAVE_USERSEC_H) -#include <usersec.h> -#endif - -#include <signal.h> -#include <pwd.h> -#include <grp.h> -#include <errno.h> -#include <time.h> - -#ifdef HAVE_TSOL -#include <user_attr.h> -#endif - -#ifdef HAVE_SELINUX -#include <selinux/selinux.h> -#include <selinux/get_context_list.h> -#endif /* HAVE_SELINUX */ - -#include <glib/gi18n.h> -#include <gdk/gdkx.h> -#include <gtk/gtk.h> - -#include "gdm.h" -#include "slave.h" -#include "misc.h" -#include "verify.h" -#include "filecheck.h" -#include "auth.h" -#include "server.h" -#include "choose.h" -#include "getvt.h" -#include "errorgui.h" -#include "cookie.h" -#include "display.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -#include "gdm-socket-protocol.h" - -#ifdef WITH_CONSOLE_KIT -#include "gdmconsolekit.h" -#endif - -/* Some per slave globals */ -static GdmDisplay *d = 0; -static gchar *login = NULL; -static gboolean greet = FALSE; -static gboolean configurator = FALSE; -static gboolean remanage_asap = FALSE; -static gboolean got_xfsz_signal = FALSE; -static gboolean do_timed_login = FALSE; /* if this is true, - login the timed login */ -static gboolean do_configurator = FALSE; /* if this is true, login as root - * and start the configurator */ -static gboolean do_cancel = FALSE; /* if this is true, go back to - username entry & unselect face - browser (if present) */ -static gboolean do_restart_greeter = FALSE; /* if this is true, whack the - greeter and try again */ -static gboolean restart_greeter_now = FALSE; /* restart_greeter_when the - SIGCHLD hits */ -static gboolean always_restart_greeter = FALSE; /* Always restart greeter when - the user accepts restarts. */ -static gboolean gdm_wait_for_ack = TRUE; /* wait for ack on all messages to - * the daemon */ -static int in_session_stop = 0; -static int in_usr2_signal = 0; -static gboolean need_to_quit_after_session_stop = FALSE; -static int exit_code_to_use = DISPLAY_REMANAGE; -static gboolean session_started = FALSE; -static gboolean greeter_disabled = FALSE; -static gboolean greeter_no_focus = FALSE; - -static uid_t logged_in_uid = -1; -static gid_t logged_in_gid = -1; - -static gboolean interrupted = FALSE; -static gchar *ParsedAutomaticLogin = NULL; -static gchar *ParsedTimedLogin = NULL; - -static int greeter_fd_out = -1; -static int greeter_fd_in = -1; - -static int gdm_in_signal = 0; -static int gdm_normal_runlevel = -1; -static pid_t extra_process = 0; -static int extra_status = 0; - -#ifdef HAVE_TSOL -static gboolean have_suntsol_extension = FALSE; -#endif - -typedef struct { - pid_t pid; -} GdmWaitPid; - -static int slave_waitpid_r = -1; -static int slave_waitpid_w = -1; -static GSList *slave_waitpids = NULL; - -extern gboolean gdm_first_login; - -/* The slavepipe (like fifo) connection, this is the write end */ -extern int slave_fifo_pipe_fd; - -/* wait for a GO in the SOP protocol */ -extern gboolean gdm_wait_for_go; - -/* Local prototypes */ -static gint gdm_slave_xerror_handler (Display *disp, XErrorEvent *evt); -static gint gdm_slave_xioerror_handler (Display *disp); -static void gdm_slave_run (GdmDisplay *display); -static void gdm_slave_wait_for_login (void); -static void gdm_slave_greeter (void); -static void gdm_slave_chooser (void); -static void gdm_slave_session_start (void); -static void gdm_slave_session_stop (gboolean run_post_session, - gboolean no_shutdown_check); -static void gdm_slave_alrm_handler (int sig); -static void gdm_slave_term_handler (int sig); -static void gdm_slave_usr2_handler (int sig); -static void gdm_slave_quick_exit (gint status); -static void gdm_slave_exit (gint status, const gchar *format, ...) G_GNUC_PRINTF (2, 3); -static void gdm_child_exit (gint status, const gchar *format, ...) G_GNUC_PRINTF (2, 3); -static gint gdm_slave_exec_script (GdmDisplay *d, const gchar *dir, - const char *login, struct passwd *pwent, - gboolean pass_stdout); -static gchar *gdm_parse_enriched_login (const gchar *s, GdmDisplay *display); -static void gdm_slave_handle_usr2_message (void); -static void gdm_slave_handle_notify (const char *msg); -static void create_temp_auth_file (void); -static void set_xnest_parent_stuff (void); -static void check_notifies_now (void); -static void restart_the_greeter (void); - -#ifdef HAVE_TSOL -static gboolean gdm_can_i_assume_root_role (struct passwd *pwent); -#endif - -gboolean gdm_is_user_valid (const char *username); - -/* Yay thread unsafety */ -static gboolean x_error_occurred = FALSE; -static gboolean gdm_got_ack = FALSE; -static char * gdm_ack_response = NULL; -char * gdm_ack_question_response = NULL; -static GList *unhandled_notifies = NULL; - -/* for signals that want to exit */ -static Jmp_buf slave_start_jmp; -static gboolean return_to_slave_start_jmp = FALSE; -static gboolean already_in_slave_start_jmp = FALSE; -static char *slave_start_jmp_error_to_print = NULL; -enum { - JMP_FIRST_RUN = 0, - JMP_SESSION_STOP_AND_QUIT = 1, - JMP_JUST_QUIT_QUICKLY = 2 -}; -#define DEFAULT_LANGUAGE "Default" -#define SIGNAL_EXIT_WITH_JMP(d,how) \ - { \ - if ((d)->slavepid == getpid () && return_to_slave_start_jmp) { \ - already_in_slave_start_jmp = TRUE; \ - Longjmp (slave_start_jmp, how); \ - } else { \ - /* evil! how this this happen */ \ - if (slave_start_jmp_error_to_print != NULL) \ - gdm_error (slave_start_jmp_error_to_print); \ - gdm_error ("Bad (very very VERY bad!) things happening in signal"); \ - _exit (DISPLAY_REMANAGE); \ - } \ - } - -/* Notify all waitpids, make waitpids check notifies */ -static void -slave_waitpid_notify (void) -{ - /* we're in no slave waitpids */ - if (slave_waitpids == NULL) - return; - - gdm_sigchld_block_push (); - - if (slave_waitpid_w >= 0) - VE_IGNORE_EINTR (write (slave_waitpid_w, "N", 1)); - - gdm_sigchld_block_pop (); -} - -/* Make sure to wrap this call with sigchld blocks */ -static GdmWaitPid * -slave_waitpid_setpid (pid_t pid) -{ - int p[2]; - GdmWaitPid *wp; - - if G_UNLIKELY (pid <= 1) - return NULL; - - wp = g_new0 (GdmWaitPid, 1); - wp->pid = pid; - - if (slave_waitpid_r < 0) { - if G_UNLIKELY (pipe (p) < 0) { - gdm_error ("slave_waitpid_setpid: cannot create pipe, trying to wing it"); - } else { - slave_waitpid_r = p[0]; - slave_waitpid_w = p[1]; - } - } - - slave_waitpids = g_slist_prepend (slave_waitpids, wp); - return wp; -} - -static void -run_session_output (gboolean read_until_eof) -{ - char buf[256]; - int r, written; - uid_t old; - gid_t oldg; - - old = geteuid (); - oldg = getegid (); - - /* make sure we can set the gid */ - NEVER_FAILS_seteuid (0); - - /* make sure we are the user when we do this, - for purposes of file limits and all that kind of - stuff */ - if G_LIKELY (logged_in_gid >= 0) { - if G_UNLIKELY (setegid (logged_in_gid) != 0) { - gdm_error (_("Can't set EGID to user GID")); - NEVER_FAILS_root_set_euid_egid (old, oldg); - return; - } - } - - if G_LIKELY (logged_in_uid >= 0) { - if G_UNLIKELY (seteuid (logged_in_uid) != 0) { - gdm_error (_("Can't set EUID to user UID")); - NEVER_FAILS_root_set_euid_egid (old, oldg); - return; - } - } - - /* the fd is non-blocking */ - for (;;) { - VE_IGNORE_EINTR (r = read (d->session_output_fd, buf, sizeof (buf))); - - /* EOF */ - if G_UNLIKELY (r == 0) { - VE_IGNORE_EINTR (close (d->session_output_fd)); - d->session_output_fd = -1; - VE_IGNORE_EINTR (close (d->xsession_errors_fd)); - d->xsession_errors_fd = -1; - break; - } - - /* Nothing to read */ - if (r < 0 && errno == EAGAIN) - break; - - /* some evil error */ - if G_UNLIKELY (r < 0) { - gdm_error ("error reading from session output, closing the pipe"); - VE_IGNORE_EINTR (close (d->session_output_fd)); - d->session_output_fd = -1; - VE_IGNORE_EINTR (close (d->xsession_errors_fd)); - d->xsession_errors_fd = -1; - break; - } - - if G_UNLIKELY (d->xsession_errors_bytes >= MAX_XSESSION_ERRORS_BYTES || - got_xfsz_signal) - continue; - - /* write until we succeed in writing something */ - VE_IGNORE_EINTR (written = write (d->xsession_errors_fd, buf, r)); - if G_UNLIKELY (written < 0 || got_xfsz_signal) { - /* evil! */ - break; - } - - /* write until we succeed in writing everything */ - while G_UNLIKELY (written < r) { - int n; - VE_IGNORE_EINTR (n = write (d->xsession_errors_fd, &buf[written], r-written)); - if G_UNLIKELY (n < 0 || got_xfsz_signal) { - /* evil! */ - break; - } - written += n; - } - - d->xsession_errors_bytes += r; - - if G_UNLIKELY (d->xsession_errors_bytes >= MAX_XSESSION_ERRORS_BYTES && - ! got_xfsz_signal) { - VE_IGNORE_EINTR (write (d->xsession_errors_fd, - "\n...Too much output, ignoring rest...\n", - strlen ("\n...Too much output, ignoring rest...\n"))); - } - - /* there wasn't more then buf available, so no need to try reading - * again, unless we really want to */ - if (r < sizeof (buf) && ! read_until_eof) - break; - } - - NEVER_FAILS_root_set_euid_egid (old, oldg); -} - -static void -run_chooser_output (void) -{ - char *bf; - - if G_UNLIKELY (d->chooser_output_fd < 0) - return; - - /* the fd is non-blocking */ - do { - bf = gdm_fdgets (d->chooser_output_fd); - if (bf != NULL) { - g_free (d->chooser_last_line); - d->chooser_last_line = bf; - } - } while (bf != NULL); -} - -#define TIME_UNSET_P(tv) ((tv)->tv_sec == 0 && (tv)->tv_usec == 0) - -/* Try to touch an authfb auth file every 12 hours. That way if it's - * in /tmp it doesn't get whacked by tmpwatch */ -#define TRY_TO_TOUCH_TIME (60*60*12) - -static struct timeval * -min_time_to_wait (struct timeval *tv) -{ - if (d->authfb) { - time_t ct = time (NULL); - time_t sec_to_wait; - - if (d->last_auth_touch + TRY_TO_TOUCH_TIME + 5 <= ct) - sec_to_wait = 5; - else - sec_to_wait = (d->last_auth_touch + TRY_TO_TOUCH_TIME) - ct; - - if (TIME_UNSET_P (tv) || - sec_to_wait < tv->tv_sec) - tv->tv_sec = sec_to_wait; - } - if (TIME_UNSET_P (tv)) - return NULL; - else - return tv; -} - -static void -try_to_touch_fb_userauth (void) -{ - if (d->authfb && d->userauth != NULL && logged_in_uid >= 0) { - time_t ct = time (NULL); - - if (d->last_auth_touch + TRY_TO_TOUCH_TIME <= ct) { - uid_t old; - gid_t oldg; - - old = geteuid (); - oldg = getegid (); - - NEVER_FAILS_seteuid (0); - - /* make sure we are the user when we do this, - for purposes of file limits and all that kind of - stuff */ - if G_LIKELY (logged_in_gid >= 0) { - if G_UNLIKELY (setegid (logged_in_gid) != 0) { - gdm_error ("Can't set GID to user GID"); - NEVER_FAILS_root_set_euid_egid (old, oldg); - return; - } - } - - if G_LIKELY (logged_in_uid >= 0) { - if G_UNLIKELY (seteuid (logged_in_uid) != 0) { - gdm_error ("Can't set UID to user UID"); - NEVER_FAILS_root_set_euid_egid (old, oldg); - return; - } - } - - /* This will "touch" the file */ - utime (d->userauth, NULL); - - NEVER_FAILS_root_set_euid_egid (old, oldg); - - d->last_auth_touch = ct; - } - } -} - -/* must call slave_waitpid_setpid before calling this */ -static void -slave_waitpid (GdmWaitPid *wp) -{ - if G_UNLIKELY (wp == NULL) - return; - - gdm_debug ("slave_waitpid: waiting on %d", (int)wp->pid); - - if G_UNLIKELY (slave_waitpid_r < 0) { - gdm_error ("slave_waitpid: no pipe, trying to wing it"); - - /* This is a real stupid fallback for a real stupid case */ - while (wp->pid > 1) { - struct timeval tv; - /* Wait 5 seconds. */ - tv.tv_sec = 5; - tv.tv_usec = 0; - select (0, NULL, NULL, NULL, min_time_to_wait (&tv)); - /* don't want to use sleep since we're using alarm - for pinging */ - - /* try to touch an fb auth file */ - try_to_touch_fb_userauth (); - - if (d->session_output_fd >= 0) - run_session_output (FALSE /* read_until_eof */); - if (d->chooser_output_fd >= 0) - run_chooser_output (); - check_notifies_now (); - } - check_notifies_now (); - } else { - gboolean read_session_output = TRUE; - - do { - char buf[1]; - fd_set rfds; - int ret; - struct timeval tv; - int maxfd; - - FD_ZERO (&rfds); - FD_SET (slave_waitpid_r, &rfds); - if (read_session_output && - d->session_output_fd >= 0) - FD_SET (d->session_output_fd, &rfds); - if (d->chooser_output_fd >= 0) - FD_SET (d->chooser_output_fd, &rfds); - - /* unset time */ - tv.tv_sec = 0; - tv.tv_usec = 0; - maxfd = MAX (slave_waitpid_r, d->session_output_fd); - maxfd = MAX (maxfd, d->chooser_output_fd); - - ret = select (maxfd + 1, &rfds, NULL, NULL, min_time_to_wait (&tv)); - - /* try to touch an fb auth file */ - try_to_touch_fb_userauth (); - - if (ret > 0) { - if (FD_ISSET (slave_waitpid_r, &rfds)) { - VE_IGNORE_EINTR (read (slave_waitpid_r, buf, 1)); - } - if (d->session_output_fd >= 0 && - FD_ISSET (d->session_output_fd, &rfds)) { - run_session_output (FALSE /* read_until_eof */); - } - if (d->chooser_output_fd >= 0 && - FD_ISSET (d->chooser_output_fd, &rfds)) { - run_chooser_output (); - } - } else if (errno == EBADF) { - read_session_output = FALSE; - } - check_notifies_now (); - } while (wp->pid > 1); - check_notifies_now (); - } - - gdm_sigchld_block_push (); - - wp->pid = -1; - - slave_waitpids = g_slist_remove (slave_waitpids, wp); - g_free (wp); - - gdm_sigchld_block_pop (); - - gdm_debug ("slave_waitpid: done_waiting"); -} - -static void -check_notifies_now (void) -{ - GList *list, *li; - - if (restart_greeter_now && - do_restart_greeter) { - do_restart_greeter = FALSE; - restart_the_greeter (); - } - - while (unhandled_notifies != NULL) { - gdm_sigusr2_block_push (); - list = unhandled_notifies; - unhandled_notifies = NULL; - gdm_sigusr2_block_pop (); - - for (li = list; li != NULL; li = li->next) { - char *s = li->data; - li->data = NULL; - - gdm_slave_handle_notify (s); - - g_free (s); - } - g_list_free (list); - } - - if (restart_greeter_now && - do_restart_greeter) { - do_restart_greeter = FALSE; - restart_the_greeter (); - } -} - -static void -gdm_slave_desensitize_config (void) -{ - if (configurator && - d->dsp != NULL) { - gulong foo = 1; - Atom atom = XInternAtom (d->dsp, - "_GDM_SETUP_INSENSITIVE", - False); - XChangeProperty (d->dsp, - DefaultRootWindow (d->dsp), - atom, - XA_CARDINAL, 32, PropModeReplace, - (unsigned char *) &foo, 1); - XSync (d->dsp, False); - } - -} - -static void -gdm_slave_sensitize_config (void) -{ - if (d->dsp != NULL) { - XDeleteProperty (d->dsp, - DefaultRootWindow (d->dsp), - XInternAtom (d->dsp, - "_GDM_SETUP_INSENSITIVE", - False)); - XSync (d->dsp, False); - } -} - -/* ignore handlers */ -static int -ignore_xerror_handler (Display *disp, XErrorEvent *evt) -{ - x_error_occurred = TRUE; - return 0; -} - -static void -whack_greeter_fds (void) -{ - if (greeter_fd_out > 0) - VE_IGNORE_EINTR (close (greeter_fd_out)); - greeter_fd_out = -1; - if (greeter_fd_in > 0) - VE_IGNORE_EINTR (close (greeter_fd_in)); - greeter_fd_in = -1; -} - -static void -term_session_stop_and_quit (void) -{ - gdm_in_signal = 0; - already_in_slave_start_jmp = TRUE; - gdm_wait_for_ack = FALSE; - need_to_quit_after_session_stop = TRUE; - - if (slave_start_jmp_error_to_print != NULL) - gdm_error (slave_start_jmp_error_to_print); - slave_start_jmp_error_to_print = NULL; - - /* only if we're not hanging in session stop and getting a - TERM signal again */ - if (in_session_stop == 0 && session_started) - gdm_slave_session_stop (d->logged_in && login != NULL, - TRUE /* no_shutdown_check */); - - gdm_debug ("term_session_stop_and_quit: Final cleanup"); - - /* Well now we're just going to kill - * everything including the X server, - * so no need doing XCloseDisplay which - * may just get us an XIOError */ - d->dsp = NULL; - - gdm_slave_quick_exit (exit_code_to_use); -} - -static void -term_quit (void) -{ - gdm_in_signal = 0; - already_in_slave_start_jmp = TRUE; - gdm_wait_for_ack = FALSE; - need_to_quit_after_session_stop = TRUE; - - if (slave_start_jmp_error_to_print != NULL) - gdm_error (slave_start_jmp_error_to_print); - slave_start_jmp_error_to_print = NULL; - - gdm_debug ("term_quit: Final cleanup"); - - /* Well now we're just going to kill - * everything including the X server, - * so no need doing XCloseDisplay which - * may just get us an XIOError */ - d->dsp = NULL; - - gdm_slave_quick_exit (exit_code_to_use); -} - -static gboolean -parent_exists (void) -{ - pid_t ppid = getppid (); - static gboolean parent_dead = FALSE; /* once dead, always dead */ - - if G_UNLIKELY (parent_dead || - ppid <= 1 || - kill (ppid, 0) < 0) { - parent_dead = TRUE; - return FALSE; - } - return TRUE; -} - -#ifdef SIGXFSZ -static void -gdm_slave_xfsz_handler (int signal) -{ - gdm_in_signal++; - - /* in places where we care we can check - * and stop writing */ - got_xfsz_signal = TRUE; - - /* whack self ASAP */ - remanage_asap = TRUE; - - gdm_in_signal--; -} -#endif /* SIGXFSZ */ - - -static int -get_runlevel (void) -{ - int rl; - - rl = -1; -#ifdef __linux__ - /* on linux we get our current runlevel, for use later - * to detect a shutdown going on, and not mess up. */ - if (g_access ("/sbin/runlevel", X_OK) == 0) { - char ign; - int rnl; - FILE *fp = popen ("/sbin/runlevel", "r"); - if (fp != NULL) { - if (fscanf (fp, "%c %d", &ign, &rnl) == 2) { - rl = rnl; - } - pclose (fp); - } - } -#endif /* __linux__ */ - return rl; -} - -void -gdm_slave_start (GdmDisplay *display) -{ - time_t first_time; - int death_count; - struct sigaction alrm, term, child, usr2; -#ifdef SIGXFSZ - struct sigaction xfsz; -#endif /* SIGXFSZ */ - sigset_t mask; - int pinginterval = gdm_daemon_config_get_value_int (GDM_KEY_PING_INTERVAL); - - /* - * Set d global to display before setting signal handlers, - * since the signal handlers use the d value. Avoids a - * race condition. It is also set again in gdm_slave_run - * since it is called in a loop. - */ - d = display; - - gdm_normal_runlevel = get_runlevel (); - - /* Ignore SIGUSR1/SIGPIPE, and especially ignore it - before the Setjmp */ - gdm_signal_ignore (SIGUSR1); - gdm_signal_ignore (SIGPIPE); - - /* ignore power failures, up to user processes to - * handle things correctly */ -#ifdef SIGPWR - gdm_signal_ignore (SIGPWR); -#endif - - /* The signals we wish to listen to */ - sigemptyset (&mask); - sigaddset (&mask, SIGINT); - sigaddset (&mask, SIGTERM); - sigaddset (&mask, SIGCHLD); - sigaddset (&mask, SIGUSR2); - sigaddset (&mask, SIGUSR1); /* normally we ignore USR1 */ - if ( ! SERVER_IS_LOCAL (display) && pinginterval > 0) { - sigaddset (&mask, SIGALRM); - } - /* must set signal mask before the Setjmp as it will be - restored, and we're only interested in catching the above signals */ - sigprocmask (SIG_UNBLOCK, &mask, NULL); - - - if G_UNLIKELY (display == NULL) { - /* saaay ... what? */ - _exit (DISPLAY_REMANAGE); - } - - gdm_debug ("gdm_slave_start: Starting slave process for %s", display->name); - - switch (Setjmp (slave_start_jmp)) { - case JMP_FIRST_RUN: - return_to_slave_start_jmp = TRUE; - break; - case JMP_SESSION_STOP_AND_QUIT: - term_session_stop_and_quit (); - /* huh? should never get here */ - _exit (DISPLAY_REMANAGE); - default: - case JMP_JUST_QUIT_QUICKLY: - term_quit (); - /* huh? should never get here */ - _exit (DISPLAY_REMANAGE); - } - - if ( ! SERVER_IS_LOCAL (display) && pinginterval > 0) { - /* Handle a ALRM signals from our ping alarms */ - alrm.sa_handler = gdm_slave_alrm_handler; - alrm.sa_flags = SA_RESTART | SA_NODEFER; - sigemptyset (&alrm.sa_mask); - sigaddset (&alrm.sa_mask, SIGALRM); - - if G_UNLIKELY (sigaction (SIGALRM, &alrm, NULL) < 0) - gdm_slave_exit (DISPLAY_ABORT, - _("%s: Error setting up %s signal handler: %s"), - "gdm_slave_start", "ALRM", strerror (errno)); - } - - /* Handle a INT/TERM signals from gdm master */ - term.sa_handler = gdm_slave_term_handler; - term.sa_flags = SA_RESTART; - sigemptyset (&term.sa_mask); - sigaddset (&term.sa_mask, SIGTERM); - sigaddset (&term.sa_mask, SIGINT); - - if G_UNLIKELY ((sigaction (SIGTERM, &term, NULL) < 0) || - (sigaction (SIGINT, &term, NULL) < 0)) - gdm_slave_exit (DISPLAY_ABORT, - _("%s: Error setting up %s signal handler: %s"), - "gdm_slave_start", "TERM/INT", strerror (errno)); - - /* Child handler. Keeps an eye on greeter/session */ - child.sa_handler = gdm_slave_child_handler; - child.sa_flags = SA_RESTART|SA_NOCLDSTOP; - sigemptyset (&child.sa_mask); - sigaddset (&child.sa_mask, SIGCHLD); - - if G_UNLIKELY (sigaction (SIGCHLD, &child, NULL) < 0) - gdm_slave_exit (DISPLAY_ABORT, _("%s: Error setting up %s signal handler: %s"), - "gdm_slave_start", "CHLD", strerror (errno)); - - /* Handle a USR2 which is ack from master that it received a message */ - usr2.sa_handler = gdm_slave_usr2_handler; - usr2.sa_flags = SA_RESTART; - sigemptyset (&usr2.sa_mask); - sigaddset (&usr2.sa_mask, SIGUSR2); - - if G_UNLIKELY (sigaction (SIGUSR2, &usr2, NULL) < 0) - gdm_slave_exit (DISPLAY_ABORT, _("%s: Error setting up %s signal handler: %s"), - "gdm_slave_start", "USR2", strerror (errno)); - -#ifdef SIGXFSZ - /* handle the filesize signal */ - xfsz.sa_handler = gdm_slave_xfsz_handler; - xfsz.sa_flags = SA_RESTART; - sigemptyset (&xfsz.sa_mask); - sigaddset (&xfsz.sa_mask, SIGXFSZ); - - if G_UNLIKELY (sigaction (SIGXFSZ, &xfsz, NULL) < 0) - gdm_slave_exit (DISPLAY_ABORT, - _("%s: Error setting up %s signal handler: %s"), - "gdm_slave_start", "XFSZ", strerror (errno)); -#endif /* SIGXFSZ */ - - first_time = time (NULL); - death_count = 0; - - for (;;) { - time_t the_time; - - check_notifies_now (); - - gdm_debug ("gdm_slave_start: Loop Thingie"); - gdm_slave_run (display); - - /* remote and flexi only run once */ - if (display->type != TYPE_STATIC || - ! parent_exists ()) { - gdm_server_stop (display); - gdm_slave_send_num (GDM_SOP_XPID, 0); - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - - the_time = time (NULL); - - death_count++; - - if ((the_time - first_time) <= 0 || - (the_time - first_time) > 60) { - first_time = the_time; - death_count = 0; - } else if G_UNLIKELY (death_count > 6) { - gdm_slave_quick_exit (DISPLAY_ABORT); - } - - gdm_debug ("gdm_slave_start: Reinitializing things"); - - /* Whack the server if we want to restart it next time - * we run gdm_slave_run */ - gdm_server_stop (display); - gdm_slave_send_num (GDM_SOP_XPID, 0); - } - /* very very very evil, should never break, we can't return from - here sanely */ - _exit (DISPLAY_ABORT); -} - -static gboolean -setup_automatic_session (GdmDisplay *display, const char *name) -{ - char *new_login; - g_free (login); - login = g_strdup (name); - - greet = FALSE; - gdm_debug ("setup_automatic_session: Automatic login: %s", login); - - /* Run the init script. gdmslave suspends until script - * has terminated */ - gdm_slave_exec_script (display, gdm_daemon_config_get_value_string (GDM_KEY_DISPLAY_INIT_DIR), - NULL, NULL, FALSE /* pass_stdout */); - - gdm_debug ("setup_automatic_session: DisplayInit script finished"); - - new_login = NULL; - if ( ! gdm_verify_setup_user (display, login, - display->name, &new_login)) - return FALSE; - - if (new_login != NULL) { - g_free (login); - login = g_strdup (new_login); - } - - gdm_debug ("setup_automatic_session: Automatic login successful"); - - return TRUE; -} - -#ifdef HAVE_TSOL -static void -gdm_tsol_init (GdmDisplay *display) -{ - - int opcode; - int firstevent; - int firsterror; - - have_suntsol_extension = XQueryExtension (display->dsp, - "SUN_TSOL", - &opcode, - &firstevent, - &firsterror); -} -#endif - -static void -gdm_screen_init (GdmDisplay *display) -{ -#ifdef HAVE_XFREE_XINERAMA - int (* old_xerror_handler) (Display *, XErrorEvent *); - gboolean have_xinerama = FALSE; - - x_error_occurred = FALSE; - old_xerror_handler = XSetErrorHandler (ignore_xerror_handler); - - have_xinerama = XineramaIsActive (display->dsp); - - XSync (display->dsp, False); - XSetErrorHandler (old_xerror_handler); - - if (x_error_occurred) - have_xinerama = FALSE; - - if (have_xinerama) { - int screen_num; - int xineramascreen; - XineramaScreenInfo *xscreens = - XineramaQueryScreens (display->dsp, - &screen_num); - - - if G_UNLIKELY (screen_num <= 0) - gdm_fail ("Xinerama active, but <= 0 screens?"); - - if (screen_num <= gdm_daemon_config_get_value_int (GDM_KEY_XINERAMA_SCREEN)) - gdm_daemon_config_set_value_int (GDM_KEY_XINERAMA_SCREEN, 0); - - xineramascreen = gdm_daemon_config_get_value_int (GDM_KEY_XINERAMA_SCREEN); - - display->screenx = xscreens[xineramascreen].x_org; - display->screeny = xscreens[xineramascreen].y_org; - display->screenwidth = xscreens[xineramascreen].width; - display->screenheight = xscreens[xineramascreen].height; - - display->lrh_offsetx = - DisplayWidth (display->dsp, - DefaultScreen (display->dsp)) - - (display->screenx + display->screenwidth); - display->lrh_offsety = - DisplayHeight (display->dsp, - DefaultScreen (display->dsp)) - - (display->screeny + display->screenheight); - - XFree (xscreens); - } else -#elif HAVE_SOLARIS_XINERAMA - /* This code from GDK, Copyright (C) 2002 Sun Microsystems */ - int opcode; - int firstevent; - int firsterror; - int n_monitors = 0; - - gboolean have_xinerama = FALSE; - have_xinerama = XQueryExtension (display->dsp, - "XINERAMA", - &opcode, - &firstevent, - &firsterror); - - if (have_xinerama) { - - int result; - XRectangle monitors[MAXFRAMEBUFFERS]; - unsigned char hints[16]; - int xineramascreen; - - result = XineramaGetInfo (display->dsp, 0, monitors, hints, &n_monitors); - /* Yes I know it should be Success but the current implementation - * returns the num of monitor - */ - if G_UNLIKELY (result <= 0) - gdm_fail ("Xinerama active, but <= 0 screens?"); - - if (n_monitors <= gdm_daemon_config_get_value_int (GDM_KEY_XINERAMA_SCREEN)) - gdm_daemon_config_set_value_int (GDM_KEY_XINERAMA_SCREEN, 0); - - xineramascreen = gdm_daemon_config_get_value_int (GDM_KEY_XINERAMA_SCREEN); - display->screenx = monitors[xineramascreen].x; - display->screeny = monitors[xineramascreen].y; - display->screenwidth = monitors[xineramascreen].width; - display->screenheight = monitors[xineramascreen].height; - - display->lrh_offsetx = - DisplayWidth (display->dsp, - DefaultScreen (display->dsp)) - - (display->screenx + display->screenwidth); - display->lrh_offsety = - DisplayHeight (display->dsp, - DefaultScreen (display->dsp)) - - (display->screeny + display->screenheight); - - } else -#endif - { - display->screenx = 0; - display->screeny = 0; - display->screenwidth = 0; /* we'll use the gdk size */ - display->screenheight = 0; - - display->lrh_offsetx = 0; - display->lrh_offsety = 0; - } -} - -static void -gdm_slave_whack_greeter (void) -{ - GdmWaitPid *wp; - - gdm_sigchld_block_push (); - - /* do what you do when you quit, this will hang until the - * greeter decides to print an STX\n and die, meaning it can do some - * last minute cleanup */ - gdm_slave_greeter_ctl_no_ret (GDM_QUIT, ""); - - greet = FALSE; - - wp = slave_waitpid_setpid (d->greetpid); - gdm_sigchld_block_pop (); - - slave_waitpid (wp); - - d->greetpid = 0; - - whack_greeter_fds (); - - gdm_slave_send_num (GDM_SOP_GREETPID, 0); - - gdm_slave_whack_temp_auth_file (); -} - -static void -wait_for_display_to_die (Display *display, - const char *display_name) -{ - fd_set rfds; - int fd; - - gdm_debug ("wait_for_display_to_die: waiting for display '%s' to die", - display_name); - - fd = ConnectionNumber (display); - - FD_ZERO (&rfds); - FD_SET (fd, &rfds); - - while (1) { - char buf[256]; - struct timeval tv; - int n; - - tv.tv_sec = 5; - tv.tv_usec = 0; - - n = select (fd + 1, &rfds, NULL, NULL, &tv); - if (G_LIKELY (n == 0)) { - XSync (display, True); - } else if (n > 0) { - VE_IGNORE_EINTR (n = read (fd, buf, sizeof (buf))); - if (n <= 0) - break; - } else if (errno != EINTR) { - break; - } - - FD_CLR (fd, &rfds); - } - - gdm_debug ("wait_for_display_to_die: '%s' dead", display_name); -} - -static int -ask_migrate (const char *migrate_to) -{ - int r; - char *msg; - char *but[4]; - char *askbuttons_msg; - - but[0] = _("Log in anyway"); - if (migrate_to != NULL) { - msg = _("You are already logged in. " - "You can log in anyway, return to your " - "previous login session, or abort this " - "login"); - but[1] = _("Return to previous login"); - but[2] = _("Abort login"); - but[3] = "NIL"; - } else { - msg = _("You are already logged in. " - "You can log in anyway or abort this " - "login"); - but[1] = _("Abort login"); - but[2] = "NIL"; - but[3] = "NIL"; - } - - if (greet) - gdm_slave_greeter_ctl_no_ret (GDM_DISABLE, ""); - - askbuttons_msg = g_strdup_printf ("askbuttons_msg=%s$$options_msg1=%s$$options_msg2=%s$$options_msg3=%s$$options_msg4=%s", msg, but[0], but[1], but[2], but[3]); - - - gdm_slave_send_string (GDM_SOP_SHOW_ASKBUTTONS_DIALOG, askbuttons_msg); - - r = atoi (gdm_ack_response); - - g_free (askbuttons_msg); - g_free (gdm_ack_response); - gdm_ack_response = NULL; - - if (greet) - gdm_slave_greeter_ctl_no_ret (GDM_ENABLE, ""); - - return r; -} - -gboolean -gdm_slave_check_user_wants_to_log_in (const char *user) -{ - gboolean loggedin = FALSE; - int i; - char **vec; - char *migrate_to = NULL; - - /* always ignore root here, this is mostly a special case - * since a root login may not be a real login, such as the - * config stuff, and people shouldn't log in as root anyway - */ - if (strcmp (user, gdm_root_user ()) == 0) - return TRUE; - - gdm_slave_send_string (GDM_SOP_QUERYLOGIN, user); - if G_LIKELY (ve_string_empty (gdm_ack_response)) - return TRUE; - vec = g_strsplit (gdm_ack_response, ",", -1); - if (vec == NULL) - return TRUE; - - gdm_debug ("QUERYLOGIN response: %s\n", gdm_ack_response); - - for (i = 0; vec[i] != NULL && vec[i+1] != NULL; i += 2) { - int ii; - loggedin = TRUE; - if (sscanf (vec[i+1], "%d", &ii) == 1 && ii == 1) { - migrate_to = g_strdup (vec[i]); - break; - } - } - - g_strfreev (vec); - - if ( ! loggedin) - return TRUE; - - if (d->type != TYPE_XDMCP_PROXY) { - int r; - - if (!gdm_daemon_config_get_value_bool (GDM_KEY_DOUBLE_LOGIN_WARNING)) { - g_free (migrate_to); - return TRUE; - } - - if (gdm_daemon_config_get_value_bool (GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION)) - r = 1; - else - r = ask_migrate (migrate_to); - - if (r <= 0) { - g_free (migrate_to); - return TRUE; - } - - if (migrate_to == NULL || - (migrate_to != NULL && r == 2)) { - g_free (migrate_to); - return FALSE; - } - - /* Must be that r == 1, that is - return to previous login */ - - if (d->type == TYPE_FLEXI) { - gdm_slave_whack_greeter (); - gdm_server_stop (d); - gdm_slave_send_num (GDM_SOP_XPID, 0); - - /* wait for a few seconds to avoid any vt changing race - */ - gdm_sleep_no_signal (1); - -#ifdef WITH_CONSOLE_KIT - unlock_ck_session (user, migrate_to); -#endif - - gdm_slave_send_string (GDM_SOP_MIGRATE, migrate_to); - g_free (migrate_to); - - /* we are no longer needed so just die. - REMANAGE == ABORT here really */ - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - - gdm_slave_send_string (GDM_SOP_MIGRATE, migrate_to); - g_free (migrate_to); - } else { - Display *parent_dsp; - - if (migrate_to == NULL) - return TRUE; - - gdm_slave_send_string (GDM_SOP_MIGRATE, migrate_to); - g_free (migrate_to); - - /* - * We must stay running and hold open our connection to the - * parent display because with XDMCP the Xserver resets when - * the initial X client closes its connection (rather than - * when *all* X clients have closed their connection) - */ - - gdm_slave_whack_greeter (); - - parent_dsp = d->parent_dsp; - d->parent_dsp = NULL; - gdm_server_stop (d); - - gdm_slave_send_num (GDM_SOP_XPID, 0); - - gdm_debug ("Slave not exiting in order to hold open the connection to the parent display"); - - wait_for_display_to_die (d->parent_dsp, d->parent_disp); - - gdm_slave_quick_exit (DISPLAY_ABORT); - } - - /* abort this login attempt */ - return FALSE; -} - -static gboolean do_xfailed_on_xio_error = FALSE; - -static void -gdm_slave_run (GdmDisplay *display) -{ - gint openretries = 0; - gint maxtries = 0; - gint pinginterval = gdm_daemon_config_get_value_int (GDM_KEY_PING_INTERVAL); - - gdm_reset_locale (); - - /* Reset d since gdm_slave_run is called in a loop */ - d = display; - - gdm_random_tick (); - - if (d->sleep_before_run > 0) { - gdm_debug ("gdm_slave_run: Sleeping %d seconds before server start", d->sleep_before_run); - gdm_sleep_no_signal (d->sleep_before_run); - d->sleep_before_run = 0; - - check_notifies_now (); - } - - /* - * Set it before we run the server, it may be that we're using - * the XOpenDisplay to find out if a server is ready (as with - * nested display) - */ - d->dsp = NULL; - - /* if this is local display start a server if one doesn't - * exist */ - if (SERVER_IS_LOCAL (d) && - d->servpid <= 0) { - if G_UNLIKELY ( ! gdm_server_start (d, - TRUE /* try_again_if_busy */, - FALSE /* treat_as_flexi */, - 20 /* min_flexi_disp */, - 5 /* flexi_retries */)) { - /* We're really not sure what is going on, - * so we throw up our hands and tell the user - * that we've given up. The error is likely something - * internal. */ - gdm_text_message_dialog - (C_(N_("Could not start the X\n" - "server (your graphical environment)\n" - "due to some internal error.\n" - "Please contact your system administrator\n" - "or check your syslog to diagnose.\n" - "In the meantime this display will be\n" - "disabled. Please restart GDM when\n" - "the problem is corrected."))); - gdm_slave_quick_exit (DISPLAY_ABORT); - } - gdm_slave_send_num (GDM_SOP_XPID, d->servpid); - - check_notifies_now (); - } - - /* We can use d->handled from now on on this display, - * since the lookup was done in server start */ - - g_setenv ("DISPLAY", d->name, TRUE); - g_unsetenv ("XAUTHORITY"); /* just in case it's set */ - - gdm_auth_set_local_auth (d); - - if (d->handled) { - /* Now the display name and hostname is final */ - - const char *automaticlogin = gdm_daemon_config_get_value_string (GDM_KEY_AUTOMATIC_LOGIN); - const char *timedlogin = gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_AUTOMATIC_LOGIN_ENABLE) && - ! ve_string_empty (automaticlogin)) { - g_free (ParsedAutomaticLogin); - ParsedAutomaticLogin = gdm_parse_enriched_login (automaticlogin, - display); - } - - if (gdm_daemon_config_get_value_bool (GDM_KEY_TIMED_LOGIN_ENABLE) && - ! ve_string_empty (timedlogin)) { - g_free (ParsedTimedLogin); - ParsedTimedLogin = gdm_parse_enriched_login (timedlogin, - display); - } - } - - /* X error handlers to avoid the default one (i.e. exit (1)) */ - do_xfailed_on_xio_error = TRUE; - XSetErrorHandler (gdm_slave_xerror_handler); - XSetIOErrorHandler (gdm_slave_xioerror_handler); - - /* We keep our own (windowless) connection (dsp) open to avoid the - * X server resetting due to lack of active connections. */ - - gdm_debug ("gdm_slave_run: Opening display %s", d->name); - - /* if local then the the server should be ready for openning, so - * don't try so long before killing it and trying again */ - if (SERVER_IS_LOCAL (d)) - maxtries = 2; - else - maxtries = 10; - - while (d->handled && - openretries < maxtries && - d->dsp == NULL && - ( ! SERVER_IS_LOCAL (d) || d->servpid > 1)) { - - gdm_sigchld_block_push (); - d->dsp = XOpenDisplay (d->name); - gdm_sigchld_block_pop (); - - if G_UNLIKELY (d->dsp == NULL) { - gdm_debug ("gdm_slave_run: Sleeping %d on a retry", 1+openretries*2); - gdm_sleep_no_signal (1+openretries*2); - openretries++; - } - } - - /* Really this will only be useful for the first local server, - since that's the only time this can really be on */ - while G_UNLIKELY (gdm_wait_for_go) { - struct timeval tv; - /* Wait 1 second. */ - tv.tv_sec = 1; - tv.tv_usec = 0; - select (0, NULL, NULL, NULL, &tv); - /* don't want to use sleep since we're using alarm - for pinging */ - check_notifies_now (); - } - - /* Set the busy cursor */ - if (d->dsp != NULL) { - Cursor xcursor = XCreateFontCursor (d->dsp, GDK_WATCH); - XDefineCursor (d->dsp, - DefaultRootWindow (d->dsp), - xcursor); - XFreeCursor (d->dsp, xcursor); - XSync (d->dsp, False); - } - - /* Just a race avoiding sleep, probably not necessary though, - * but doesn't hurt anything */ - if ( ! d->handled) - gdm_sleep_no_signal (1); - - if (SERVER_IS_LOCAL (d)) { - gdm_slave_send (GDM_SOP_START_NEXT_LOCAL, FALSE); - } - - check_notifies_now (); - - /* something may have gone wrong, try xfailed, if local (non-flexi), - * the toplevel loop of death will handle us */ - if G_UNLIKELY (d->handled && d->dsp == NULL) { - if (d->type == TYPE_STATIC) - gdm_slave_quick_exit (DISPLAY_XFAILED); - else - gdm_slave_quick_exit (DISPLAY_ABORT); - } - - /* OK from now on it's really the user whacking us most likely, - * we have already started up well */ - do_xfailed_on_xio_error = FALSE; - - /* If XDMCP setup pinging */ - if ( ! SERVER_IS_LOCAL (d) && pinginterval > 0) { - alarm (pinginterval); - } - - /* checkout xinerama */ - if (d->handled) - gdm_screen_init (d); - -#ifdef HAVE_TSOL - /* Check out Solaris Trusted Xserver extension */ - if (d->handled) - gdm_tsol_init (d); -#endif - - /* check log stuff for the server, this is done here - * because it's really a race */ - if (SERVER_IS_LOCAL (d)) - gdm_server_checklog (d); - - if ( ! d->handled) { - /* yay, we now wait for the server to die */ - while (d->servpid > 0) { - pause (); - } - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } else if (d->use_chooser) { - /* this usually doesn't return */ - gdm_slave_chooser (); /* Run the chooser */ - return; - } else if (d->type == TYPE_STATIC && - gdm_first_login && - ! ve_string_empty (ParsedAutomaticLogin) && - strcmp (ParsedAutomaticLogin, gdm_root_user ()) != 0) { - gdm_first_login = FALSE; - - d->logged_in = TRUE; - gdm_slave_send_num (GDM_SOP_LOGGED_IN, TRUE); - gdm_slave_send_string (GDM_SOP_LOGIN, ParsedAutomaticLogin); - - if (setup_automatic_session (d, ParsedAutomaticLogin)) { - gdm_slave_session_start (); - } - - gdm_slave_send_num (GDM_SOP_LOGGED_IN, FALSE); - d->logged_in = FALSE; - gdm_slave_send_string (GDM_SOP_LOGIN, ""); - logged_in_uid = -1; - logged_in_gid = -1; - - gdm_debug ("gdm_slave_run: Automatic login done"); - - if (remanage_asap) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - - /* return to gdm_slave_start so that the server - * can be reinitted and all that kind of fun stuff. */ - return; - } - - if (gdm_first_login) - gdm_first_login = FALSE; - - do { - check_notifies_now (); - - if ( ! greet) { - gdm_slave_greeter (); /* Start the greeter */ - greeter_no_focus = FALSE; - greeter_disabled = FALSE; - } - - gdm_slave_wait_for_login (); /* wait for a password */ - - d->logged_in = TRUE; - gdm_slave_send_num (GDM_SOP_LOGGED_IN, TRUE); - - if (do_timed_login) { - /* timed out into a timed login */ - do_timed_login = FALSE; - if (setup_automatic_session (d, ParsedTimedLogin)) { - gdm_slave_send_string (GDM_SOP_LOGIN, - ParsedTimedLogin); - gdm_slave_session_start (); - } - } else { - gdm_slave_send_string (GDM_SOP_LOGIN, login); - gdm_slave_session_start (); - } - - gdm_slave_send_num (GDM_SOP_LOGGED_IN, FALSE); - d->logged_in = FALSE; - gdm_slave_send_string (GDM_SOP_LOGIN, ""); - logged_in_uid = -1; - logged_in_gid = -1; - - if (remanage_asap) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - - if (greet) { - greeter_no_focus = FALSE; - gdm_slave_greeter_ctl_no_ret (GDM_FOCUS, ""); - greeter_disabled = FALSE; - gdm_slave_greeter_ctl_no_ret (GDM_ENABLE, ""); - gdm_slave_greeter_ctl_no_ret (GDM_RESETOK, ""); - } - /* Note that greet is only true if the above was no 'login', - * so no need to reinit the server nor rebake cookies - * nor such nonsense */ - } while (greet); - - /* If XDMCP stop pinging */ - if ( ! SERVER_IS_LOCAL (d)) - alarm (0); -} - -/* A hack really, this will wait around until the first mapped window - * with this class and focus it */ -static void -focus_first_x_window (const char *class_res_name) -{ - pid_t pid; - Display *disp; - int p[2]; - XWindowAttributes attribs = { 0, }; - - if G_UNLIKELY (pipe (p) < 0) { - p[0] = -1; - p[1] = -1; - } - - g_debug ("Forking process to focus first X11 window"); - - pid = fork (); - if G_UNLIKELY (pid < 0) { - if (p[0] != -1) - VE_IGNORE_EINTR (close (p[0])); - if (p[1] != -1) - VE_IGNORE_EINTR (close (p[1])); - gdm_error (_("%s: cannot fork"), "focus_first_x_window"); - return; - } - /* parent */ - if (pid > 0) { - /* Wait for this subprocess to start-up */ - if (p[0] >= 0) { - fd_set rfds; - struct timeval tv; - - VE_IGNORE_EINTR (close (p[1])); - - FD_ZERO(&rfds); - FD_SET(p[0], &rfds); - - /* Wait up to 2 seconds. */ - tv.tv_sec = 2; - tv.tv_usec = 0; - - select (p[0]+1, &rfds, NULL, NULL, &tv); - - VE_IGNORE_EINTR (close (p[0])); - } - return; - } - - gdm_unset_signals (); - - gdm_log_shutdown (); - - gdm_close_all_descriptors (0 /* from */, p[1] /* except */, -1 /* except2 */); - - /* No error checking here - if it's messed the best response - * is to ignore & try to continue */ - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - gdm_log_init (); - - /* just in case it's set */ - g_unsetenv ("XAUTHORITY"); - - gdm_auth_set_local_auth (d); - - gdm_sigchld_block_push (); - disp = XOpenDisplay (d->name); - gdm_sigchld_block_pop (); - if G_UNLIKELY (disp == NULL) { - gdm_error (_("%s: cannot open display %s"), - "focus_first_x_window", - d->name); - _exit (0); - } - - XSetInputFocus (disp, PointerRoot, RevertToPointerRoot, CurrentTime); - - /* set event mask for events on root window */ - XGetWindowAttributes (disp, - DefaultRootWindow (disp), - &attribs); - XSelectInput (disp, - DefaultRootWindow (disp), - attribs.your_event_mask | - SubstructureNotifyMask); - - if G_LIKELY (p[1] >= 0) { - VE_IGNORE_EINTR (write (p[1], "!", 1)); - VE_IGNORE_EINTR (close (p[1])); - } - - for (;;) { - XEvent event = { 0, }; - XClassHint hint = { NULL, NULL }; - - XNextEvent (disp, &event); - - if (event.type == MapNotify && - XGetClassHint (disp, - event.xmap.window, - &hint) && - hint.res_name != NULL && - strcmp (hint.res_name, class_res_name) == 0) { - Window root_return; - int x_return, y_return; - unsigned int width_return = 0, height_return = 0; - unsigned int border_width_return; - unsigned int depth_return; - - XGetGeometry (disp, event.xmap.window, - &root_return, &x_return, - &y_return, &width_return, - &height_return, &border_width_return, - &depth_return); - XWarpPointer (disp, None, event.xmap.window, - 0, 0, 0, 0, - width_return / 2, - height_return / 2); - XSync (disp, False); - XCloseDisplay (disp); - - _exit (0); - } - } -} - -static void -run_config (GdmDisplay *display, struct passwd *pwent) -{ - pid_t pid; - - /* Lets check if custom.conf exists. If not there - is no point in launching gdmsetup as it will fail. - We don't need to worry about defaults.conf as - the daemon wont start without it - */ - if (gdm_daemon_config_get_custom_config_file () == NULL) { - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("Could not access configuration file (custom.conf). " - "Make sure that the file exists before launching " - " login manager config utility.")); - return; - } - - /* Set the busy cursor */ - if (d->dsp != NULL) { - Cursor xcursor = XCreateFontCursor (d->dsp, GDK_WATCH); - XDefineCursor (d->dsp, - DefaultRootWindow (d->dsp), - xcursor); - XFreeCursor (d->dsp, xcursor); - XSync (d->dsp, False); - } - - g_debug ("Forking GDM configuration process"); - - gdm_sigchld_block_push (); - gdm_sigterm_block_push (); - pid = d->sesspid = fork (); - if (pid == 0) - gdm_unset_signals (); - gdm_sigterm_block_pop (); - gdm_sigchld_block_pop (); - - if G_UNLIKELY (pid < 0) { - /* Return left pointer */ - Cursor xcursor; - - /* Can't fork */ - display->sesspid = 0; - - xcursor = XCreateFontCursor (d->dsp, GDK_LEFT_PTR); - XDefineCursor (d->dsp, - DefaultRootWindow (d->dsp), - xcursor); - XFreeCursor (d->dsp, xcursor); - XSync (d->dsp, False); - - return; - } - - if (pid == 0) { - char **argv; - const char *s; - - /* child */ - - setsid (); - - gdm_unset_signals (); - - setuid (0); - setgid (0); - gdm_desetuid (); - - /* setup environment */ - gdm_restoreenv (); - gdm_reset_locale (); - - /* root here */ - g_setenv ("XAUTHORITY", GDM_AUTHFILE (display), TRUE); - g_setenv ("DISPLAY", display->name, TRUE); - g_setenv ("LOGNAME", pwent->pw_name, TRUE); - g_setenv ("USER", pwent->pw_name, TRUE); - g_setenv ("USERNAME", pwent->pw_name, TRUE); - g_setenv ("HOME", pwent->pw_dir, TRUE); - g_setenv ("SHELL", pwent->pw_shell, TRUE); - g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE); - g_setenv ("RUNNING_UNDER_GDM", "true", TRUE); - if ( ! ve_string_empty (display->theme_name)) - g_setenv ("GDM_GTK_THEME", display->theme_name, TRUE); - g_unsetenv ("MAIL"); /* Unset $MAIL for broken shells */ - - gdm_log_shutdown (); - - gdm_close_all_descriptors (0 /* from */, slave_fifo_pipe_fd /* except */, d->slave_notify_fd /* except2 */); - - /* No error checking here - if it's messed the best response - * is to ignore & try to continue */ - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - gdm_log_init (); - - VE_IGNORE_EINTR (g_chdir (pwent->pw_dir)); - if G_UNLIKELY (errno != 0) - VE_IGNORE_EINTR (g_chdir ("/")); - - /* exec the configurator */ - argv = NULL; - s = gdm_daemon_config_get_value_string (GDM_KEY_CONFIGURATOR); - if (s != NULL) { - g_shell_parse_argv (s, NULL, &argv, NULL); - } - - if G_LIKELY (argv != NULL && - argv[0] != NULL && - g_access (argv[0], X_OK) == 0) { - VE_IGNORE_EINTR (execv (argv[0], argv)); - } - - g_strfreev (argv); - - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("Could not execute the configuration " - "application. Make sure its path is set " - "correctly in the configuration file. " - "Attempting to start it from the default " - "location.")); - s = LIBEXECDIR "/gdmsetup --disable-sound --disable-crash-dialog"; - argv = NULL; - g_shell_parse_argv (s, NULL, &argv, NULL); - - if (g_access (argv[0], X_OK) == 0) { - VE_IGNORE_EINTR (execv (argv[0], argv)); - } - - g_strfreev (argv); - - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("Could not execute the configuration " - "application. Make sure its path is set " - "correctly in the configuration file.")); - - _exit (0); - } else { - GdmWaitPid *wp; - - configurator = TRUE; - - gdm_sigchld_block_push (); - wp = slave_waitpid_setpid (display->sesspid); - gdm_sigchld_block_pop (); - - slave_waitpid (wp); - - display->sesspid = 0; - configurator = FALSE; - - /* this will clean up the sensitivity property */ - gdm_slave_sensitize_config (); - } -} - -static void -restart_the_greeter (void) -{ - do_restart_greeter = FALSE; - - gdm_slave_desensitize_config (); - - /* no login */ - g_free (login); - login = NULL; - - /* Now restart it */ - if (greet) { - GdmWaitPid *wp; - - gdm_sigchld_block_push (); - - gdm_slave_greeter_ctl_no_ret (GDM_SAVEDIE, ""); - - greet = FALSE; - - wp = slave_waitpid_setpid (d->greetpid); - - gdm_sigchld_block_pop (); - - slave_waitpid (wp); - - d->greetpid = 0; - - whack_greeter_fds (); - - gdm_slave_send_num (GDM_SOP_GREETPID, 0); - } - gdm_slave_greeter (); - - if (greeter_disabled) - gdm_slave_greeter_ctl_no_ret (GDM_DISABLE, ""); - - if (greeter_no_focus) - gdm_slave_greeter_ctl_no_ret (GDM_NOFOCUS, ""); - - gdm_slave_sensitize_config (); -} - -static gboolean -play_login_sound (const char *sound_file) -{ - const char *soundprogram = gdm_daemon_config_get_value_string (GDM_KEY_SOUND_PROGRAM); - pid_t pid; - - if (ve_string_empty (soundprogram) || - ve_string_empty (sound_file) || - g_access (soundprogram, X_OK) != 0 || - g_access (sound_file, F_OK) != 0) - return FALSE; - - gdm_sigchld_block_push (); - gdm_sigterm_block_push (); - - g_debug ("Forking sound program: %s", soundprogram); - - pid = fork (); - if (pid == 0) - gdm_unset_signals (); - - gdm_sigterm_block_pop (); - gdm_sigchld_block_pop (); - - if (pid == 0) { - setsid (); - seteuid (0); - setegid (0); - execl (soundprogram, - soundprogram, - sound_file, - NULL); - _exit (0); - } - - return TRUE; -} - -static void -gdm_slave_wait_for_login (void) -{ - const char *successsound; - char *username; - g_free (login); - login = NULL; - - /* Chat with greeter */ - while (login == NULL) { - /* init to a sane value */ - do_timed_login = FALSE; - do_configurator = FALSE; - do_cancel = FALSE; - - if G_UNLIKELY (do_restart_greeter) { - do_restart_greeter = FALSE; - restart_the_greeter (); - } - - /* We are NOT interrupted yet */ - interrupted = FALSE; - - check_notifies_now (); - - /* just for paranoia's sake */ - NEVER_FAILS_root_set_euid_egid (0, 0); - - gdm_debug ("gdm_slave_wait_for_login: In loop"); - username = d->preset_user; - d->preset_user = NULL; - login = gdm_verify_user (d /* the display */, - username /* username */, - d->name /* display name */, - d->attached /* display attached? */, - TRUE /* allow retry */); - g_free (username); - - gdm_debug ("gdm_slave_wait_for_login: end verify for '%s'", - ve_sure_string (login)); - - /* Complex, make sure to always handle the do_configurator - * do_timed_login and do_restart_greeter after any call - * to gdm_verify_user */ - - if G_UNLIKELY (do_restart_greeter) { - g_free (login); - login = NULL; - do_restart_greeter = FALSE; - restart_the_greeter (); - continue; - } - - check_notifies_now (); - - if G_UNLIKELY (do_configurator) { - struct passwd *pwent; - gboolean oldAllowRoot; - - do_configurator = FALSE; - g_free (login); - login = NULL; - /* clear any error */ - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, ""); - gdm_slave_greeter_ctl_no_ret - (GDM_MSG, - _("You must authenticate as root to run configuration.")); - - /* we always allow root for this */ - oldAllowRoot = gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_ROOT); - gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_ROOT, TRUE); - - pwent = getpwuid (0); - if G_UNLIKELY (pwent == NULL) { - /* what? no "root" ?? */ - gdm_slave_greeter_ctl_no_ret (GDM_RESET, ""); - continue; - } - - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, pwent->pw_name); - login = gdm_verify_user (d, - pwent->pw_name, - d->name, - d->attached, - FALSE); - gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_ROOT, oldAllowRoot); - - /* Clear message */ - gdm_slave_greeter_ctl_no_ret (GDM_MSG, ""); - - if G_UNLIKELY (do_restart_greeter) { - g_free (login); - login = NULL; - do_restart_greeter = FALSE; - restart_the_greeter (); - continue; - } - - check_notifies_now (); - - /* The user can't remember his password */ - if (login == NULL) { - gdm_debug ("gdm_slave_wait_for_login: No login/Bad login"); - gdm_slave_greeter_ctl_no_ret (GDM_RESET, ""); - continue; - } - - /* Wipe the login */ - g_free (login); - login = NULL; - - /* Note that this can still fall through to - * the timed login if the user doesn't type in the - * password fast enough and there is timed login - * enabled */ - if (do_timed_login) { - break; - } - - if G_UNLIKELY (do_configurator) { - do_configurator = FALSE; - gdm_slave_greeter_ctl_no_ret (GDM_RESET, ""); - continue; - } - - /* Now running as root */ - - /* Get the root pwent */ - pwent = getpwuid (0); - - if G_UNLIKELY (pwent == NULL) { - /* What? No "root" ?? This is not possible - * since we logged in, but I'm paranoid */ - gdm_slave_greeter_ctl_no_ret (GDM_RESET, ""); - continue; - } - - d->logged_in = TRUE; - logged_in_uid = 0; - logged_in_gid = 0; - gdm_slave_send_num (GDM_SOP_LOGGED_IN, TRUE); - /* Note: nobody really logged in */ - gdm_slave_send_string (GDM_SOP_LOGIN, ""); - - /* Disable the login screen, we don't want people to - * log in in the meantime */ - gdm_slave_greeter_ctl_no_ret (GDM_DISABLE, ""); - greeter_disabled = TRUE; - - /* Make the login screen not focusable */ - gdm_slave_greeter_ctl_no_ret (GDM_NOFOCUS, ""); - greeter_no_focus = TRUE; - - check_notifies_now (); - restart_greeter_now = TRUE; - - gdm_debug ("gdm_slave_wait_for_login: Running GDM Configurator ..."); - run_config (d, pwent); - gdm_debug ("gdm_slave_wait_for_login: GDM Configurator finished ..."); - - restart_greeter_now = FALSE; - - gdm_verify_cleanup (d); - - gdm_slave_send_num (GDM_SOP_LOGGED_IN, FALSE); - d->logged_in = FALSE; - logged_in_uid = -1; - logged_in_gid = -1; - - if (remanage_asap) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - - greeter_no_focus = FALSE; - gdm_slave_greeter_ctl_no_ret (GDM_FOCUS, ""); - - greeter_disabled = FALSE; - gdm_slave_greeter_ctl_no_ret (GDM_ENABLE, ""); - gdm_slave_greeter_ctl_no_ret (GDM_RESETOK, ""); - continue; - } - - /* The user timed out into a timed login during the - * conversation */ - if (do_timed_login) { - break; - } - - if (login == NULL) { - const char *failuresound = gdm_daemon_config_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE); - - gdm_debug ("gdm_slave_wait_for_login: No login/Bad login"); - gdm_slave_greeter_ctl_no_ret (GDM_RESET, ""); - - /* Play sounds if specified for a failed login */ - if (d->attached && failuresound && - gdm_daemon_config_get_value_bool (GDM_KEY_SOUND_ON_LOGIN_FAILURE) && - ! play_login_sound (failuresound)) { - gdm_error (_("Login sound requested on non-local display or the play " - "software cannot be run or the sound does not exist.")); - } - } - } - - /* The user timed out into a timed login during the conversation */ - if (do_timed_login) { - g_free (login); - login = NULL; - /* timed login is automatic, thus no need for greeter, - * we'll take default values */ - gdm_slave_whack_greeter (); - - gdm_debug ("gdm_slave_wait_for_login: Timed Login"); - } - - successsound = gdm_daemon_config_get_value_string (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE); - /* Play sounds if specified for a successful login */ - if (login != NULL && successsound && - gdm_daemon_config_get_value_bool (GDM_KEY_SOUND_ON_LOGIN_SUCCESS) && - d->attached && - ! play_login_sound (successsound)) { - gdm_error (_("Login sound requested on non-local display or the play software " - "cannot be run or the sound does not exist.")); - } - - gdm_debug ("gdm_slave_wait_for_login: got_login for '%s'", - ve_sure_string (login)); - - -} - -/* This is VERY evil! */ -static void -run_pictures (void) -{ - char *response; - int max_write; - char buf[1024]; - size_t bytes; - struct passwd *pwent; - char *picfile; - FILE *fp; - - response = NULL; - for (;;) { - struct stat s; - char *tmp, *ret; - int i, r; - - g_free (response); - response = gdm_slave_greeter_ctl (GDM_NEEDPIC, ""); - if (ve_string_empty (response)) { - g_free (response); - return; - } - - pwent = getpwnam (response); - if G_UNLIKELY (pwent == NULL) { - gdm_slave_greeter_ctl_no_ret (GDM_READPIC, ""); - continue; - } - - picfile = NULL; - - NEVER_FAILS_seteuid (0); - if G_UNLIKELY (setegid (pwent->pw_gid) != 0 || - seteuid (pwent->pw_uid) != 0) { - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - gdm_slave_greeter_ctl_no_ret (GDM_READPIC, ""); - continue; - } - - picfile = gdm_daemon_config_get_facefile_from_home (pwent->pw_dir, pwent->pw_uid); - - if (! picfile) - picfile = gdm_daemon_config_get_facefile_from_global (pwent->pw_name, pwent->pw_uid); - - if (! picfile) { - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - gdm_slave_greeter_ctl_no_ret (GDM_READPIC, ""); - continue; - } - - VE_IGNORE_EINTR (r = g_stat (picfile, &s)); - if G_UNLIKELY (r < 0 || s.st_size > gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE)) { - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - - gdm_slave_greeter_ctl_no_ret (GDM_READPIC, ""); - continue; - } - - VE_IGNORE_EINTR (fp = fopen (picfile, "r")); - g_free (picfile); - if G_UNLIKELY (fp == NULL) { - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - - gdm_slave_greeter_ctl_no_ret (GDM_READPIC, ""); - continue; - } - - tmp = g_strdup_printf ("buffer:%d", (int)s.st_size); - ret = gdm_slave_greeter_ctl (GDM_READPIC, tmp); - g_free (tmp); - - if G_UNLIKELY (ret == NULL || strcmp (ret, "OK") != 0) { - VE_IGNORE_EINTR (fclose (fp)); - g_free (ret); - - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - - continue; - } - g_free (ret); - - gdm_fdprintf (greeter_fd_out, "%c", STX); - -#ifdef PIPE_BUF - max_write = MIN (PIPE_BUF, sizeof (buf)); -#else - /* apparently Hurd doesn't have PIPE_BUF */ - max_write = fpathconf (greeter_fd_out, _PC_PIPE_BUF); - /* could return -1 if no limit */ - if (max_write > 0) - max_write = MIN (max_write, sizeof (buf)); - else - max_write = sizeof (buf); -#endif - - i = 0; - while (i < s.st_size) { - int written; - - VE_IGNORE_EINTR (bytes = fread (buf, sizeof (char), - max_write, fp)); - - if (bytes <= 0) - break; - - if G_UNLIKELY (i + bytes > s.st_size) - bytes = s.st_size - i; - - /* write until we succeed in writing something */ - VE_IGNORE_EINTR (written = write (greeter_fd_out, buf, bytes)); - if G_UNLIKELY (written < 0 && - (errno == EPIPE || errno == EBADF)) { - /* something very, very bad has happened */ - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - - if G_UNLIKELY (written < 0) - written = 0; - - /* write until we succeed in writing everything */ - while (written < bytes) { - int n; - VE_IGNORE_EINTR (n = write (greeter_fd_out, &buf[written], bytes-written)); - if G_UNLIKELY (n < 0 && - (errno == EPIPE || errno == EBADF)) { - /* something very, very bad has happened */ - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } else if G_LIKELY (n > 0) { - written += n; - } - } - - /* we have written bytes bytes if it likes it or not */ - i += bytes; - } - - VE_IGNORE_EINTR (fclose (fp)); - - /* eek, this "could" happen, so just send some garbage */ - while G_UNLIKELY (i < s.st_size) { - bytes = MIN (sizeof (buf), s.st_size - i); - errno = 0; - bytes = write (greeter_fd_out, buf, bytes); - if G_UNLIKELY (bytes < 0 && (errno == EPIPE || errno == EBADF)) { - /* something very, very bad has happened */ - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - if (bytes > 0) - i += bytes; - } - - gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "done"); - - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - } - g_free (response); /* not reached */ -} - -/* hakish, copy file (owned by fromuid) to a temp file owned by touid */ -static char * -copy_auth_file (uid_t fromuid, uid_t touid, const char *file) -{ - uid_t old = geteuid (); - gid_t oldg = getegid (); - char *name; - int authfd; - int fromfd; - int bytes; - char buf[2048]; - int cnt; - - NEVER_FAILS_seteuid (0); - NEVER_FAILS_setegid (gdm_daemon_config_get_gdmgid ()); - - if G_UNLIKELY (seteuid (fromuid) != 0) { - NEVER_FAILS_root_set_euid_egid (old, oldg); - return NULL; - } - - if ( ! gdm_auth_file_check ("copy_auth_file", fromuid, - file, FALSE /* absentok */, NULL)) { - NEVER_FAILS_root_set_euid_egid (old, oldg); - return NULL; - } - - do { - errno = 0; - fromfd = open (file, O_RDONLY -#ifdef O_NOCTTY - |O_NOCTTY -#endif -#ifdef O_NOFOLLOW - |O_NOFOLLOW -#endif - ); - } while G_UNLIKELY (errno == EINTR); - - if G_UNLIKELY (fromfd < 0) { - NEVER_FAILS_root_set_euid_egid (old, oldg); - return NULL; - } - - NEVER_FAILS_root_set_euid_egid (0, 0); - - name = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), - d->name, ".XnestAuth"); - - VE_IGNORE_EINTR (g_unlink (name)); - VE_IGNORE_EINTR (authfd = open (name, O_EXCL|O_TRUNC|O_WRONLY|O_CREAT, 0600)); - - if G_UNLIKELY (authfd < 0) { - VE_IGNORE_EINTR (close (fromfd)); - NEVER_FAILS_root_set_euid_egid (old, oldg); - g_free (name); - return NULL; - } - - VE_IGNORE_EINTR (fchown (authfd, touid, -1)); - - cnt = 0; - for (;;) { - int written, n; - VE_IGNORE_EINTR (bytes = read (fromfd, buf, sizeof (buf))); - - /* EOF */ - if (bytes == 0) - break; - - if G_UNLIKELY (bytes < 0) { - /* Error reading */ - gdm_error ("Error reading %s: %s", file, strerror (errno)); - VE_IGNORE_EINTR (close (fromfd)); - VE_IGNORE_EINTR (close (authfd)); - NEVER_FAILS_root_set_euid_egid (old, oldg); - g_free (name); - return NULL; - } - - written = 0; - do { - VE_IGNORE_EINTR (n = write (authfd, &buf[written], bytes-written)); - if G_UNLIKELY (n < 0) { - /* Error writing */ - gdm_error ("Error writing %s: %s", name, strerror (errno)); - VE_IGNORE_EINTR (close (fromfd)); - VE_IGNORE_EINTR (close (authfd)); - NEVER_FAILS_root_set_euid_egid (old, oldg); - g_free (name); - return NULL; - } - written += n; - } while (written < bytes); - - cnt = cnt + written; - /* this should never occur (we check above) - but we're paranoid) */ - if G_UNLIKELY (cnt > gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE)) - return NULL; - } - - VE_IGNORE_EINTR (close (fromfd)); - VE_IGNORE_EINTR (close (authfd)); - - NEVER_FAILS_root_set_euid_egid (old, oldg); - - return name; -} - -static void -exec_command (const char *command, const char *extra_arg) -{ - char **argv; - int argc; - - if (! g_shell_parse_argv (command, &argc, &argv, NULL)) { - return; - } - - if (argv == NULL || - ve_string_empty (argv[0])) - return; - - if (g_access (argv[0], X_OK) != 0) - return; - - if (extra_arg != NULL) { - - argv = g_renew (char *, argv, argc + 2); - - argv[argc] = g_strdup (extra_arg); - argv[argc + 1] = NULL; - } - - VE_IGNORE_EINTR (execv (argv[0], argv)); - - g_strfreev (argv); -} - -static void -gdm_slave_greeter (void) -{ - gint pipe1[2], pipe2[2]; - struct passwd *pwent; - pid_t pid; - const char *command; - const char *defaultpath; - const char *gdmuser; - const char *moduleslist; - const char *gdmlang; - - gdm_debug ("gdm_slave_greeter: Running greeter on %s", d->name); - - /* Run the init script. gdmslave suspends until script has terminated */ - gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_DISPLAY_INIT_DIR), - NULL, NULL, FALSE /* pass_stdout */); - - /* Open a pipe for greeter communications */ - if G_UNLIKELY (pipe (pipe1) < 0) - gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't init pipe to gdmgreeter"), - "gdm_slave_greeter"); - if G_UNLIKELY (pipe (pipe2) < 0) { - VE_IGNORE_EINTR (close (pipe1[0])); - VE_IGNORE_EINTR (close (pipe1[1])); - gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't init pipe to gdmgreeter"), - "gdm_slave_greeter"); - } - - /* hackish ain't it */ - create_temp_auth_file (); - - if (d->attached) - command = gdm_daemon_config_get_value_string (GDM_KEY_GREETER); - else - command = gdm_daemon_config_get_value_string (GDM_KEY_REMOTE_GREETER); - - g_debug ("Forking greeter process: %s", command); - - /* Fork. Parent is gdmslave, child is greeter process. */ - gdm_sigchld_block_push (); - gdm_sigterm_block_push (); - greet = TRUE; - pid = d->greetpid = fork (); - if (pid == 0) - gdm_unset_signals (); - gdm_sigterm_block_pop (); - gdm_sigchld_block_pop (); - - switch (pid) { - - case 0: - setsid (); - - gdm_unset_signals (); - - /* Plumbing */ - VE_IGNORE_EINTR (close (pipe1[1])); - VE_IGNORE_EINTR (close (pipe2[0])); - - VE_IGNORE_EINTR (dup2 (pipe1[0], STDIN_FILENO)); - VE_IGNORE_EINTR (dup2 (pipe2[1], STDOUT_FILENO)); - - gdm_log_shutdown (); - - gdm_close_all_descriptors (2 /* from */, slave_fifo_pipe_fd/* except */, d->slave_notify_fd/* except2 */); - - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - gdm_log_init (); - - if G_UNLIKELY (setgid (gdm_daemon_config_get_gdmgid ()) < 0) - gdm_child_exit (DISPLAY_ABORT, - _("%s: Couldn't set groupid to %d"), - "gdm_slave_greeter", gdm_daemon_config_get_gdmgid ()); - - gdmuser = gdm_daemon_config_get_value_string (GDM_KEY_USER); - if G_UNLIKELY (initgroups (gdmuser, gdm_daemon_config_get_gdmgid ()) < 0) - gdm_child_exit (DISPLAY_ABORT, - _("%s: initgroups () failed for %s"), - "gdm_slave_greeter", gdmuser); - - if G_UNLIKELY (setuid (gdm_daemon_config_get_gdmuid ()) < 0) - gdm_child_exit (DISPLAY_ABORT, - _("%s: Couldn't set userid to %d"), - "gdm_slave_greeter", gdm_daemon_config_get_gdmuid ()); - - gdm_restoreenv (); - gdm_reset_locale (); - - g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE); - g_setenv ("DISPLAY", d->name, TRUE); - - /* hackish ain't it */ - set_xnest_parent_stuff (); - - g_setenv ("LOGNAME", gdmuser, TRUE); - g_setenv ("USER", gdmuser, TRUE); - g_setenv ("USERNAME", gdmuser, TRUE); - g_setenv ("GDM_GREETER_PROTOCOL_VERSION", - GDM_GREETER_PROTOCOL_VERSION, TRUE); - g_setenv ("GDM_VERSION", VERSION, TRUE); - g_unsetenv ("MAIL"); /* Unset $MAIL for broken shells */ - - pwent = getpwnam (gdmuser); - if G_LIKELY (pwent != NULL) { - /* Note that usually this doesn't exist */ - if (pwent->pw_dir != NULL && - g_file_test (pwent->pw_dir, G_FILE_TEST_EXISTS)) - g_setenv ("HOME", pwent->pw_dir, TRUE); - else - g_setenv ("HOME", - ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)), - TRUE); /* Hack */ - g_setenv ("SHELL", pwent->pw_shell, TRUE); - } else { - g_setenv ("HOME", - ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)), - TRUE); /* Hack */ - g_setenv ("SHELL", "/bin/sh", TRUE); - } - - defaultpath = gdm_daemon_config_get_value_string (GDM_KEY_PATH); - if (ve_string_empty (g_getenv ("PATH"))) { - g_setenv ("PATH", defaultpath, TRUE); - } else if ( ! ve_string_empty (defaultpath)) { - gchar *temp_string = g_strconcat (g_getenv ("PATH"), - ":", defaultpath, NULL); - g_setenv ("PATH", temp_string, TRUE); - g_free (temp_string); - } - g_setenv ("RUNNING_UNDER_GDM", "true", TRUE); - if ( ! ve_string_empty (d->theme_name)) - g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG_GESTURES)) { - g_setenv ("GDM_DEBUG_GESTURES", "true", TRUE); - } - - /* Note that this is just informative, the slave will not listen to - * the greeter even if it does something it shouldn't on a non-local - * display so it's not a security risk */ - if (d->attached) { - g_setenv ("GDM_IS_LOCAL", "yes", TRUE); - } else { - g_unsetenv ("GDM_IS_LOCAL"); - } - - /* this is again informal only, if the greeter does time out it will - * not actually login a user if it's not enabled for this display */ - if (d->timed_login_ok) { - if (ParsedTimedLogin == NULL) - g_setenv ("GDM_TIMED_LOGIN_OK", " ", TRUE); - else - g_setenv ("GDM_TIMED_LOGIN_OK", ParsedTimedLogin, TRUE); - } else { - g_unsetenv ("GDM_TIMED_LOGIN_OK"); - } - - if (SERVER_IS_FLEXI (d)) { - g_setenv ("GDM_FLEXI_SERVER", "yes", TRUE); - } else { - g_unsetenv ("GDM_FLEXI_SERVER"); - } - - if G_UNLIKELY (d->is_emergency_server) { - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("No servers were defined in the " - "configuration file and XDMCP was " - "disabled. This can only be a " - "configuration error. GDM has started " - "a single server for you. You should " - "log in and fix the configuration. " - "Note that automatic and timed logins " - "are disabled now.")); - g_unsetenv ("GDM_TIMED_LOGIN_OK"); - } - - if G_UNLIKELY (d->failsafe_xserver) { - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("Could not start the regular X " - "server (your graphical environment) " - "and so this is a failsafe X server. " - "You should log in and properly " - "configure the X server.")); - } - - if G_UNLIKELY (d->busy_display) { - char *msg = g_strdup_printf - (_("The specified display number was busy, so " - "this server was started on display %s."), - d->name); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, msg); - g_free (msg); - } - - if G_UNLIKELY (d->try_different_greeter) { - /* FIXME: we should also really be able to do standalone failsafe - login, but that requires some work and is perhaps an overkill. */ - /* This should handle mostly the case where gdmgreeter is crashing - and we'd want to start gdmlogin for the user so that at least - something works instead of a flickering screen */ - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("The greeter application appears to be crashing. " - "Attempting to use a different one.")); - if (strstr (command, "gdmlogin") != NULL) { - /* in case it is gdmlogin that's crashing - try the themed greeter for luck */ - command = LIBEXECDIR "/gdmgreeter"; - } else { - /* in all other cases, try the gdmlogin (standard greeter) - proggie */ - command = LIBEXECDIR "/gdmlogin"; - } - } - - moduleslist = gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES) && - ! ve_string_empty (moduleslist) && - /* don't add modules if we're trying to prevent crashes, - perhaps it's the modules causing the problem in the first place */ - ! d->try_different_greeter) { - gchar *modules = g_strdup_printf ("--gtk-module=%s", moduleslist); - exec_command (command, modules); - /* Something went wrong */ - gdm_error (_("%s: Cannot start greeter with gtk modules: %s. Trying without modules"), - "gdm_slave_greeter", - moduleslist); - g_free (modules); - } - exec_command (command, NULL); - - gdm_error (_("%s: Cannot start greeter trying default: %s"), - "gdm_slave_greeter", - LIBEXECDIR "/gdmlogin"); - - g_setenv ("GDM_WHACKED_GREETER_CONFIG", "true", TRUE); - - exec_command (LIBEXECDIR "/gdmlogin", NULL); - - VE_IGNORE_EINTR (execl (LIBEXECDIR "/gdmlogin", LIBEXECDIR "/gdmlogin", NULL)); - - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("Cannot start the greeter application; " - "you will not be able to log in. " - "This display will be disabled. " - "Try logging in by other means and " - "editing the configuration file")); - - /* If no greeter we really have to disable the display */ - gdm_child_exit (DISPLAY_ABORT, _("%s: Error starting greeter on display %s"), "gdm_slave_greeter", d->name); - - case -1: - d->greetpid = 0; - gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't fork gdmgreeter process"), "gdm_slave_greeter"); - - default: - VE_IGNORE_EINTR (close (pipe1[0])); - VE_IGNORE_EINTR (close (pipe2[1])); - - whack_greeter_fds (); - - greeter_fd_out = pipe1[1]; - greeter_fd_in = pipe2[0]; - - gdm_debug ("gdm_slave_greeter: Greeter on pid %d", (int)pid); - - gdm_slave_send_num (GDM_SOP_GREETPID, d->greetpid); - run_pictures (); /* Append pictures to greeter if browsing is on */ - - if (always_restart_greeter) - gdm_slave_greeter_ctl_no_ret (GDM_ALWAYS_RESTART, "Y"); - else - gdm_slave_greeter_ctl_no_ret (GDM_ALWAYS_RESTART, "N"); - gdmlang = g_getenv ("GDM_LANG"); - if (gdmlang) - gdm_slave_greeter_ctl_no_ret (GDM_SETLANG, gdmlang); - - - check_notifies_now (); - break; - } -} - -/* This should not call anything that could cause a syslog in case we - * are in a signal */ -void -gdm_slave_send (const char *str, gboolean wait_for_ack) -{ - int fd; - char *fifopath; - int i; - uid_t old; - - if ( ! gdm_wait_for_ack) - wait_for_ack = FALSE; - - if (wait_for_ack) { - gdm_got_ack = FALSE; - g_free (gdm_ack_response); - gdm_ack_response = NULL; - } - - /* ensure this is sent from the actual slave with the pipe always, this is anal I know */ - if (G_LIKELY (d->slavepid == getppid ()) || G_LIKELY (d->slavepid == getpid ())) { - fd = slave_fifo_pipe_fd; - } else { - fd = -1; - } - - if G_UNLIKELY (fd < 0) { - /* FIXME: This is not likely to ever be used, remove - at some point. Other then slaves shouldn't be using - these functions. And if the pipe creation failed - in main daemon just abort the main daemon. */ - /* Use the fifo as a fallback only now that we have a pipe */ - fifopath = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), - ".gdmfifo", NULL); - old = geteuid (); - if (old != 0) - seteuid (0); -#ifdef O_NOFOLLOW - VE_IGNORE_EINTR (fd = open (fifopath, O_WRONLY|O_NOFOLLOW)); -#else - VE_IGNORE_EINTR (fd = open (fifopath, O_WRONLY)); -#endif - if (old != 0) - seteuid (old); - g_free (fifopath); - } - - /* eek */ - if G_UNLIKELY (fd < 0) { - if (gdm_in_signal == 0) - gdm_error (_("%s: Can't open fifo!"), "gdm_slave_send"); - return; - } - - gdm_fdprintf (fd, "\n%s\n", str); - - if G_UNLIKELY (fd != slave_fifo_pipe_fd) { - VE_IGNORE_EINTR (close (fd)); - } - -#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD) - if (wait_for_ack && ! gdm_got_ack) { - /* let the other process do its stuff */ - sched_yield (); - } -#endif - - /* Wait till you get a response from the daemon */ - if (strncmp (str, "opcode="GDM_SOP_SHOW_ERROR_DIALOG, - strlen ("opcode="GDM_SOP_SHOW_ERROR_DIALOG)) == 0 || - strncmp (str, "opcode="GDM_SOP_SHOW_YESNO_DIALOG, - strlen ("opcode="GDM_SOP_SHOW_YESNO_DIALOG)) == 0 || - strncmp (str, "opcode="GDM_SOP_SHOW_QUESTION_DIALOG, - strlen ("opcode="GDM_SOP_SHOW_QUESTION_DIALOG)) == 0 || - strncmp (str, "opcode="GDM_SOP_SHOW_ASKBUTTONS_DIALOG, - strlen ("opcode="GDM_SOP_SHOW_ASKBUTTONS_DIALOG)) == 0) { - - for (; wait_for_ack && !gdm_got_ack ; ) { - fd_set rfds; - - FD_ZERO (&rfds); - FD_SET (d->slave_notify_fd, &rfds); - - if (select (d->slave_notify_fd+1, &rfds, NULL, NULL, NULL) > 0) { - gdm_slave_handle_usr2_message (); - } - } - } else { - for (i = 0; - wait_for_ack && - ! gdm_got_ack && - parent_exists () && - i < 10; - i++) { - if (in_usr2_signal > 0) { - fd_set rfds; - struct timeval tv; - - FD_ZERO (&rfds); - FD_SET (d->slave_notify_fd, &rfds); - - /* Wait up to 1 second. */ - tv.tv_sec = 1; - tv.tv_usec = 0; - - if (select (d->slave_notify_fd+1, &rfds, NULL, NULL, &tv) > 0) { - gdm_slave_handle_usr2_message (); - } - } else { - struct timeval tv; - /* Wait 1 second. */ - tv.tv_sec = 1; - tv.tv_usec = 0; - select (0, NULL, NULL, NULL, &tv); - /* don't want to use sleep since we're using alarm - for pinging */ - } - } - } - - if G_UNLIKELY (wait_for_ack && - ! gdm_got_ack && - gdm_in_signal == 0) { - if (strncmp (str, GDM_SOP_COOKIE " ", - strlen (GDM_SOP_COOKIE " ")) == 0) { - char *s = g_strndup - (str, strlen (GDM_SOP_COOKIE " XXXX XX")); - /* cut off most of the cookie for "security" */ - gdm_debug ("Timeout occurred for sending message %s...", s); - g_free (s); - } else { - gdm_debug ("Timeout occurred for sending message %s", str); - } - } -} - -void -gdm_slave_send_num (const char *opcode, long num) -{ - char *msg; - - if (gdm_in_signal == 0) - gdm_debug ("Sending %s == %ld for slave %ld", - opcode, - (long)num, - (long)getpid ()); - - msg = g_strdup_printf ("%s %ld %ld", opcode, - (long)getpid (), (long)num); - - gdm_slave_send (msg, TRUE); - - g_free (msg); -} - -void -gdm_slave_send_string (const char *opcode, const char *str) -{ - char *msg; - - if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG) && gdm_in_signal == 0) { - gdm_debug ("Sending %s == <secret> for slave %ld", - opcode, - (long)getpid ()); - } - - if (strcmp (opcode, GDM_SOP_SHOW_ERROR_DIALOG) == 0 || - strcmp (opcode, GDM_SOP_SHOW_YESNO_DIALOG) == 0 || - strcmp (opcode, GDM_SOP_SHOW_QUESTION_DIALOG) == 0 || - strcmp (opcode, GDM_SOP_SHOW_ASKBUTTONS_DIALOG) == 0) { - msg = g_strdup_printf ("opcode=%s$$pid=%ld$$%s", opcode, - (long)d->slavepid, ve_sure_string (str)); - } else { - msg = g_strdup_printf ("%s %ld %s", opcode, - (long)getpid (), ve_sure_string (str)); - } - - gdm_slave_send (msg, TRUE); - - g_free (msg); -} - -static void -send_chosen_host (GdmDisplay *disp, - const char *hostname) -{ - GdmHostent *hostent; - struct sockaddr_storage ss; - char *str = NULL; - char *host; - - hostent = gdm_gethostbyname (hostname); - - if G_UNLIKELY (hostent->addrs == NULL) { - gdm_error ("Cannot get address of host '%s'", hostname); - gdm_hostent_free (hostent); - return; - } - - /* take first address */ - memcpy (&ss, &hostent->addrs[0], sizeof (struct sockaddr_storage)); - - gdm_address_get_info (&ss, &host, NULL); - gdm_hostent_free (hostent); - - gdm_debug ("Sending chosen host address (%s) %s", hostname, host); - str = g_strdup_printf ("%s %d %s", GDM_SOP_CHOSEN, disp->indirect_id, host); - gdm_slave_send (str, FALSE); - - g_free (str); -} - - -static void -gdm_slave_chooser (void) -{ - gint p[2]; - struct passwd *pwent; - pid_t pid; - GdmWaitPid *wp; - const char *defaultpath; - const char *gdmuser; - const char *moduleslist; - - gdm_debug ("gdm_slave_chooser: Running chooser on %s", d->name); - - /* Open a pipe for chooser communications */ - if G_UNLIKELY (pipe (p) < 0) - gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't init pipe to gdmchooser"), "gdm_slave_chooser"); - - /* Run the init script. gdmslave suspends until script has terminated */ - gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_DISPLAY_INIT_DIR), - NULL, NULL, FALSE /* pass_stdout */); - - g_debug ("Forking chooser process: %s", gdm_daemon_config_get_value_string (GDM_KEY_CHOOSER)); - - /* Fork. Parent is gdmslave, child is greeter process. */ - gdm_sigchld_block_push (); - gdm_sigterm_block_push (); - pid = d->chooserpid = fork (); - if (pid == 0) - gdm_unset_signals (); - gdm_sigterm_block_pop (); - gdm_sigchld_block_pop (); - - switch (pid) { - - case 0: - setsid (); - - gdm_unset_signals (); - - /* Plumbing */ - VE_IGNORE_EINTR (close (p[0])); - - if (p[1] != STDOUT_FILENO) - VE_IGNORE_EINTR (dup2 (p[1], STDOUT_FILENO)); - - gdm_log_shutdown (); - - VE_IGNORE_EINTR (close (0)); - gdm_close_all_descriptors (2 /* from */, slave_fifo_pipe_fd /* except */, d->slave_notify_fd /* except2 */); - - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - - gdm_log_init (); - - if G_UNLIKELY (setgid (gdm_daemon_config_get_gdmgid ()) < 0) - gdm_child_exit (DISPLAY_ABORT, - _("%s: Couldn't set groupid to %d"), - "gdm_slave_chooser", gdm_daemon_config_get_gdmgid ()); - - gdmuser = gdm_daemon_config_get_value_string (GDM_KEY_USER); - if G_UNLIKELY (initgroups (gdmuser, gdm_daemon_config_get_gdmgid ()) < 0) - gdm_child_exit (DISPLAY_ABORT, - _("%s: initgroups () failed for %s"), - "gdm_slave_chooser", gdmuser); - - if G_UNLIKELY (setuid (gdm_daemon_config_get_gdmuid ()) < 0) - gdm_child_exit (DISPLAY_ABORT, - _("%s: Couldn't set userid to %d"), - "gdm_slave_chooser", gdm_daemon_config_get_gdmuid ()); - - gdm_restoreenv (); - gdm_reset_locale (); - - g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE); - g_setenv ("DISPLAY", d->name, TRUE); - - g_setenv ("LOGNAME", gdmuser, TRUE); - g_setenv ("USER", gdmuser, TRUE); - g_setenv ("USERNAME", gdmuser, TRUE); - - g_setenv ("GDM_VERSION", VERSION, TRUE); - - g_unsetenv ("MAIL"); /* Unset $MAIL for broken shells */ - - pwent = getpwnam (gdmuser); - if G_LIKELY (pwent != NULL) { - /* Note that usually this doesn't exist */ - if (g_file_test (pwent->pw_dir, G_FILE_TEST_EXISTS)) - g_setenv ("HOME", pwent->pw_dir, TRUE); - else - g_setenv ("HOME", - ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)), - TRUE); /* Hack */ - g_setenv ("SHELL", pwent->pw_shell, TRUE); - } else { - g_setenv ("HOME", - ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)), - TRUE); /* Hack */ - g_setenv ("SHELL", "/bin/sh", TRUE); - } - - defaultpath = gdm_daemon_config_get_value_string (GDM_KEY_PATH); - if (ve_string_empty (g_getenv ("PATH"))) { - g_setenv ("PATH", defaultpath, TRUE); - } else if ( ! ve_string_empty (defaultpath)) { - gchar *temp_string = g_strconcat (g_getenv ("PATH"), - ":", defaultpath, NULL); - g_setenv ("PATH", temp_string, TRUE); - g_free (temp_string); - } - g_setenv ("RUNNING_UNDER_GDM", "true", TRUE); - if ( ! ve_string_empty (d->theme_name)) - g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE); - - moduleslist = gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST); - if (gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES) && - ! ve_string_empty (moduleslist)) { - char *modules = g_strdup_printf ("--gtk-module=%s", moduleslist); - exec_command (gdm_daemon_config_get_value_string (GDM_KEY_CHOOSER), modules); - } - - exec_command (gdm_daemon_config_get_value_string (GDM_KEY_CHOOSER), NULL); - - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("Cannot start the chooser application. " - "You will probably not be able to log in. " - "Please contact the system administrator.")); - - gdm_child_exit (DISPLAY_REMANAGE, _("%s: Error starting chooser on display %s"), "gdm_slave_chooser", d->name); - - case -1: - gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't fork gdmchooser process"), "gdm_slave_chooser"); - - default: - gdm_debug ("gdm_slave_chooser: Chooser on pid %d", d->chooserpid); - gdm_slave_send_num (GDM_SOP_CHOOSERPID, d->chooserpid); - - VE_IGNORE_EINTR (close (p[1])); - - g_free (d->chooser_last_line); - d->chooser_last_line = NULL; - d->chooser_output_fd = p[0]; - /* make the output read fd non-blocking */ - fcntl (d->chooser_output_fd, F_SETFL, O_NONBLOCK); - - /* wait for the chooser to die */ - - gdm_sigchld_block_push (); - wp = slave_waitpid_setpid (d->chooserpid); - gdm_sigchld_block_pop (); - - slave_waitpid (wp); - - d->chooserpid = 0; - gdm_slave_send_num (GDM_SOP_CHOOSERPID, 0); - - /* Note: Nothing affecting the chooser needs update - * from notifies, plus we are exitting right now */ - - run_chooser_output (); - VE_IGNORE_EINTR (close (d->chooser_output_fd)); - d->chooser_output_fd = -1; - - if (d->chooser_last_line != NULL) { - char *host = d->chooser_last_line; - d->chooser_last_line = NULL; - - if (SERVER_IS_XDMCP (d)) { - send_chosen_host (d, host); - gdm_slave_quick_exit (DISPLAY_CHOSEN); - } else { - gdm_debug ("Sending locally chosen host %s", host); - gdm_slave_send_string (GDM_SOP_CHOSEN_LOCAL, host); - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - } - - gdm_slave_quick_exit (DISPLAY_REMANAGE); - break; - } -} - -gboolean -gdm_is_session_magic (const char *session_name) -{ - return (strcmp (session_name, GDM_SESSION_DEFAULT) == 0 || - strcmp (session_name, GDM_SESSION_CUSTOM) == 0 || - strcmp (session_name, GDM_SESSION_FAILSAFE) == 0); -} - -/* Note that this does check TryExec! while normally we don't check - * it */ -static gboolean -is_session_ok (const char *session_name) -{ - char *exec; - gboolean ret = TRUE; - - /* these are always OK */ - if (strcmp (session_name, GDM_SESSION_FAILSAFE_GNOME) == 0 || - strcmp (session_name, GDM_SESSION_FAILSAFE_XTERM) == 0) - return TRUE; - - if (ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR))) - return gdm_is_session_magic (session_name); - - exec = gdm_daemon_config_get_session_exec (session_name, TRUE /* check_try_exec */); - if (exec == NULL) - ret = FALSE; - g_free (exec); - return ret; -} - -static char * -find_a_session (void) -{ - char *try[] = { - "Default", - "default", - "Gnome", - "gnome", - "GNOME", - "Custom", - "custom", - "kde", - "KDE", - "failsafe", - "Failsafe", - NULL - }; - int i; - char *session; - const char *defaultsession = gdm_daemon_config_get_value_string (GDM_KEY_DEFAULT_SESSION); - - if (!ve_string_empty (defaultsession) && - is_session_ok (defaultsession)) - session = g_strdup (defaultsession); - else - session = NULL; - - for (i = 0; try[i] != NULL && session == NULL; i++) { - if (is_session_ok (try[i])) - session = g_strdup (try[i]); - } - return session; -} - -static char * -find_prog (const char *name) -{ - char *path; - int i; - char *try[] = { - "/usr/bin/X11/", - "/usr/X11R6/bin/", - "/opt/X11R6/bin/", - "/usr/bin/", - "/usr/openwin/bin/", - "/usr/local/bin/", - "/opt/gnome/bin/", - BINDIR "/", - NULL - }; - - path = g_find_program_in_path (name); - if (path != NULL && - g_access (path, X_OK) == 0) { - return path; - } - g_free (path); - for (i = 0; try[i] != NULL; i++) { - path = g_strconcat (try[i], name, NULL); - if (g_access (path, X_OK) == 0) { - return path; - } - g_free (path); - } - return NULL; -} - -static gboolean -wipe_xsession_errors (struct passwd *pwent, - const char *home_dir, - gboolean home_dir_ok) -{ - gboolean wiped_something = FALSE; - DIR *dir; - struct dirent *ent; - uid_t old = geteuid (); - uid_t oldg = getegid (); - - seteuid (0); - if G_UNLIKELY (setegid (pwent->pw_gid) != 0 || - seteuid (pwent->pw_uid) != 0) { - NEVER_FAILS_root_set_euid_egid (old, oldg); - return FALSE; - } - - if G_LIKELY (home_dir_ok) { - char *filename = g_build_filename (home_dir, - ".xsession-errors", - NULL); - if (g_access (filename, F_OK) == 0) { - wiped_something = TRUE; - VE_IGNORE_EINTR (g_unlink (filename)); - } - g_free (filename); - } - - VE_IGNORE_EINTR (dir = opendir ("/tmp")); - if G_LIKELY (dir != NULL) { - char *prefix = g_strdup_printf ("xses-%s.", pwent->pw_name); - int prefixlen = strlen (prefix); - VE_IGNORE_EINTR (ent = readdir (dir)); - while (ent != NULL) { - if (strncmp (ent->d_name, prefix, prefixlen) == 0) { - char *filename = g_strdup_printf ("/tmp/%s", - ent->d_name); - wiped_something = TRUE; - VE_IGNORE_EINTR (g_unlink (filename)); - g_free (filename); - } - VE_IGNORE_EINTR (ent = readdir (dir)); - } - VE_IGNORE_EINTR (closedir (dir)); - g_free (prefix); - } - - NEVER_FAILS_root_set_euid_egid (old, oldg); - - return wiped_something; -} - -static int -open_xsession_errors (struct passwd *pwent, - gboolean failsafe, - const char *home_dir, - gboolean home_dir_ok) -{ - int logfd = -1; - - g_free (d->xsession_errors_filename); - d->xsession_errors_filename = NULL; - - /* Log all output from session programs to a file, - * unless in failsafe mode which needs to work when there is - * no diskspace as well */ - if G_LIKELY ( ! failsafe && home_dir_ok) { - char *filename = g_build_filename (home_dir, - ".xsession-errors", - NULL); - uid_t old = geteuid (); - uid_t oldg = getegid (); - - seteuid (0); - if G_LIKELY (setegid (pwent->pw_gid) == 0 && - seteuid (pwent->pw_uid) == 0) { - /* unlink to be anal */ - VE_IGNORE_EINTR (g_unlink (filename)); - VE_IGNORE_EINTR (logfd = open (filename, O_EXCL|O_CREAT|O_TRUNC|O_WRONLY, 0644)); - } - NEVER_FAILS_root_set_euid_egid (old, oldg); - - if G_UNLIKELY (logfd < 0) { - gdm_error (_("%s: Could not open ~/.xsession-errors"), - "run_session_child"); - g_free (filename); - } else { - d->xsession_errors_filename = filename; - } - } - - /* let's try an alternative */ - if G_UNLIKELY (logfd < 0) { - mode_t oldmode; - - char *filename = g_strdup_printf ("/tmp/xses-%s.XXXXXX", - pwent->pw_name); - uid_t old = geteuid (); - uid_t oldg = getegid (); - - seteuid (0); - if G_LIKELY (setegid (pwent->pw_gid) == 0 && - seteuid (pwent->pw_uid) == 0) { - oldmode = umask (077); - logfd = mkstemp (filename); - umask (oldmode); - } - - NEVER_FAILS_root_set_euid_egid (old, oldg); - - if G_LIKELY (logfd >= 0) { - d->xsession_errors_filename = filename; - } else { - g_free (filename); - } - } - - return logfd; -} - -#ifdef HAVE_SELINUX -/* This should be run just before we exec the user session */ -static gboolean -gdm_selinux_setup (const char *login) -{ - security_context_t scontext; - int ret=-1; - char *seuser=NULL; - char *level=NULL; - - /* If selinux is not enabled, then we don't do anything */ - if (is_selinux_enabled () <= 0) - return TRUE; - - if (getseuserbyname(login, &seuser, &level) == 0) - ret=get_default_context_with_level(seuser, level, 0, &scontext); - - if (ret < 0) { - gdm_error ("SELinux gdm login: unable to obtain default security context for %s.", login); - /* note that this will be run when the .xsession-errors - is already being logged, so we can use stderr */ - gdm_fdprintf (2, "SELinux gdm login: unable to obtain default security context for %s.", login); - return (security_getenforce()==0); - } - - gdm_assert (scontext != NULL); - - if (setexeccon (scontext) != 0) { - gdm_error ("SELinux gdm login: unable to set executable context %s.", - (char *)scontext); - gdm_fdprintf (2, "SELinux gdm login: unable to set executable context %s.", - (char *)scontext); - freecon (scontext); - return (security_getenforce()==0); - } - - freecon (scontext); - - return TRUE; -} -#endif /* HAVE_SELINUX */ - -static void -session_child_run (struct passwd *pwent, - int logfd, - gboolean failsafe, - const char *home_dir, - gboolean home_dir_ok, -#ifdef WITH_CONSOLE_KIT - const char *ck_session_cookie, -#endif - const char *session, - const char *save_session, - const char *language, - const char *gnome_session, - gboolean usrcfgok, - gboolean savesess, - gboolean savelang) -{ - char *exec; - const char *shell = NULL; - const char *greeter; - gint result; -#ifndef HAVE_TSOL - char *argv[4]; -#else - char *argv[7]; -#endif - -#ifdef CAN_USE_SETPENV - extern char **newenv; - int i; -#endif - - gdm_unset_signals (); - if G_UNLIKELY (setsid () < 0) - /* should never happen */ - gdm_error (_("%s: setsid () failed: %s!"), - "session_child_run", strerror (errno)); - - g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE); - - /* Here we setup our 0,1,2 descriptors, we do it here - * nowdays rather then later on so that we get errors even - * from the PreSession script */ - if G_LIKELY (logfd >= 0) { - VE_IGNORE_EINTR (dup2 (logfd, 1)); - VE_IGNORE_EINTR (dup2 (logfd, 2)); - VE_IGNORE_EINTR (close (logfd)); - } else { - VE_IGNORE_EINTR (close (1)); - VE_IGNORE_EINTR (close (2)); - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - } - - VE_IGNORE_EINTR (close (0)); - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - - /* Set this for the PreSession script */ - /* compatibility */ - g_setenv ("GDMSESSION", session, TRUE); - - g_setenv ("DESKTOP_SESSION", session, TRUE); - - /* Determine default greeter type so the PreSession */ - /* script can set the appropriate background color. */ - if (d->attached) { - greeter = gdm_daemon_config_get_value_string (GDM_KEY_GREETER); - } else { - greeter = gdm_daemon_config_get_value_string (GDM_KEY_REMOTE_GREETER); - } - - if (strstr (greeter, "gdmlogin") != NULL) { - g_setenv ("GDM_GREETER_TYPE", "PLAIN", TRUE); - } else if (strstr (greeter, "gdmgreeter") != NULL) { - g_setenv ("GDM_GREETER_TYPE", "THEMED", TRUE); - } else { - /* huh? */ - g_setenv ("GDM_GREETER_TYPE", "unknown", TRUE); - } - - /* Run the PreSession script */ - if G_UNLIKELY (gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_PRESESSION), - pwent->pw_name, pwent, - TRUE /* pass_stdout */) != EXIT_SUCCESS && - /* ignore errors in failsafe modes */ - ! failsafe) - /* If script fails reset X server and restart greeter */ - gdm_child_exit (DISPLAY_REMANAGE, - _("%s: Execution of PreSession script returned > 0. Aborting."), "session_child_run"); - - ve_clearenv (); - - /* Prepare user session */ - g_setenv ("XAUTHORITY", d->userauth, TRUE); - g_setenv ("DISPLAY", d->name, TRUE); - g_setenv ("LOGNAME", pwent->pw_name, TRUE); - g_setenv ("USER", pwent->pw_name, TRUE); - g_setenv ("USERNAME", pwent->pw_name, TRUE); - g_setenv ("HOME", home_dir, TRUE); -#ifdef WITH_CONSOLE_KIT - if (ck_session_cookie != NULL) { - g_setenv ("XDG_SESSION_COOKIE", ck_session_cookie, TRUE); - } -#endif - g_setenv ("GDMSESSION", session, TRUE); - g_setenv ("DESKTOP_SESSION", session, TRUE); - g_setenv ("SHELL", pwent->pw_shell, TRUE); - g_unsetenv ("MAIL"); /* Unset $MAIL for broken shells */ - - if (d->type == TYPE_STATIC) { - g_setenv ("GDM_XSERVER_LOCATION", "local", TRUE); - } else if (d->type == TYPE_XDMCP) { - g_setenv ("GDM_XSERVER_LOCATION", "xdmcp", TRUE); - } else if (d->type == TYPE_FLEXI) { - g_setenv ("GDM_XSERVER_LOCATION", "flexi", TRUE); - } else if (d->type == TYPE_FLEXI_XNEST) { - g_setenv ("GDM_XSERVER_LOCATION", "flexi-xnest", TRUE); - } else if (d->type == TYPE_XDMCP_PROXY) { - g_setenv ("GDM_XSERVER_LOCATION", "xdmcp-proxy", TRUE); - } else { - /* huh? */ - g_setenv ("GDM_XSERVER_LOCATION", "unknown", TRUE); - } - - if (gnome_session != NULL) - g_setenv ("GDM_GNOME_SESSION", gnome_session, TRUE); - - /* Special PATH for root */ - if (pwent->pw_uid == 0) - g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE); - else - g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_PATH), TRUE); - - /* Eeeeek, this no lookie as a correct language code, - * just use the system default */ - if G_UNLIKELY ( ! ve_string_empty (language) && - ! ve_locale_exists (language)) { - char *msg = g_strdup_printf (_("Language %s does not exist; using %s"), - language, _("System default")); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, msg); - language = NULL; - g_free (msg); - } - - /* Now still as root make the system authfile not readable by others, - and therefore not by the gdm user */ - VE_IGNORE_EINTR (g_chmod (GDM_AUTHFILE (d), 0640)); - - setpgid (0, 0); - - umask (022); - - /* setup the verify env vars */ - if G_UNLIKELY ( ! gdm_verify_setup_env (d)) - gdm_child_exit (DISPLAY_REMANAGE, - _("%s: Could not setup environment for %s. " - "Aborting."), - "session_child_run", login); - - /* setup euid/egid to the correct user, - * not to leave the egid around. It's - * ok to gdm_fail here */ - NEVER_FAILS_root_set_euid_egid (pwent->pw_uid, pwent->pw_gid); - - VE_IGNORE_EINTR (result = g_chdir (home_dir)); - if G_UNLIKELY (result != 0) { - VE_IGNORE_EINTR (g_chdir ("/")); - NEVER_FAILS_root_set_euid_egid (0, 0); - } else if (pwent->pw_uid != 0) { - /* sanitize .ICEauthority to be of the correct - * permissions, if it exists */ - struct stat s0, s1, s2; - gint s0_ret, s1_ret, s2_ret; - gint iceauth_fd; - - NEVER_FAILS_root_set_euid_egid (0, 0); - - iceauth_fd = open (".ICEauthority", O_RDONLY); - - s0_ret = stat (home_dir, &s0); - s1_ret = lstat (".ICEauthority", &s1); - s2_ret = fstat (iceauth_fd, &s2); - - if (iceauth_fd >= 0 && - s0_ret == 0 && - s0.st_uid == pwent->pw_uid && - s1_ret == 0 && - s2_ret == 0 && - S_ISREG (s1.st_mode) && - s1.st_ino == s2.st_ino && - s1.st_dev == s2.st_dev && - s1.st_uid == s2.st_uid && - s1.st_gid == s2.st_gid && - s1.st_mode == s2.st_mode && - (s1.st_uid != pwent->pw_uid || - s1.st_gid != pwent->pw_gid || - (s1.st_mode & (S_IRWXG|S_IRWXO)) || - !(s1.st_mode & S_IRWXU))) { - /* This may not work on NFS, but oh well, there - * this is beyond our help, but it's unlikely - * that it got screwed up when NFS was used - * in the first place */ - - /* only if we own the current directory */ - fchown (iceauth_fd, - pwent->pw_uid, - pwent->pw_gid); - fchmod (iceauth_fd, S_IRUSR | S_IWUSR); - } - - if (iceauth_fd >= 0) - close (iceauth_fd); - } - - NEVER_FAILS_setegid (pwent->pw_gid); -#ifdef HAVE_LOGINCAP - if (setusercontext (NULL, pwent, pwent->pw_uid, - LOGIN_SETLOGIN | LOGIN_SETPATH | - LOGIN_SETPRIORITY | LOGIN_SETRESOURCES | - LOGIN_SETUMASK | LOGIN_SETUSER | - LOGIN_SETENV) < 0) - gdm_child_exit (DISPLAY_REMANAGE, - _("%s: setusercontext () failed for %s. " - "Aborting."), "session_child_run", - login); -#else - if G_UNLIKELY (setuid (pwent->pw_uid) < 0) - gdm_child_exit (DISPLAY_REMANAGE, - _("%s: Could not become %s. Aborting."), "session_child_run", login); -#endif - - /* Only force GDM_LANG to something if there is other then - * system default selected. Else let the session do whatever it - * does since we're using sys default */ - if ( ! ve_string_empty (language)) { - g_setenv ("LANG", language, TRUE); - g_setenv ("GDM_LANG", language, TRUE); - } - - /* just in case there is some weirdness going on */ - VE_IGNORE_EINTR (g_chdir (home_dir)); - - if (usrcfgok && home_dir_ok) - gdm_daemon_config_set_user_session_lang (savesess, savelang, home_dir, save_session, language); - - gdm_log_shutdown (); - - gdm_close_all_descriptors (3 /* from */, slave_fifo_pipe_fd /* except */, d->slave_notify_fd /* except2 */); - - gdm_log_init (); - - argv[0] = NULL; - argv[1] = NULL; - argv[2] = NULL; - argv[3] = NULL; -#ifdef HAVE_TSOL - argv[4] = NULL; - argv[5] = NULL; - argv[6] = NULL; -#endif - - exec = NULL; - if (strcmp (session, GDM_SESSION_FAILSAFE_XTERM) != 0 && - strcmp (session, GDM_SESSION_FAILSAFE_GNOME) != 0) { - exec = gdm_daemon_config_get_session_exec (session, - FALSE /* check_try_exec */); - - if G_UNLIKELY (exec == NULL) { - gchar *msg = g_strdup_printf ( - _("No Exec line in the session file: %s. Running the GNOME failsafe session instead"), - session); - - gdm_error (_("%s: %s"), "session_child_run", msg); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, msg); - g_free (msg); - - session = GDM_SESSION_FAILSAFE_GNOME; - } else { - /* HACK!, if failsafe, we really wish to run the - internal one */ - if (strcmp (exec, "failsafe") == 0) { - session = GDM_SESSION_FAILSAFE_XTERM; - exec = NULL; - } - } - } - - if (exec != NULL) { - const char *basexsession = gdm_daemon_config_get_value_string (GDM_KEY_BASE_XSESSION); - - /* cannot be possibly failsafe */ - if G_UNLIKELY (g_access (basexsession, X_OK) != 0) { - gdm_error (_("%s: Cannot find or run the base Xsession script. Running the GNOME failsafe session instead."), - "session_child_run"); - session = GDM_SESSION_FAILSAFE_GNOME; - exec = NULL; - gdm_errorgui_error_box - (d, GTK_MESSAGE_ERROR, - _("Cannot find or run the base session script. Running the GNOME failsafe session instead.")); - } else { - /* This is where everything is OK, and note that - we really DON'T care about leaks, we are going to - exec in just a bit */ -#ifdef HAVE_TSOL - if (have_suntsol_extension) { - argv[0] = g_strdup (basexsession); - argv[1] = g_strdup ("/usr/bin/tsoljdslabel"); - argv[2] = exec; - argv[3] = argv[4] = argv[5] = argv[6] = NULL; - } else { -#endif - argv[0] = g_strdup (basexsession); - argv[1] = exec; - argv[2] = NULL; -#ifdef HAVE_TSOL - argv[3] = argv[4] = argv[5] = argv[6] = NULL; - } -#endif - } - } - - if (strcmp (session, GDM_SESSION_FAILSAFE_GNOME) == 0) { -#ifdef HAVE_TSOL - if (have_suntsol_extension == TRUE) { - /* Trusted Path will be preserved as long as the sys admin - * doesn't put anything stupid in gdm.conf */ - argv[0] = g_strdup ("/usr/bin/tsoljdslabel"); - argv[1] = find_prog ("gnome-session"); - if G_UNLIKELY (argv[1] == NULL) { - /* yaikes */ - gdm_error (_("%s: gnome-session not found for a failsafe GNOME session, trying xterm"), - "session_child_run"); - session = GDM_SESSION_FAILSAFE_XTERM; - gdm_errorgui_error_box - (d, GTK_MESSAGE_ERROR, - _("Could not find the GNOME installation, " - "will try running the \"Failsafe xterm\" " - "session.")); - } else { - argv[2] = "--failsafe"; - argv[3] = NULL; - gdm_errorgui_error_box - (d, GTK_MESSAGE_INFO, - _("This is the Failsafe GNOME session. " - "You will be logged into the 'Default' " - "session of GNOME without the startup scripts " - "being run. This should be used to fix problems " - "in your installation.")); - } - } else { -#endif - argv[0] = find_prog ("gnome-session"); - if G_UNLIKELY (argv[0] == NULL) { - /* yaikes */ - gdm_error (_("%s: gnome-session not found for a failsafe GNOME session; trying xterm"), - "session_child_run"); - session = GDM_SESSION_FAILSAFE_XTERM; - gdm_errorgui_error_box - (d, GTK_MESSAGE_ERROR, - _("Could not find the GNOME installation. " - "Running the \"Failsafe xterm\" " - "session instead.")); - } else { - argv[1] = "--failsafe"; - argv[2] = NULL; - gdm_errorgui_error_box - (d, GTK_MESSAGE_INFO, - _("This is the Failsafe GNOME session. " - "You will be logged into the 'Default' " - "session of GNOME without the startup scripts " - "being run. This should be used to fix problems " - "in your installation.")); - } -#ifdef HAVE_TSOL - } -#endif - failsafe = TRUE; - } - - /* an if and not an else, we could have done a fall-through - * to here in the above code if we can't find gnome-session */ - if (strcmp (session, GDM_SESSION_FAILSAFE_XTERM) == 0) { - argv[0] = find_prog ("xterm"); - if (argv[0] == NULL) { - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("Cannot find \"xterm\" to start " - "a failsafe session.")); - /* nyah nyah nyah nyah nyah */ - /* 66 means no "session crashed" examine .xsession-errors dialog */ - _exit (66); -#ifdef HAVE_TSOL - } else if (have_suntsol_extension) { - argv[1] = "-geometry"; - argv[2] = g_strdup_printf ("80x24-%d-%d", - d->lrh_offsetx, - d->lrh_offsety); - /* - * In a Solaris Trusted Extensions environment, failsafe xterms should - * be restricted to the root user, or users who have the root role. - * This is necessary to prevent normal users and evil terrorists - * bypassing their assigned clearance and getting direct access - * to the global zone. - */ - if (pwent->pw_uid == 0) { - argv[3] = argv[4] = argv[5] = argv[6] = NULL; - gdm_errorgui_error_box - (d, GTK_MESSAGE_INFO, - _("This is the Failsafe xterm session. " - "You will be logged into a terminal " - "console so that you may fix your system " - "if you cannot log in any other way. " - "To exit the terminal emulator, type " - "'exit' and an enter into the window.")); - focus_first_x_window ("xterm"); - } else if (gdm_can_i_assume_root_role (pwent) == TRUE) { - argv[3] = "-C"; - argv[4] = "-e"; - argv[5] = "su"; - argv[6] = NULL; - gdm_errorgui_error_box - (d, GTK_MESSAGE_INFO, - _("This is the Failsafe xterm session. " - "You will be logged into a terminal " - "console and be prompted to enter the " - "password for root so that you may fix " - "your system if you cannot log in any " - "other way. To exit the terminal " - "emulator, type 'exit' and an enter " - "into the window.")); - focus_first_x_window ("xterm"); - } else { - /* Normal user without root role - get lost */ - gdm_errorgui_error_box - (d, GTK_MESSAGE_INFO, - _("The failsafe session is restricted to " - "users who have been assigned the root " - "role. If you cannot log in any other " - "way please contact your system " - "administrator")); - _exit (66); - } -#endif /* HAVE_TSOL */ - } else { - argv[1] = "-geometry"; - argv[2] = g_strdup_printf ("80x24-%d-%d", - d->lrh_offsetx, - d->lrh_offsety); - argv[3] = NULL; -#ifdef HAVE_TSOL - argv[4] = argv[5] = argv[6] = NULL; -#endif - gdm_errorgui_error_box - (d, GTK_MESSAGE_INFO, - _("This is the Failsafe xterm session. " - "You will be logged into a terminal " - "console so that you may fix your system " - "if you cannot log in any other way. " - "To exit the terminal emulator, type " - "'exit' and an enter into the window.")); - focus_first_x_window ("xterm"); - } - failsafe = TRUE; - } - -#ifdef HAVE_TSOL - gdm_debug ("Running %s %s %s %s %s %s for %s on %s", - argv[0], - ve_sure_string (argv[1]), - ve_sure_string (argv[2]), - ve_sure_string (argv[3]), - ve_sure_string (argv[4]), - ve_sure_string (argv[5]), - login, d->name); -#else - gdm_debug ("Running %s %s %s for %s on %s", - argv[0], - ve_sure_string (argv[1]), - ve_sure_string (argv[2]), - login, d->name); -#endif - - if ( ! ve_string_empty (pwent->pw_shell)) { - shell = pwent->pw_shell; - } else { - shell = "/bin/sh"; - } - - /* just a stupid test */ - if (strcmp (shell, "/sbin/nologin") == 0 || - strcmp (shell, "/bin/false") == 0 || - strcmp (shell, "/bin/true") == 0) { - gdm_error (_("%s: User not allowed to log in"), - "session_child_run"); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("The system administrator has " - "disabled your account.")); - /* ends as if nothing bad happened */ - /* 66 means no "session crashed" examine .xsession-errors - dialog */ - _exit (66); - } - -#ifdef CAN_USE_SETPENV - /* Call the function setpenv which instanciates the extern variable "newenv" */ - setpenv (login, (PENV_INIT | PENV_NOEXEC), NULL, NULL); - - /* Add the content of the "newenv" variable to the environment */ - for (i=0; newenv != NULL && newenv[i] != NULL; i++) { - char *env_str = g_strdup (newenv[i]); - char *p = strchr (env_str, '='); - if (p != NULL) { - /* Add a NULL byte to terminate the variable name */ - p[0] = '\0'; - /* Add the variable to the env */ - g_setenv (env_str, &p[1], TRUE); - } - g_free (env_str); - } -#endif - -#ifdef HAVE_SELINUX - if ( ! gdm_selinux_setup (pwent->pw_name)) { - /* 66 means no "session crashed" examine .xsession-errors - dialog */ - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("Error! Unable to set executable context.")); - _exit (66); - } -#endif - - VE_IGNORE_EINTR (execv (argv[0], argv)); - - /* will go to .xsession-errors */ -#ifdef HAVE_TSOL - fprintf (stderr, _("%s: Could not exec %s %s %s %s %s %s"), - "session_child_run", - argv[0], - ve_sure_string (argv[1]), - ve_sure_string (argv[2]), - ve_sure_string (argv[3]), - ve_sure_string (argv[4]), - ve_sure_string (argv[5])); - - gdm_error ( _("%s: Could not exec %s %s %s %s %s %s"), - "session_child_run", - argv[0], - ve_sure_string (argv[1]), - ve_sure_string (argv[2]), - ve_sure_string (argv[3]), - ve_sure_string (argv[4]), - ve_sure_string (argv[5])); -#else - fprintf (stderr, _("%s: Could not exec %s %s %s"), - "session_child_run", - argv[0], - ve_sure_string (argv[1]), - ve_sure_string (argv[2])); - gdm_error ( _("%s: Could not exec %s %s %s"), - "session_child_run", - argv[0], - ve_sure_string (argv[1]), - ve_sure_string (argv[2])); -#endif - - /* if we can't read and exec the session, then make a nice - * error dialog */ - gdm_errorgui_error_box - (d, GTK_MESSAGE_ERROR, - /* we can't really be any more specific */ - _("Cannot start the session due to some " - "internal error.")); - - /* ends as if nothing bad happened */ - _exit (0); -} - -static void -finish_session_output (gboolean do_read) -{ - if G_LIKELY (d->session_output_fd >= 0) { - if (do_read) - run_session_output (TRUE /* read_until_eof */); - if (d->session_output_fd >= 0) { - VE_IGNORE_EINTR (close (d->session_output_fd)); - d->session_output_fd = -1; - } - if (d->xsession_errors_fd >= 0) { - VE_IGNORE_EINTR (close (d->xsession_errors_fd)); - d->xsession_errors_fd = -1; - } - } -} - -static void -gdm_slave_session_start (void) -{ - struct passwd *pwent; - const char *home_dir = NULL; - char *save_session = NULL, *session = NULL, *language = NULL, *usrsess, *usrlang; - char *gnome_session = NULL; -#ifdef WITH_CONSOLE_KIT - char *ck_session_cookie; -#endif - char *tmp; - gboolean savesess = FALSE, savelang = FALSE; - gboolean usrcfgok = FALSE, authok = FALSE; - gboolean home_dir_ok = FALSE; - gboolean failsafe = FALSE; - time_t session_start_time, end_time; - pid_t pid; - GdmWaitPid *wp; - uid_t uid; - gid_t gid; - int logpipe[2]; - int logfilefd; - - gdm_debug ("gdm_slave_session_start: Attempting session for user '%s'", - login); - - pwent = getpwnam (login); - - if G_UNLIKELY (pwent == NULL) { - /* This is sort of an "assert", this should NEVER happen */ - if (greet) - gdm_slave_whack_greeter (); - gdm_slave_exit (DISPLAY_REMANAGE, - _("%s: User passed auth but getpwnam (%s) failed!"), "gdm_slave_session_start", login); - } - - logged_in_uid = uid = pwent->pw_uid; - logged_in_gid = gid = pwent->pw_gid; - - /* Run the PostLogin script */ - if G_UNLIKELY (gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_POSTLOGIN), - login, pwent, - TRUE /* pass_stdout */) != EXIT_SUCCESS && - /* ignore errors in failsafe modes */ - ! failsafe) { - gdm_verify_cleanup (d); - gdm_error (_("%s: Execution of PostLogin script returned > 0. Aborting."), "gdm_slave_session_start"); - /* script failed so just try again */ - return; - } - - /* - * Set euid, gid to user before testing for user's $HOME since root - * does not always have access to the user's $HOME directory. - */ - if G_UNLIKELY (setegid (pwent->pw_gid) != 0 || - seteuid (pwent->pw_uid) != 0) { - gdm_error ("Cannot set effective user/group id"); - gdm_verify_cleanup (d); - session_started = FALSE; - return; - } - - if G_UNLIKELY (pwent->pw_dir == NULL || - ! g_file_test (pwent->pw_dir, G_FILE_TEST_IS_DIR)) { - char *yesno_msg; - char *msg = g_strdup_printf ( - _("Your home directory is listed as: '%s' " - "but it does not appear to exist. " - "Do you want to log in with the / (root) " - "directory as your home directory? " - "It is unlikely anything will work unless " - "you use a failsafe session."), - ve_sure_string (pwent->pw_dir)); - - /* Set euid, egid to root:gdm to manage user interaction */ - seteuid (0); - setegid (gdm_daemon_config_get_gdmgid ()); - - gdm_error (_("%s: Home directory for %s: '%s' does not exist!"), - "gdm_slave_session_start", - login, - ve_sure_string (pwent->pw_dir)); - - /* Check what the user wants to do */ - yesno_msg = g_strdup_printf ("yesno_msg=%s", msg); - gdm_slave_send_string (GDM_SOP_SHOW_YESNO_DIALOG, yesno_msg); - - g_free (yesno_msg); - - if (strcmp (gdm_ack_response, "no") == 0) { - gdm_verify_cleanup (d); - session_started = FALSE; - - g_free (msg); - g_free (gdm_ack_response); - gdm_ack_response = NULL; - return; - } - - g_free (msg); - g_free (gdm_ack_response); - gdm_ack_response = NULL; - - /* Reset euid, egid back to user */ - if G_UNLIKELY (setegid (pwent->pw_gid) != 0 || - seteuid (pwent->pw_uid) != 0) { - gdm_error ("Cannot set effective user/group id"); - gdm_verify_cleanup (d); - session_started = FALSE; - return; - } - - home_dir_ok = FALSE; - home_dir = "/"; - } else { - home_dir_ok = TRUE; - home_dir = pwent->pw_dir; - } - - if G_LIKELY (home_dir_ok) { - /* Sanity check on ~user/.dmrc */ - usrcfgok = gdm_file_check ("gdm_slave_session_start", pwent->pw_uid, - home_dir, ".dmrc", TRUE, FALSE, - gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE), - gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM)); - } else { - usrcfgok = FALSE; - } - - if G_LIKELY (usrcfgok) { - gdm_daemon_config_get_user_session_lang (&usrsess, &usrlang, home_dir, &savesess); - } else { - /* This won't get displayed if the .dmrc file simply doesn't - * exist since we pass absentok=TRUE when we call gdm_file_check - */ - gdm_errorgui_error_box (d, - GTK_MESSAGE_WARNING, - _("User's $HOME/.dmrc file is being ignored. " - "This prevents the default session " - "and language from being saved. File " - "should be owned by user and have 644 " - "permissions. User's $HOME directory " - "must be owned by user and not writable " - "by other users.")); - usrsess = g_strdup (""); - usrlang = g_strdup (""); - } - - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - - if (greet) { - tmp = gdm_ensure_extension (usrsess, ".desktop"); - session = gdm_slave_greeter_ctl (GDM_SESS, tmp); - g_free (tmp); - - if (session != NULL && - strcmp (session, GDM_RESPONSE_CANCEL) == 0) { - gdm_debug ("User canceled login"); - gdm_verify_cleanup (d); - session_started = FALSE; - g_free (usrlang); - return; - } - - language = gdm_slave_greeter_ctl (GDM_LANG, usrlang); - if (language != NULL && - strcmp (language, GDM_RESPONSE_CANCEL) == 0) { - gdm_debug ("User canceled login"); - gdm_verify_cleanup (d); - session_started = FALSE; - g_free (usrlang); - return; - } - } else { - session = g_strdup (usrsess); - language = g_strdup (usrlang); - } - - tmp = gdm_strip_extension (session, ".desktop"); - g_free (session); - session = tmp; - - if (ve_string_empty (session)) { - g_free (session); - session = find_a_session (); - if (session == NULL) { - /* we're running out of options */ - session = g_strdup (GDM_SESSION_FAILSAFE_GNOME); - } - } - - if G_LIKELY (ve_string_empty (language)) { - g_free (language); - language = NULL; - } - - g_free (usrsess); - - gdm_debug ("Initial setting: session: '%s' language: '%s'\n", - session, ve_sure_string (language)); - - /* save this session as the users session */ - save_session = g_strdup (session); - - if (greet) { - char *ret = gdm_slave_greeter_ctl (GDM_SSESS, ""); - if ( ! ve_string_empty (ret)) - savesess = TRUE; - g_free (ret); - - ret = gdm_slave_greeter_ctl (GDM_SLANG, ""); - if ( ! ve_string_empty (ret)) - savelang = TRUE; - g_free (ret); - - gdm_debug ("gdm_slave_session_start: Authentication completed. Whacking greeter"); - - gdm_slave_whack_greeter (); - } - - if (gdm_daemon_config_get_value_bool (GDM_KEY_KILL_INIT_CLIENTS)) - gdm_server_whack_clients (d->dsp); - - /* Now that we will set up the user authorization we will - need to run session_stop to whack it */ - session_started = TRUE; - - /* Setup cookie -- We need this information during cleanup, thus - * cookie handling is done before fork()ing */ - - if G_UNLIKELY (setegid (pwent->pw_gid) != 0 || - seteuid (pwent->pw_uid) != 0) { - gdm_error ("Cannot set effective user/group id"); - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - - authok = gdm_auth_user_add (d, pwent->pw_uid, - /* Only pass the home_dir if - * it was ok */ - home_dir_ok ? home_dir : NULL); - - /* FIXME: this should be smarter and only do this on out-of-diskspace - * errors */ - if G_UNLIKELY ( ! authok && home_dir_ok) { - /* try wiping the .xsession-errors file (and perhaps other things) - in an attempt to gain disk space */ - if (wipe_xsession_errors (pwent, home_dir, home_dir_ok)) { - gdm_error ("Tried wiping some old user session errors files " - "to make disk space and will try adding user auth " - "files again"); - /* Try again */ - authok = gdm_auth_user_add (d, pwent->pw_uid, - /* Only pass the home_dir if - * it was ok */ - home_dir_ok ? home_dir : NULL); - } - } - - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - - if G_UNLIKELY ( ! authok) { - gdm_debug ("gdm_slave_session_start: Auth not OK"); - - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("GDM could not write to your authorization " - "file. This could mean that you are out of " - "disk space or that your home directory could " - "not be opened for writing. In any case, it " - "is not possible to log in. Please contact " - "your system administrator")); - - gdm_slave_session_stop (FALSE /* run_post_session */, - FALSE /* no_shutdown_check */); - - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - - if G_UNLIKELY (strcmp (session, GDM_SESSION_FAILSAFE_GNOME) == 0 || - strcmp (session, GDM_SESSION_FAILSAFE_XTERM) == 0 || - g_ascii_strcasecmp (session, "failsafe") == 0 /* hack */) - failsafe = TRUE; - - if G_LIKELY ( ! failsafe) { - char *exec = gdm_daemon_config_get_session_exec (session, FALSE /* check_try_exec */); - if ( ! ve_string_empty (exec) && - strcmp (exec, "failsafe") == 0) - failsafe = TRUE; - g_free (exec); - } - - /* Write out the Xservers file */ - gdm_slave_send_num (GDM_SOP_WRITE_X_SERVERS, 0 /* bogus */); - - if G_LIKELY (d->dsp != NULL) { - Cursor xcursor; - - XSetInputFocus (d->dsp, PointerRoot, - RevertToPointerRoot, CurrentTime); - - /* return left pointer */ - xcursor = XCreateFontCursor (d->dsp, GDK_LEFT_PTR); - XDefineCursor (d->dsp, - DefaultRootWindow (d->dsp), - xcursor); - XFreeCursor (d->dsp, xcursor); - XSync (d->dsp, False); - } - - /* Init the ~/.xsession-errors stuff */ - d->xsession_errors_bytes = 0; - d->xsession_errors_fd = -1; - d->session_output_fd = -1; - - logfilefd = open_xsession_errors (pwent, - failsafe, - home_dir, - home_dir_ok); - if G_UNLIKELY (logfilefd < 0 || - pipe (logpipe) != 0) { - if (logfilefd >= 0) - VE_IGNORE_EINTR (close (logfilefd)); - logfilefd = -1; - } - - /* don't completely rely on this, the user - * could reset time or do other crazy things */ - session_start_time = time (NULL); - -#ifdef WITH_CONSOLE_KIT - ck_session_cookie = open_ck_session (pwent, d, session); -#endif - - g_debug ("Forking user session"); - - /* Start user process */ - gdm_sigchld_block_push (); - gdm_sigterm_block_push (); - pid = d->sesspid = fork (); - if (pid == 0) - gdm_unset_signals (); - gdm_sigterm_block_pop (); - gdm_sigchld_block_pop (); - - switch (pid) { - - case -1: - gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Error forking user session"), "gdm_slave_session_start"); - - case 0: - { - const char *gdm_system_locale; - const char *lang; - gboolean has_language; - - has_language = (language != NULL) && (language[0] != '\0'); - - gdm_system_locale = setlocale (LC_CTYPE, NULL); - if ((gdm_system_locale != NULL) && (!has_language)) { - lang = gdm_system_locale; - } else { - lang = language; - } - - if G_LIKELY (logfilefd >= 0) { - VE_IGNORE_EINTR (close (logpipe[0])); - } - /* Never returns */ - session_child_run (pwent, - logpipe[1], - failsafe, - home_dir, - home_dir_ok, -#ifdef WITH_CONSOLE_KIT - ck_session_cookie, -#endif - session, - save_session, - lang, - gnome_session, - usrcfgok, - savesess, - savelang); - g_assert_not_reached (); - } - - default: - always_restart_greeter = FALSE; - if (!savelang && language && strcmp (usrlang, language)) { - const char *gdm_system_locale; - - gdm_system_locale = setlocale (LC_CTYPE, NULL); - - if (gdm_system_locale != NULL) { - g_setenv ("LANG", gdm_system_locale, TRUE); - setlocale (LC_ALL, ""); - g_unsetenv ("GDM_LANG"); - /* for "GDM_LANG" */ - gdm_clearenv_no_lang (); - gdm_saveenv (); - } - gdm_slave_greeter_ctl_no_ret (GDM_SETLANG, DEFAULT_LANGUAGE); - } - break; - } - - /* this clears internal cache */ - gdm_daemon_config_get_session_exec (NULL, FALSE); - - if G_LIKELY (logfilefd >= 0) { - d->xsession_errors_fd = logfilefd; - d->session_output_fd = logpipe[0]; - /* make the output read fd non-blocking */ - fcntl (d->session_output_fd, F_SETFL, O_NONBLOCK); - VE_IGNORE_EINTR (close (logpipe[1])); - } - - /* We must be root for this, and we are, but just to make sure */ - NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ()); - /* Reset all the process limits, pam may have set some up for our process and that - is quite evil. But pam is generally evil, so this is to be expected. */ - gdm_reset_limits (); - - g_free (session); - g_free (save_session); - g_free (language); - g_free (gnome_session); - - gdm_slave_send_num (GDM_SOP_SESSPID, pid); - - gdm_sigchld_block_push (); - wp = slave_waitpid_setpid (d->sesspid); - gdm_sigchld_block_pop (); - - slave_waitpid (wp); - - d->sesspid = 0; - - /* finish reading the session output if any of it is still there */ - finish_session_output (TRUE); - - /* Now still as root make the system authfile readable by others, - and therefore by the gdm user */ - VE_IGNORE_EINTR (g_chmod (GDM_AUTHFILE (d), 0644)); - - end_time = time (NULL); - - gdm_debug ("Session: start_time: %ld end_time: %ld", - (long)session_start_time, (long)end_time); - - /* 66 is a very magical number signifying failure in GDM */ - if G_UNLIKELY ((d->last_sess_status != 66) && - (/* sanity */ end_time >= session_start_time) && - (end_time - 10 <= session_start_time) && - /* only if the X server still exist! */ - d->servpid > 1) { - char *msg_string; - char *error_msg = - _("Your session only lasted less than " - "10 seconds. If you have not logged out " - "yourself, this could mean that there is " - "some installation problem or that you may " - "be out of diskspace. Try logging in with " - "one of the failsafe sessions to see if you " - "can fix this problem."); - - /* FIXME: perhaps do some checking to display a better error, - * such as gnome-session missing and such things. */ - gdm_debug ("Session less than 10 seconds!"); - msg_string = g_strdup_printf ("type=%d$$error_msg=%s$$details_label=%s$$details_file=%s$$uid=%d$$gid=%d", - GTK_MESSAGE_WARNING,error_msg, - (d->xsession_errors_filename != NULL) ? - _("View details (~/.xsession-errors file)") : - NULL, - d->xsession_errors_filename, - 0, 0); - - gdm_slave_send_string (GDM_SOP_SHOW_ERROR_DIALOG, msg_string); - - g_free (msg_string); - - } - -#ifdef WITH_CONSOLE_KIT - if (ck_session_cookie != NULL) { - close_ck_session (ck_session_cookie); - g_free (ck_session_cookie); - } -#endif - - gdm_slave_session_stop (pid != 0 /* run_post_session */, - FALSE /* no_shutdown_check */); - - gdm_debug ("gdm_slave_session_start: Session ended OK (now all finished)"); -} - - -/* Stop any in progress sessions */ -static void -gdm_slave_session_stop (gboolean run_post_session, - gboolean no_shutdown_check) -{ - struct passwd *pwent; - char *x_servers_file; - char *local_login; - - in_session_stop++; - - session_started = FALSE; - - local_login = login; - login = NULL; - - /* don't use NEVER_FAILS_ here this can be called from places - kind of exiting and it's ok if this doesn't work (when shouldn't - it work anyway? */ - seteuid (0); - setegid (0); - - gdm_slave_send_num (GDM_SOP_SESSPID, 0); - - /* Now still as root make the system authfile not readable by others, - and therefore not by the gdm user */ - if (GDM_AUTHFILE (d) != NULL) { - VE_IGNORE_EINTR (g_chmod (GDM_AUTHFILE (d), 0640)); - } - - gdm_debug ("gdm_slave_session_stop: %s on %s", local_login, d->name); - - /* Note we use the info in the structure here since if we get passed - * a 0 that means the process is already dead. - * FIXME: Maybe we should waitpid here, note make sure this will - * not create a hang! */ - gdm_sigchld_block_push (); - if (d->sesspid > 1) - kill (- (d->sesspid), SIGTERM); - gdm_sigchld_block_pop (); - - finish_session_output (run_post_session /* do_read */); - - if (local_login == NULL) - pwent = NULL; - else - pwent = getpwnam (local_login); /* PAM overwrites our pwent */ - - x_servers_file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), - d->name, ".Xservers"); - - /* if there was a session that ran, run the PostSession script */ - if (run_post_session) { - /* Execute post session script */ - gdm_debug ("gdm_slave_session_stop: Running post session script"); - gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_POSTSESSION), local_login, pwent, - FALSE /* pass_stdout */); - } - - VE_IGNORE_EINTR (g_unlink (x_servers_file)); - g_free (x_servers_file); - - g_free (local_login); - - if (pwent != NULL) { - seteuid (0); /* paranoia */ - /* Remove display from ~user/.Xauthority */ - if G_LIKELY (setegid (pwent->pw_gid) == 0 && - seteuid (pwent->pw_uid) == 0) { - gdm_auth_user_remove (d, pwent->pw_uid); - } - - /* don't use NEVER_FAILS_ here this can be called from places - kind of exiting and it's ok if this doesn't work (when shouldn't - it work anyway? */ - seteuid (0); - setegid (0); - } - - logged_in_uid = -1; - logged_in_gid = -1; - - /* things are going to be killed, so ignore errors */ - XSetErrorHandler (ignore_xerror_handler); - - gdm_verify_cleanup (d); - - in_session_stop --; - - if (need_to_quit_after_session_stop) { - gdm_debug ("gdm_slave_session_stop: Final cleanup"); - - gdm_slave_quick_exit (exit_code_to_use); - } - -#ifdef __linux__ - /* If on Linux and the runlevel is 0 or 6 and not the runlevel that - we were started in, then we are restarting or halting the machine. - Probably the user selected halt or restart from the logout - menu. In this case we can really just sleep for a few seconds and - basically wait to be killed. I will set the default for 30 seconds - and let people yell at me if this breaks something. It shouldn't. - In fact it should fix things so that the login screen is not brought - up again and then whacked. Waiting is safer then DISPLAY_ABORT, - since if we really do get this wrong, then at the worst case the - user will wait for a few moments. */ - if ( ! need_to_quit_after_session_stop && - ! no_shutdown_check && - g_access ("/sbin/runlevel", X_OK) == 0) { - int rnl = get_runlevel (); - if ((rnl == 0 || rnl == 6) && rnl != gdm_normal_runlevel) { - /* this is a stupid loop, but we may be getting signals, - so we don't want to just do sleep (30) */ - time_t c = time (NULL); - gdm_info (_("GDM detected a halt or restart " - "in progress.")); - while (c + 30 >= time (NULL)) { - struct timeval tv; - /* Wait 30 seconds. */ - tv.tv_sec = 30; - tv.tv_usec = 0; - select (0, NULL, NULL, NULL, &tv); - /* don't want to use sleep since we're using alarm - for pinging */ - } - /* hmm, didn't get TERM, weird */ - } - } -#endif /* __linux__ */ -} - -static void -gdm_slave_term_handler (int sig) -{ - static gboolean got_term_before = FALSE; - - gdm_in_signal++; - gdm_wait_for_ack = FALSE; - - exit_code_to_use = DISPLAY_ABORT; - need_to_quit_after_session_stop = TRUE; - - if (already_in_slave_start_jmp || - (got_term_before && in_session_stop > 0)) { - gdm_sigchld_block_push (); - /* be very very very nasty to the extra process if the user is really - trying to get rid of us */ - if (extra_process > 1) - kill (-(extra_process), SIGKILL); - /* also be very nasty to the X server at this stage */ - if (d->servpid > 1) - kill (d->servpid, SIGKILL); - gdm_sigchld_block_pop (); - gdm_in_signal--; - got_term_before = TRUE; - /* we're already quitting, just a matter of killing all the processes */ - return; - } - got_term_before = TRUE; - - /* just in case this was set to something else, like during - * server reinit */ - XSetIOErrorHandler (gdm_slave_xioerror_handler); - - if (in_session_stop > 0) { - /* the need_to_quit_after_session_stop is now set so things will - work out right */ - gdm_in_signal--; - return; - } - - if (session_started) { - SIGNAL_EXIT_WITH_JMP (d, JMP_SESSION_STOP_AND_QUIT); - } else { - SIGNAL_EXIT_WITH_JMP (d, JMP_JUST_QUIT_QUICKLY); - } - - /* never reached */ - gdm_in_signal--; -} - -/* called on alarms to ping */ -static void -gdm_slave_alrm_handler (int sig) -{ - static gboolean in_ping = FALSE; - - if G_UNLIKELY (already_in_slave_start_jmp) - return; - - gdm_in_signal++; - - if G_UNLIKELY (d->dsp == NULL) { - gdm_in_signal --; - /* huh? */ - return; - } - - if G_UNLIKELY (in_ping) { - need_to_quit_after_session_stop = TRUE; - exit_code_to_use = DISPLAY_REMANAGE; - - if (session_started) { - SIGNAL_EXIT_WITH_JMP (d, JMP_SESSION_STOP_AND_QUIT); - } else { - SIGNAL_EXIT_WITH_JMP (d, JMP_JUST_QUIT_QUICKLY); - } - } - - in_ping = TRUE; - - /* schedule next alarm */ - alarm (gdm_daemon_config_get_value_int (GDM_KEY_PING_INTERVAL)); - - XSync (d->dsp, True); - - in_ping = FALSE; - - gdm_in_signal --; -} - -/* Called on every SIGCHLD */ -void -gdm_slave_child_handler (int sig) -{ - gint status; - pid_t pid; - uid_t old; - - if G_UNLIKELY (already_in_slave_start_jmp) - return; - - gdm_in_signal++; - - old = geteuid (); - if (old != 0) - seteuid (0); - - while ((pid = waitpid (-1, &status, WNOHANG)) > 0) { - GSList *li; - - for (li = slave_waitpids; li != NULL; li = li->next) { - GdmWaitPid *wp = li->data; - if (wp->pid == pid) { - wp->pid = -1; - if (slave_waitpid_w >= 0) { - VE_IGNORE_EINTR (write (slave_waitpid_w, "!", 1)); - } - } - } - - if (pid == d->greetpid && greet) { - if (WIFEXITED (status) && - WEXITSTATUS (status) == DISPLAY_RESTARTGREETER) { - /* FIXME: shouldn't do this from - a signal handler */ - /*gdm_slave_desensitize_config ();*/ - - greet = FALSE; - d->greetpid = 0; - whack_greeter_fds (); - gdm_slave_send_num (GDM_SOP_GREETPID, 0); - - do_restart_greeter = TRUE; - if (restart_greeter_now) { - slave_waitpid_notify (); - } else { - interrupted = TRUE; - } - continue; - } - - whack_greeter_fds (); - - /* if greet is TRUE, then the greeter died outside of our - * control really, so clean up and die, something is wrong - * The greeter is only allowed to pass back these - * exit codes, else we'll just remanage */ - if (WIFEXITED (status) && - (WEXITSTATUS (status) == DISPLAY_ABORT || - WEXITSTATUS (status) == DISPLAY_REBOOT || - WEXITSTATUS (status) == DISPLAY_HALT || - WEXITSTATUS (status) == DISPLAY_SUSPEND || - WEXITSTATUS (status) == DISPLAY_RUN_CHOOSER || - WEXITSTATUS (status) == DISPLAY_RESTARTGDM || - WEXITSTATUS (status) == DISPLAY_GREETERFAILED)) { - exit_code_to_use = WEXITSTATUS (status); - SIGNAL_EXIT_WITH_JMP (d, JMP_JUST_QUIT_QUICKLY); - } else { - if (WIFSIGNALED (status) && - (WTERMSIG (status) == SIGSEGV || - WTERMSIG (status) == SIGABRT || - WTERMSIG (status) == SIGPIPE || - WTERMSIG (status) == SIGBUS)) { - exit_code_to_use = DISPLAY_GREETERFAILED; - SIGNAL_EXIT_WITH_JMP (d, JMP_JUST_QUIT_QUICKLY); - } else { - /* weird error return, interpret as failure */ - if (WIFEXITED (status) && - WEXITSTATUS (status) == 1) - exit_code_to_use = DISPLAY_GREETERFAILED; - SIGNAL_EXIT_WITH_JMP (d, JMP_JUST_QUIT_QUICKLY); - } - } - } else if (pid != 0 && pid == d->sesspid) { - d->sesspid = 0; - if (WIFEXITED (status)) - d->last_sess_status = WEXITSTATUS (status); - else - d->last_sess_status = -1; - } else if (pid != 0 && pid == d->chooserpid) { - d->chooserpid = 0; - } else if (pid != 0 && pid == d->servpid) { - if (d->servstat == SERVER_RUNNING) - gdm_server_whack_lockfile (d); - d->servstat = SERVER_DEAD; - d->servpid = 0; - gdm_server_wipe_cookies (d); - gdm_slave_whack_temp_auth_file (); - - gdm_slave_send_num (GDM_SOP_XPID, 0); - - /* whack the session good */ - if (d->sesspid > 1) { - gdm_slave_send_num (GDM_SOP_SESSPID, 0); - kill (- (d->sesspid), SIGTERM); - } - if (d->greetpid > 1) { - gdm_slave_send_num (GDM_SOP_GREETPID, 0); - kill (d->greetpid, SIGTERM); - } - if (d->chooserpid > 1) { - gdm_slave_send_num (GDM_SOP_CHOOSERPID, 0); - kill (d->chooserpid, SIGTERM); - } - - /* just in case we restart again wait at least - one sec to avoid races */ - if (d->sleep_before_run < 1) - d->sleep_before_run = 1; - } else if (pid == extra_process) { - /* an extra process died, yay! */ - extra_process = 0; - extra_status = status; - } - } - if (old != 0) - seteuid (old); - - gdm_in_signal--; -} - -static void -gdm_slave_handle_usr2_message (void) -{ - char buf[256]; - ssize_t count; - char **vec; - int i; - - VE_IGNORE_EINTR (count = read (d->slave_notify_fd, buf, sizeof (buf) -1)); - if (count <= 0) { - return; - } - - buf[count] = '\0'; - - vec = g_strsplit (buf, "\n", -1); - if (vec == NULL) { - return; - } - - for (i = 0; vec[i] != NULL; i++) { - char *s = vec[i]; - if (s[0] == GDM_SLAVE_NOTIFY_ACK) { - gdm_got_ack = TRUE; - g_free (gdm_ack_response); - if (s[1] != '\0') - gdm_ack_response = g_strdup (&s[1]); - else - gdm_ack_response = NULL; - } else if (s[0] == GDM_SLAVE_NOTIFY_KEY) { - slave_waitpid_notify (); - unhandled_notifies = - g_list_append (unhandled_notifies, - g_strdup (&s[1])); - } else if (s[0] == GDM_SLAVE_NOTIFY_COMMAND) { - if (strcmp (&s[1], GDM_NOTIFY_DIRTY_SERVERS) == 0) { - /* never restart flexi servers - * they whack themselves */ - if (!SERVER_IS_FLEXI (d)) - remanage_asap = TRUE; - } else if (strcmp (&s[1], GDM_NOTIFY_SOFT_RESTART_SERVERS) == 0) { - /* never restart flexi servers, - * they whack themselves */ - /* FIXME: here we should handle actual - * restarts of flexi servers, but it probably - * doesn't matter */ - if (!SERVER_IS_FLEXI (d)) { - if ( ! d->logged_in) { - if (gdm_in_signal > 0) { - exit_code_to_use = DISPLAY_REMANAGE; - SIGNAL_EXIT_WITH_JMP (d, JMP_JUST_QUIT_QUICKLY); - } else { - /* FIXME: are we ever not in signal here? */ - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } - } else { - remanage_asap = TRUE; - } - } - } else if (strcmp (&s[1], GDM_NOTIFY_GO) == 0) { - gdm_wait_for_go = FALSE; - } else if (strcmp (&s[1], GDM_NOTIFY_TWIDDLE_POINTER) == 0) { - gdm_twiddle_pointer (d); - } - } else if (s[0] == GDM_SLAVE_NOTIFY_RESPONSE) { - gdm_got_ack = TRUE; - if (gdm_ack_response) - g_free (gdm_ack_response); - - if (s[1] == GDM_SLAVE_NOTIFY_YESNO_RESPONSE) { - if (s[2] == '0') { - gdm_ack_response = g_strdup ("no"); - } else { - gdm_ack_response = g_strdup ("yes"); - } - } else if (s[1] == GDM_SLAVE_NOTIFY_ASKBUTTONS_RESPONSE) { - gdm_ack_response = g_strdup (&s[2]); - } else if (s[1] == GDM_SLAVE_NOTIFY_QUESTION_RESPONSE) { - gdm_ack_question_response = g_strdup (&s[2]); - } else if (s[1] == GDM_SLAVE_NOTIFY_ERROR_RESPONSE) { - if (s[2] != '\0') { - gdm_ack_response = g_strdup (&s[2]); - } else { - gdm_ack_response = NULL; - } - } - } - } - - g_strfreev (vec); -} - -static void -gdm_slave_usr2_handler (int sig) -{ - gdm_in_signal++; - in_usr2_signal++; - - gdm_slave_handle_usr2_message (); - - in_usr2_signal--; - gdm_in_signal--; -} - -/* Minor X faults */ -static gint -gdm_slave_xerror_handler (Display *disp, XErrorEvent *evt) -{ - gdm_debug ("gdm_slave_xerror_handler: X error - display doesn't respond"); - return (0); -} - -/* We usually respond to fatal errors by restarting the display */ -static gint -gdm_slave_xioerror_handler (Display *disp) -{ - if (already_in_slave_start_jmp) { - /* eki eki eki, this is not good, - should only happen if we get some io error after - we have gotten a SIGTERM */ - SIGNAL_EXIT_WITH_JMP (d, JMP_JUST_QUIT_QUICKLY); - } - - gdm_in_signal++; - - /* Display is all gone */ - d->dsp = NULL; - - if ((d->type == TYPE_STATIC || - d->type == TYPE_FLEXI) && - (do_xfailed_on_xio_error || - d->starttime + 5 >= time (NULL))) { - exit_code_to_use = DISPLAY_XFAILED; - } else { - exit_code_to_use = DISPLAY_REMANAGE; - } - - slave_start_jmp_error_to_print = - g_strdup_printf (_("%s: Fatal X error - Restarting %s"), - "gdm_slave_xioerror_handler", d->name); - - need_to_quit_after_session_stop = TRUE; - - if (session_started) { - SIGNAL_EXIT_WITH_JMP (d, JMP_SESSION_STOP_AND_QUIT); - } else { - SIGNAL_EXIT_WITH_JMP (d, JMP_JUST_QUIT_QUICKLY); - } - - /* never reached */ - gdm_in_signal--; - - return 0; -} - -/* return true for "there was an interruption received", - and interrupted will be TRUE if we are actually interrupted from doing what - we want. If FALSE is returned, just continue on as we would normally */ -static gboolean -check_for_interruption (const char *msg) -{ - /* Hell yeah we were interrupted, the greeter died */ - if (msg == NULL) { - interrupted = TRUE; - return TRUE; - } - - if (msg[0] == BEL) { - /* Different interruptions come here */ - /* Note that we don't want to actually do anything. We want - * to just set some flag and go on and schedule it after we - * dump out of the login in the main login checking loop */ - switch (msg[1]) { - case GDM_INTERRUPT_TIMED_LOGIN: - /* only allow timed login if display is local, - * it is allowed for this display (it's only allowed - * for the first local display) and if it's set up - * correctly */ - if ((d->attached || gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN)) - && d->timed_login_ok && - ! ve_string_empty (ParsedTimedLogin) && - strcmp (ParsedTimedLogin, gdm_root_user ()) != 0 && - gdm_daemon_config_get_value_int (GDM_KEY_TIMED_LOGIN_DELAY) > 0) { - do_timed_login = TRUE; - } - break; - case GDM_INTERRUPT_CONFIGURE: - if (d->attached && - gdm_daemon_config_get_value_bool_per_display (GDM_KEY_CONFIG_AVAILABLE, d->name) && - gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name) && - ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_CONFIGURATOR))) { - do_configurator = TRUE; - } - break; - case GDM_INTERRUPT_SUSPEND: - if (d->attached && - gdm_daemon_config_get_value_bool_per_display (GDM_KEY_SYSTEM_MENU, d->name) && - ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) { - gchar *msg = g_strdup_printf ("%s %ld", - GDM_SOP_SUSPEND_MACHINE, - (long)getpid ()); - - gdm_slave_send (msg, FALSE /* wait_for_ack */); - g_free (msg); - } - /* Not interrupted, continue reading input, - * just proxy this to the master server */ - return TRUE; - case GDM_INTERRUPT_LOGIN_SOUND: - if (d->attached && - ! play_login_sound (gdm_daemon_config_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FILE))) { - gdm_error (_("Login sound requested on non-local display or the play software " - "cannot be run or the sound does not exist")); - } - return TRUE; - case GDM_INTERRUPT_SELECT_USER: - gdm_verify_select_user (&msg[2]); - break; - case GDM_INTERRUPT_CANCEL: - do_cancel = TRUE; - break; - case GDM_INTERRUPT_CUSTOM_CMD: - if (d->attached && - ! ve_string_empty (&msg[2])) { - gchar *message = g_strdup_printf ("%s %ld %s", - GDM_SOP_CUSTOM_CMD, - (long)getpid (), &msg[2]); - - gdm_slave_send (message, TRUE); - g_free (message); - } - return TRUE; - case GDM_INTERRUPT_THEME: - g_free (d->theme_name); - d->theme_name = NULL; - if ( ! ve_string_empty (&msg[2])) - d->theme_name = g_strdup (&msg[2]); - gdm_slave_send_string (GDM_SOP_CHOSEN_THEME, &msg[2]); - return TRUE; - case GDM_INTERRUPT_SELECT_LANG: - if (msg + 2) { - const char *locale; - const char *gdm_system_locale; - - locale = (gchar*)(msg + 3); - gdm_system_locale = setlocale (LC_CTYPE, NULL); - - always_restart_greeter = (gboolean)(*(msg + 2)); - ve_clearenv (); - if (!strcmp (locale, DEFAULT_LANGUAGE)) { - locale = gdm_system_locale; - } - g_setenv ("GDM_LANG", locale, TRUE); - g_setenv ("LANG", locale, TRUE); - g_unsetenv ("LC_ALL"); - g_unsetenv ("LC_MESSAGES"); - setlocale (LC_ALL, ""); - setlocale (LC_MESSAGES, ""); - gdm_saveenv (); - - do_restart_greeter = TRUE; - } - break; - default: - break; - } - - /* this was an interruption, if it wasn't - * handled then the user will just get an error as if he - * entered an invalid login or passward. Seriously BEL - * cannot be part of a login/password really */ - interrupted = TRUE; - return TRUE; - } - return FALSE; -} - - -char * -gdm_slave_greeter_ctl (char cmd, const char *str) -{ - char *buf = NULL; - int c; - - /* There is no spoon^H^H^H^H^Hgreeter */ - if G_UNLIKELY ( ! greet) - return NULL; - - check_notifies_now (); - - if ( ! ve_string_empty (str)) { - gdm_fdprintf (greeter_fd_out, "%c%c%s\n", STX, cmd, str); - } else { - gdm_fdprintf (greeter_fd_out, "%c%c\n", STX, cmd); - } - -#if defined (_POSIX_PRIORITY_SCHEDULING) && defined (HAVE_SCHED_YIELD) - /* let the other process (greeter) do its stuff */ - sched_yield (); -#endif - - do { - g_free (buf); - buf = NULL; - /* Skip random junk that might have accumulated */ - do { - c = gdm_fdgetc (greeter_fd_in); - } while (c != EOF && c != STX); - - if (c == EOF || - (buf = gdm_fdgets (greeter_fd_in)) == NULL) { - interrupted = TRUE; - /* things don't seem well with the greeter, it probably died */ - return NULL; - } - } while (check_for_interruption (buf) && ! interrupted); - - /* user responses take kind of random amount of time */ - gdm_random_tick (); - - if ( ! ve_string_empty (buf)) { - return buf; - } else { - g_free (buf); - return NULL; - } -} - -void -gdm_slave_greeter_ctl_no_ret (char cmd, const char *str) -{ - g_free (gdm_slave_greeter_ctl (cmd, str)); -} - -static void -gdm_slave_quick_exit (gint status) -{ - /* just for paranoia's sake */ - /* don't use NEVER_FAILS_ here this can be called from places - kind of exiting and it's ok if this doesn't work (when shouldn't - it work anyway? */ - seteuid (0); - setegid (0); - - if (d != NULL) { - gdm_debug ("gdm_slave_quick_exit: Will kill everything from the display"); - - /* just in case we do get the XIOError, - don't run session_stop since we've - requested a quick exit */ - session_started = FALSE; - - /* No need to send the PIDS to the daemon - * since we'll just exit cleanly */ - - /* Push and never pop */ - gdm_sigchld_block_push (); - - /* Kill children where applicable */ - if (d->greetpid > 1) - kill (d->greetpid, SIGTERM); - d->greetpid = 0; - - if (d->chooserpid > 1) - kill (d->chooserpid, SIGTERM); - d->chooserpid = 0; - - if (d->sesspid > 1) - kill (-(d->sesspid), SIGTERM); - d->sesspid = 0; - - if (extra_process > 1) - kill (-(extra_process), SIGTERM); - extra_process = 0; - - gdm_verify_cleanup (d); - gdm_server_stop (d); - - if (d->servpid > 1) - kill (d->servpid, SIGTERM); - d->servpid = 0; - - gdm_debug ("gdm_slave_quick_exit: Killed everything from the display"); - } - - _exit (status); -} - -static void -gdm_slave_exit (gint status, const gchar *format, ...) -{ - va_list args; - gchar *s; - - va_start (args, format); - s = g_strdup_vprintf (format, args); - va_end (args); - - gdm_error ("%s", s); - - g_free (s); - - gdm_slave_quick_exit (status); -} - -static void -gdm_child_exit (gint status, const gchar *format, ...) -{ - va_list args; - gchar *s; - - va_start (args, format); - s = g_strdup_vprintf (format, args); - va_end (args); - - g_error ("%s", s); - - g_free (s); - - _exit (status); -} - -void -gdm_slave_whack_temp_auth_file (void) -{ - uid_t old; - - old = geteuid (); - if (old != 0) - seteuid (0); - if (d->parent_temp_auth_file != NULL) { - VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file)); - } - g_free (d->parent_temp_auth_file); - d->parent_temp_auth_file = NULL; - if (old != 0) - seteuid (old); -} - -static void -create_temp_auth_file (void) -{ - if (d->type == TYPE_FLEXI_XNEST && - d->parent_auth_file != NULL) { - if (d->parent_temp_auth_file != NULL) { - VE_IGNORE_EINTR (g_unlink (d->parent_temp_auth_file)); - } - g_free (d->parent_temp_auth_file); - d->parent_temp_auth_file = - copy_auth_file (d->server_uid, - gdm_daemon_config_get_gdmuid (), - d->parent_auth_file); - } -} - -static void -set_xnest_parent_stuff (void) -{ - if (d->type == TYPE_FLEXI_XNEST) { - g_setenv ("GDM_PARENT_DISPLAY", d->parent_disp, TRUE); - if (d->parent_temp_auth_file != NULL) { - g_setenv ("GDM_PARENT_XAUTHORITY", - d->parent_temp_auth_file, TRUE); - g_free (d->parent_temp_auth_file); - d->parent_temp_auth_file = NULL; - } - } -} - -static gint -gdm_slave_exec_script (GdmDisplay *d, - const gchar *dir, - const char *login, - struct passwd *pwent, - gboolean pass_stdout) -{ - pid_t pid; - char *script; - gchar **argv; - gint status; - char *x_servers_file; - - if G_UNLIKELY (!d || ve_string_empty (dir)) - return EXIT_SUCCESS; - - script = g_build_filename (dir, d->name, NULL); - if (g_access (script, R_OK|X_OK) != 0) { - g_free (script); - script = NULL; - } - if (script == NULL && - ! ve_string_empty (d->hostname)) { - script = g_build_filename (dir, d->hostname, NULL); - if (g_access (script, R_OK|X_OK) != 0) { - g_free (script); - script = NULL; - } - } - if (script == NULL && - SERVER_IS_XDMCP (d)) { - script = g_build_filename (dir, "XDMCP", NULL); - if (g_access (script, R_OK|X_OK) != 0) { - g_free (script); - script = NULL; - } - } - if (script == NULL && - SERVER_IS_FLEXI (d)) { - script = g_build_filename (dir, "Flexi", NULL); - if (g_access (script, R_OK|X_OK) != 0) { - g_free (script); - script = NULL; - } - } - if (script == NULL) { - script = g_build_filename (dir, "Default", NULL); - if (g_access (script, R_OK|X_OK) != 0) { - g_free (script); - script = NULL; - } - } - - if (script == NULL) { - return EXIT_SUCCESS; - } - - create_temp_auth_file (); - - g_debug ("Forking extra process: %s", script); - - extra_process = pid = gdm_fork_extra (); - - switch (pid) { - case 0: - gdm_log_shutdown (); - - VE_IGNORE_EINTR (close (0)); - gdm_open_dev_null (O_RDONLY); /* open stdin - fd 0 */ - - if ( ! pass_stdout) { - VE_IGNORE_EINTR (close (1)); - VE_IGNORE_EINTR (close (2)); - /* No error checking here - if it's messed the best response - * is to ignore & try to continue */ - gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */ - gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */ - } - - gdm_close_all_descriptors (3 /* from */, -1 /* except */, -1 /* except2 */); - - gdm_log_init (); - - if (login != NULL) { - g_setenv ("LOGNAME", login, TRUE); - g_setenv ("USER", login, TRUE); - g_setenv ("USERNAME", login, TRUE); - } else { - const char *gdmuser = gdm_daemon_config_get_value_string (GDM_KEY_USER); - g_setenv ("LOGNAME", gdmuser, TRUE); - g_setenv ("USER", gdmuser, TRUE); - g_setenv ("USERNAME", gdmuser, TRUE); - } - if (pwent != NULL) { - if (ve_string_empty (pwent->pw_dir)) { - g_setenv ("HOME", "/", TRUE); - g_setenv ("PWD", "/", TRUE); - VE_IGNORE_EINTR (g_chdir ("/")); - } else { - g_setenv ("HOME", pwent->pw_dir, TRUE); - g_setenv ("PWD", pwent->pw_dir, TRUE); - VE_IGNORE_EINTR (g_chdir (pwent->pw_dir)); - if (errno != 0) { - VE_IGNORE_EINTR (g_chdir ("/")); - g_setenv ("PWD", "/", TRUE); - } - } - g_setenv ("SHELL", pwent->pw_shell, TRUE); - } else { - g_setenv ("HOME", "/", TRUE); - g_setenv ("PWD", "/", TRUE); - VE_IGNORE_EINTR (g_chdir ("/")); - g_setenv ("SHELL", "/bin/sh", TRUE); - } - - set_xnest_parent_stuff (); - - /* some env for use with the Pre and Post scripts */ - x_servers_file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), - d->name, ".Xservers"); - g_setenv ("X_SERVERS", x_servers_file, TRUE); - g_free (x_servers_file); - if (SERVER_IS_XDMCP (d)) - g_setenv ("REMOTE_HOST", d->hostname, TRUE); - - /* Runs as root */ - if (GDM_AUTHFILE (d) != NULL) - g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE); - else - g_unsetenv ("XAUTHORITY"); - g_setenv ("DISPLAY", d->name, TRUE); - g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE); - g_setenv ("RUNNING_UNDER_GDM", "true", TRUE); - if ( ! ve_string_empty (d->theme_name)) - g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE); - g_unsetenv ("MAIL"); - - argv = NULL; - g_shell_parse_argv (script, NULL, &argv, NULL); - - VE_IGNORE_EINTR (execv (argv[0], argv)); - g_error (_("%s: Failed starting: %s"), - "gdm_slave_exec_script", - script); - _exit (EXIT_SUCCESS); - - case -1: - gdm_slave_whack_temp_auth_file (); - g_free (script); - g_error (_("%s: Can't fork script process!"), "gdm_slave_exec_script"); - return EXIT_SUCCESS; - - default: - gdm_wait_for_extra (extra_process, &status); - - gdm_slave_whack_temp_auth_file (); - - g_free (script); - - if (WIFEXITED (status)) - return WEXITSTATUS (status); - else - return EXIT_SUCCESS; - } -} - -gboolean -gdm_slave_greeter_check_interruption (void) -{ - if (interrupted) { - /* no longer interrupted */ - interrupted = FALSE; - return TRUE; - } else { - return FALSE; - } -} - -gboolean -gdm_slave_action_pending (void) -{ - if (do_timed_login || - do_configurator || - do_restart_greeter || - do_cancel) - return FALSE; - return TRUE; -} - -/* The user name for automatic/timed login may be parameterized by - host/display. */ - -static gchar * -gdm_parse_enriched_login (const gchar *s, GdmDisplay *display) -{ - gchar cmd, in_buffer[20]; - GString *str; - gint pipe1[2], in_buffer_len; - gchar **argv; - pid_t pid; - - if (s == NULL) - return (NULL); - - str = g_string_new (NULL); - - while (s[0] != '\0') { - - if (s[0] == '%' && s[1] != 0) { - cmd = s[1]; - s++; - - switch (cmd) { - - case 'h': - g_string_append (str, display->hostname); - break; - - case 'd': - g_string_append (str, display->name); - break; - - case '%': - g_string_append_c (str, '%'); - break; - - default: - break; - }; - } else { - g_string_append_c (str, *s); - } - s++; - } - - /* Sometimes it is not convenient to use the display or hostname as - user name. A script may be used to generate the automatic/timed - login name based on the display/host by ending the name with the - pipe symbol '|'. */ - - if (str->len > 0 && str->str[str->len - 1] == '|') { - g_string_truncate (str, str->len - 1); - if G_UNLIKELY (pipe (pipe1) < 0) { - gdm_error (_("%s: Failed creating pipe"), - "gdm_parse_enriched_login"); - } else { - g_debug ("Forking extra process: %s", str->str); - - extra_process = pid = gdm_fork_extra (); - - switch (pid) { - case 0: - /* The child will write the username to stdout based on the DISPLAY - environment variable. */ - - VE_IGNORE_EINTR (close (pipe1[0])); - if G_LIKELY (pipe1[1] != STDOUT_FILENO) { - VE_IGNORE_EINTR (dup2 (pipe1[1], STDOUT_FILENO)); - } - - gdm_log_shutdown (); - - gdm_close_all_descriptors (3 /* from */, pipe1[1] /* except */, -1 /* except2 */); - - gdm_log_init (); - - /* runs as root */ - if (GDM_AUTHFILE (display) != NULL) - g_setenv ("XAUTHORITY", GDM_AUTHFILE (display), TRUE); - else - g_unsetenv ("XAUTHORITY"); - g_setenv ("DISPLAY", display->name, TRUE); - if (SERVER_IS_XDMCP (display)) - g_setenv ("REMOTE_HOST", display->hostname, TRUE); - g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE); - g_setenv ("SHELL", "/bin/sh", TRUE); - g_setenv ("RUNNING_UNDER_GDM", "true", TRUE); - if ( ! ve_string_empty (d->theme_name)) - g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE); - g_unsetenv ("MAIL"); - - argv = NULL; - g_shell_parse_argv (str->str, NULL, &argv, NULL); - - VE_IGNORE_EINTR (execv (argv[0], argv)); - gdm_error (_("%s: Failed executing: %s"), - "gdm_parse_enriched_login", - str->str); - _exit (EXIT_SUCCESS); - - case -1: - gdm_error (_("%s: Can't fork script process!"), - "gdm_parse_enriched_login"); - VE_IGNORE_EINTR (close (pipe1[0])); - VE_IGNORE_EINTR (close (pipe1[1])); - break; - - default: - /* The parent reads username from the pipe a chunk at a time */ - VE_IGNORE_EINTR (close (pipe1[1])); - g_string_truncate (str, 0); - do { - VE_IGNORE_EINTR (in_buffer_len = read (pipe1[0], in_buffer, - sizeof (in_buffer) - 1)); - if (in_buffer_len > 0) { - in_buffer[in_buffer_len] = '\0'; - g_string_append (str, in_buffer); - } - } while (in_buffer_len > 0); - - if (str->len > 0 && str->str[str->len - 1] == '\n') - g_string_truncate (str, str->len - 1); - - VE_IGNORE_EINTR (close (pipe1[0])); - - gdm_wait_for_extra (extra_process, NULL); - } - } - } - - if (!ve_string_empty(str->str) && gdm_is_user_valid(str->str)) - return g_string_free (str, FALSE); - else - { - /* "If an empty or otherwise invalid username is returned [by the script] - * automatic login [and timed login] is not performed." -- GDM manual - */ - /* fixme: also turn off automatic login */ - gdm_daemon_config_set_value_bool(GDM_KEY_TIMED_LOGIN_ENABLE, FALSE); - d->timed_login_ok = FALSE; - do_timed_login = FALSE; - g_string_free(str, TRUE); - return NULL; - } -} - -static void -gdm_slave_handle_notify (const char *msg) -{ - int val; - - gdm_debug ("Handling slave notify: '%s'", msg); - - if (sscanf (msg, GDM_NOTIFY_ALLOW_ROOT " %d", &val) == 1) { - gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_ROOT, val); - } else if (sscanf (msg, GDM_NOTIFY_ALLOW_REMOTE_ROOT " %d", &val) == 1) { - gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT, val); - } else if (sscanf (msg, GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN " %d", &val) == 1) { - gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN, val); - } else if (sscanf (msg, GDM_NOTIFY_SYSTEM_MENU " %d", &val) == 1) { - gdm_daemon_config_set_value_bool (GDM_KEY_SYSTEM_MENU, val); - if (d->greetpid > 1) - kill (d->greetpid, SIGHUP); - } else if (sscanf (msg, GDM_NOTIFY_CONFIG_AVAILABLE " %d", &val) == 1) { - gdm_daemon_config_set_value_bool (GDM_KEY_CONFIG_AVAILABLE, val); - if (d->greetpid > 1) - kill (d->greetpid, SIGHUP); - } else if (sscanf (msg, GDM_NOTIFY_CHOOSER_BUTTON " %d", &val) == 1) { - gdm_daemon_config_set_value_bool (GDM_KEY_CHOOSER_BUTTON, val); - if (d->greetpid > 1) - kill (d->greetpid, SIGHUP); - } else if (sscanf (msg, GDM_NOTIFY_RETRY_DELAY " %d", &val) == 1) { - gdm_daemon_config_set_value_int (GDM_KEY_RETRY_DELAY, val); - } else if (sscanf (msg, GDM_NOTIFY_DISALLOW_TCP " %d", &val) == 1) { - gdm_daemon_config_set_value_bool (GDM_KEY_DISALLOW_TCP, val); - remanage_asap = TRUE; - } else if (strncmp (msg, GDM_NOTIFY_GREETER " ", - strlen (GDM_NOTIFY_GREETER) + 1) == 0) { - gdm_daemon_config_set_value_string (GDM_KEY_GREETER, ((gchar *)&msg[strlen (GDM_NOTIFY_GREETER) + 1])); - - if (d->attached) { - do_restart_greeter = TRUE; - if (restart_greeter_now) { - ; /* will get restarted later */ - } else if (d->type == TYPE_STATIC) { - /* FIXME: can't handle flexi servers like this - * without going all cranky */ - if ( ! d->logged_in) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } else { - remanage_asap = TRUE; - } - } - } - } else if (strncmp (msg, GDM_NOTIFY_CUSTOM_CMD_TEMPLATE, - strlen (GDM_NOTIFY_CUSTOM_CMD_TEMPLATE)) == 0) { - if (sscanf (msg, GDM_NOTIFY_CUSTOM_CMD_TEMPLATE "%d", &val) == 1) { - gchar * key_string = g_strdup_printf("%s%d=", GDM_KEY_CUSTOM_CMD_TEMPLATE, val); - /* This assumes that the number of commands is < 100, i.e two digits - if that is not the case then this will fail */ - gdm_daemon_config_set_value_string (key_string, ((gchar *)&msg[strlen (GDM_NOTIFY_CUSTOM_CMD_TEMPLATE) + 2])); - g_free(key_string); - - if (d->attached) { - do_restart_greeter = TRUE; - if (restart_greeter_now) { - ; /* will get restarted later */ - } else if (d->type == TYPE_STATIC) { - /* FIXME: can't handle flexi servers like this - * without going all cranky */ - if ( ! d->logged_in) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } else { - remanage_asap = TRUE; - } - } - } - } - } else if (strncmp (msg, GDM_NOTIFY_REMOTE_GREETER " ", - strlen (GDM_NOTIFY_REMOTE_GREETER) + 1) == 0) { - gdm_daemon_config_set_value_string (GDM_KEY_REMOTE_GREETER, - (gchar *)(&msg[strlen (GDM_NOTIFY_REMOTE_GREETER) + 1])); - if ( ! d->attached) { - do_restart_greeter = TRUE; - if (restart_greeter_now) { - ; /* will get restarted later */ - } else if (d->type == TYPE_XDMCP) { - /* FIXME: can't handle flexi servers like this - * without going all cranky */ - if ( ! d->logged_in) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } else { - remanage_asap = TRUE; - } - } - } - } else if ((strncmp (msg, GDM_NOTIFY_TIMED_LOGIN " ", - strlen (GDM_NOTIFY_TIMED_LOGIN) + 1) == 0) || - (strncmp (msg, GDM_NOTIFY_TIMED_LOGIN_DELAY " ", - strlen (GDM_NOTIFY_TIMED_LOGIN_DELAY) + 1) == 0) || - (strncmp (msg, GDM_NOTIFY_TIMED_LOGIN_ENABLE " ", - strlen (GDM_NOTIFY_TIMED_LOGIN_ENABLE) + 1) == 0)) { - do_restart_greeter = TRUE; - /* FIXME: this is fairly nasty, we should handle this nicer */ - /* FIXME: can't handle flexi servers without going all cranky */ - if (d->type == TYPE_STATIC || d->type == TYPE_XDMCP) { - if ( ! d->logged_in) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } else { - remanage_asap = TRUE; - } - } - } else if (strncmp (msg, GDM_NOTIFY_SOUND_ON_LOGIN_FILE " ", - strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FILE) + 1) == 0) { - gdm_daemon_config_set_value_string (GDM_KEY_SOUND_ON_LOGIN_FILE, - (gchar *)(&msg[strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FILE) + 1])); - if (d->greetpid > 1) - kill (d->greetpid, SIGHUP); - } else if (strncmp (msg, GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE " ", - strlen (GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE) + 1) == 0) { - gdm_daemon_config_set_value_string (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE, - (gchar *)(&msg[strlen (GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE) + 1])); - if (d->greetpid > 1) - kill (d->greetpid, SIGHUP); - } else if (strncmp (msg, GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE " ", - strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE) + 1) == 0) { - gdm_daemon_config_set_value_string (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE, - (gchar *)(&msg[strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE) + 1])); - if (d->greetpid > 1) - kill (d->greetpid, SIGHUP); - } else if (strncmp (msg, GDM_NOTIFY_GTK_MODULES_LIST " ", - strlen (GDM_NOTIFY_GTK_MODULES_LIST) + 1) == 0) { - gdm_daemon_config_set_value_string (GDM_KEY_GTK_MODULES_LIST, - (gchar *)(&msg[strlen (GDM_NOTIFY_GTK_MODULES_LIST) + 1])); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES)) { - do_restart_greeter = TRUE; - if (restart_greeter_now) { - ; /* will get restarted later */ - } else if (d->type == TYPE_STATIC) { - /* FIXME: can't handle flexi servers like this - * without going all cranky */ - if ( ! d->logged_in) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } else { - remanage_asap = TRUE; - } - } - } - } else if (sscanf (msg, GDM_NOTIFY_ADD_GTK_MODULES " %d", &val) == 1) { - gdm_daemon_config_set_value_bool (GDM_KEY_ADD_GTK_MODULES, val); - - do_restart_greeter = TRUE; - if (restart_greeter_now) { - ; /* will get restarted later */ - } else if (d->type == TYPE_STATIC) { - /* FIXME: can't handle flexi servers like this - * without going all cranky */ - if ( ! d->logged_in) { - gdm_slave_quick_exit (DISPLAY_REMANAGE); - } else { - remanage_asap = TRUE; - } - } - } -} - -/* do cleanup but only if we are a slave, if we're not a slave, just - * return FALSE */ -gboolean -gdm_slave_final_cleanup (void) -{ - if (getpid () != d->slavepid) - return FALSE; - gdm_debug ("slave killing self"); - gdm_slave_term_handler (SIGTERM); - return TRUE; -} - -#ifdef HAVE_TSOL -static gboolean -gdm_can_i_assume_root_role (struct passwd *pwent) -{ - userattr_t *uattr = NULL; - char *freeroles = NULL; - char *roles = NULL; - char *role = NULL; - - uattr = getuseruid (pwent->pw_uid); - if G_UNLIKELY (uattr == NULL) - return FALSE; - - freeroles = roles = g_strdup (kva_match (uattr->attr, USERATTR_ROLES_KW)); - if (roles == NULL) { - return FALSE; - } - - while ((role = strtok (roles, ",")) != NULL) { - roles = NULL; - if (!strncmp (role, "root", 4)) { - g_free (freeroles); - g_free (role); - return TRUE; - } - } - g_free (freeroles); - g_free (role); - return FALSE; -} -#endif /* HAVE_TSOL */ - - -/* gdm_is_user_valid() mostly copied from gui/gdmuser.c */ -gboolean -gdm_is_user_valid (const char *username) -{ - return (NULL != getpwnam (username)); -} diff --git a/daemon/slave.h b/daemon/slave.h deleted file mode 100644 index 1f1599e0..00000000 --- a/daemon/slave.h +++ /dev/null @@ -1,49 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_SLAVE_H -#define GDM_SLAVE_H - -#include <glib.h> - -#include "gdm.h" -#include "display.h" - -void gdm_slave_start (GdmDisplay *d); -void gdm_slave_greeter_ctl_no_ret (char cmd, const char *str); -char *gdm_slave_greeter_ctl (char cmd, const char *str); -gboolean gdm_slave_greeter_check_interruption (void); -gboolean gdm_slave_action_pending (void); - -void gdm_slave_send (const char *str, gboolean wait_for_ack); -void gdm_slave_send_num (const char *opcode, long num); -void gdm_slave_send_string (const char *opcode, const char *str); -gboolean gdm_slave_final_cleanup (void); - -void gdm_slave_whack_temp_auth_file (void); - -gboolean gdm_slave_check_user_wants_to_log_in (const char *user); -gboolean gdm_is_session_magic (const char *session_name); - -/* This is the slave child handler so that we can chain to it from elsewhere */ -void gdm_slave_child_handler (int sig); - -#endif /* GDM_SLAVE_H */ - -/* EOF */ - diff --git a/daemon/verify-crypt.c b/daemon/verify-crypt.c deleted file mode 100644 index 3de0ad4a..00000000 --- a/daemon/verify-crypt.c +++ /dev/null @@ -1,464 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <glib/gi18n.h> -#include <pwd.h> -#include <grp.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> - -#if defined (CAN_CLEAR_ADMCHG) && defined (HAVE_USERSEC_H) -# include <usersec.h> -#endif /* CAN_CLEAR_ADMCHG && HAVE_USERSEC_H */ - -#ifdef HAVE_CRYPT -# include <crypt.h> -#endif /* HAVE_CRYPT */ - -#include "gdm.h" -#include "misc.h" -#include "slave.h" -#include "verify.h" -#include "errorgui.h" -#include "gdm-common.h" -#include "gdm-daemon-config.h" -#include "gdm-socket-protocol.h" - -static char *selected_user = NULL; - -void -gdm_verify_select_user (const char *user) -{ - g_free (selected_user); - if (ve_string_empty (user)) - selected_user = NULL; - else - selected_user = g_strdup (user); -} - -static void -print_cant_auth_errbox (void) -{ - gboolean is_capslock = FALSE; - const char *basemsg; - char *msg; - char *ret; - - ret = gdm_slave_greeter_ctl (GDM_QUERY_CAPSLOCK, ""); - if ( ! ve_string_empty (ret)) - is_capslock = TRUE; - g_free (ret); - - basemsg = _("\nIncorrect username or password. " - "Letters must be typed in the correct " - "case."); - if (is_capslock) { - msg = g_strconcat (basemsg, " ", - _("Caps Lock is on."), - NULL); - } else { - msg = g_strdup (basemsg); - } - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, msg); - g_free (msg); -} - -/** - * gdm_verify_user: - * @username: Name of user or NULL if we should ask - * @display: Name of display to register with the authentication system - * @local: boolean if local - * @allow_retry: boolean. Not used by verify-crypt. If this code - * allowed the user to retry, this boolean would specify - * whether to enable this feature. We only want this - * feature to work for normal login, not for asking for - * root password to call the configurator. - * - * Provides a communication layer between the operating system's - * authentication functions and the gdmgreeter. - * - * Returns the user's login on success and NULL on failure. - */ - -gchar * -gdm_verify_user (GdmDisplay *d, - const char *username, - const gchar *display, - gboolean local, - gboolean allow_retry) -{ - gchar *login, *passwd, *ppasswd; - struct passwd *pwent; -#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS) \ - || defined (HAVE_LOGINRESTRICTIONS) - gchar *message = NULL; -#endif -#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS) - gchar *info_msg = NULL, *response = NULL; - gint reEnter, ret; -#endif - - if (local && d->timed_login_ok) - gdm_slave_greeter_ctl_no_ret (GDM_STARTTIMER, ""); - - if (username == NULL) { - authenticate_again: - /* Ask for the user's login */ - gdm_verify_select_user (NULL); - gdm_slave_greeter_ctl_no_ret (GDM_MSG, _("Please enter your username")); - login = gdm_slave_greeter_ctl (GDM_PROMPT, _("Username:")); - if (login == NULL || - gdm_slave_greeter_check_interruption ()) { - if ( ! ve_string_empty (selected_user)) { - /* user selected */ - g_free (login); - login = selected_user; - selected_user = NULL; - } else { - /* some other interruption */ - if (local) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - g_free (login); - return NULL; - } - } - gdm_slave_greeter_ctl_no_ret (GDM_MSG, ""); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_DISPLAY_LAST_LOGIN)) { - char *info = gdm_get_last_info (login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, info); - g_free (info); - } - } else { - login = g_strdup (username); - } - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - - pwent = getpwnam (login); - - ppasswd = (pwent == NULL) ? NULL : g_strdup (pwent->pw_passwd); - - /* Request the user's password */ - if (pwent != NULL && - ve_string_empty (ppasswd)) { - /* eeek a passwordless account */ - passwd = g_strdup (""); - } else { - passwd = gdm_slave_greeter_ctl (GDM_NOECHO, _("Password:")); - if (passwd == NULL) - passwd = g_strdup (""); - if (gdm_slave_greeter_check_interruption ()) { - if (local) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - } - - if (local) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - - if (pwent == NULL) { - gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY)); - g_warning (_("Couldn't authenticate user \"%s\""), login); - - print_cant_auth_errbox (); - - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - - /* Check whether password is valid */ - if (ppasswd == NULL || (ppasswd[0] != '\0' && - strcmp (crypt (passwd, ppasswd), ppasswd) != 0)) { - gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY)); - g_warning (_("Couldn't authenticate user \"%s\""), login); - - print_cant_auth_errbox (); - - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - - if ( ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_ROOT)|| - ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT) && ! local) ) && - pwent->pw_uid == 0) { - g_warning (_("Root login disallowed on display '%s'"), display); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("The system administrator " - "is not allowed to login " - "from this screen")); - /*gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, - _("Root login disallowed"));*/ - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - -#ifdef HAVE_LOGINRESTRICTIONS - - /* Check with the 'loginrestrictions' function - if the user has been disallowed */ - if (loginrestrictions (login, 0, NULL, &message) != 0) { - g_warning (_("User %s not allowed to log in"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator " - "has disabled your " - "account.")); - g_free (login); - g_free (passwd); - g_free (ppasswd); - if (message != NULL) - free (message); - return NULL; - } - - if (message != NULL) - free (message); - message = NULL; - -#else /* ! HAVE_LOGINRESTRICTIONS */ - - /* check for the standard method of disallowing users */ - if (pwent->pw_shell != NULL && - (strcmp (pwent->pw_shell, "/sbin/nologin") == 0 || - strcmp (pwent->pw_shell, "/bin/true") == 0 || - strcmp (pwent->pw_shell, "/bin/false") == 0)) { - g_warning (_("User %s not allowed to log in"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator " - "has disabled your " - "account.")); - /*gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, - _("Login disabled"));*/ - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - -#endif /* HAVE_LOGINRESTRICTIONS */ - - g_free (passwd); - g_free (ppasswd); - - if ( ! gdm_slave_check_user_wants_to_log_in (login)) { - g_free (login); - login = NULL; - goto authenticate_again; - } - - if ( ! gdm_setup_gids (login, pwent->pw_gid)) { - g_warning (_("Cannot set user group for %s"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nCannot set your user group; " - "you will not be able to log in. " - "Please contact your system administrator.")); - g_free (login); - return NULL; - } - -#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS) - - switch (passwdexpired (login, &info_msg)) { - case 1 : - g_warning (_("Password of %s has expired"), login); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("You are required to change your password.\n" - "Please choose a new one.")); - g_free (info_msg); - - do { - ret = chpass (login, response, &reEnter, &message); - g_free (response); - - if (ret != 1) { - if (ret != 0) { - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nCannot change your password; " - "you will not be able to log in. " - "Please try again later or contact " - "your system administrator.")); - } else if ((reEnter != 0) && (message)) { - response = gdm_slave_greeter_ctl (GDM_NOECHO, message); - if (response == NULL) - response = g_strdup (""); - } - } - - g_free (message); - message = NULL; - - } while ( ((reEnter != 0) && (ret == 0)) - || (ret ==1) ); - - g_free (response); - g_free (message); - - if ((ret != 0) || (reEnter != 0)) { - return NULL; - } - -#if defined (CAN_CLEAR_ADMCHG) - /* The password is changed by root, clear the ADM_CHG - flag in the passwd file */ - ret = setpwdb (S_READ | S_WRITE); - if (!ret) { - upwd = getuserpw (login); - if (upwd == NULL) { - ret = -1; - } else { - upwd->upw_flags &= ~PW_ADMCHG; - ret = putuserpw (upwd); - if (!ret) { - ret = endpwdb (); - } - } - } - - if (ret) { - gdm_errorgui_error_box (d, GTK_MESSAGE_WARNING, - _("Your password has been changed but " - "you may have to change it again. " - "Please try again later or contact " - "your system administrator.")); - } - -#else /* !CAN_CLEAR_ADMCHG */ - gdm_errorgui_error_box (d, GTK_MESSAGE_WARNING, - _("Your password has been changed but you " - "may have to change it again. Please try again " - "later or contact your system administrator.")); - -#endif /* CAN_CLEAR_ADMCHG */ - - break; - - case 2 : - g_warning (_("Password of %s has expired"), login); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("Your password has expired.\n" - "Only a system administrator can now change it")); - g_free (info_msg); - return NULL; - break; - - case -1 : - g_warning (_("Internal error on passwdexpired")); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("An internal error occurred. You will not be able to log in.\n" - "Please try again later or contact your system administrator.")); - g_free (info_msg); - return NULL; - break; - - default : - g_free (info_msg); - break; - } - -#endif /* HAVE_PASSWDEXPIRED && HAVE_CHPASS */ - - return login; -} - -/** - * gdm_verify_setup_user: - * @login: The name of the user - * @display: The name of the display - * - * This is used for auto loging in. This just sets up the login - * session for this user - */ - -gboolean -gdm_verify_setup_user (GdmDisplay *d, - const gchar *login, const gchar *display, - char **new_login) -{ - struct passwd *pwent; - - *new_login = NULL; - - pwent = getpwnam (login); - if (pwent == NULL) { - g_warning (_("Cannot get passwd structure for %s"), login); - return FALSE; - } - - if ( ! gdm_setup_gids (login, pwent->pw_gid)) { - g_warning (_("Cannot set user group for %s"), login); - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("\nCannot set your user group; " - "you will not be able to log in. " - "Please contact your system administrator.")); - return FALSE; - } - - return TRUE; -} - -/** - * gdm_verify_cleanup: - * - * Unregister the user's session - */ - -void -gdm_verify_cleanup (GdmDisplay *d) -{ - gid_t groups[1] = { 0 }; - - /* Clear the group setup */ - setgid (0); - /* this will get rid of any suplementary groups etc... */ - setgroups (1, groups); -} - -/** - * gdm_verify_check: - * - * Check that the authentication system is correctly configured. - * - * Aborts daemon on error - */ - -void -gdm_verify_check (void) -{ -} - -/* used in pam */ -gboolean -gdm_verify_setup_env (GdmDisplay *d) -{ - return TRUE; -} diff --git a/daemon/verify-pam.c b/daemon/verify-pam.c deleted file mode 100644 index 0e747637..00000000 --- a/daemon/verify-pam.c +++ /dev/null @@ -1,1631 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <grp.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <syslog.h> -#include <security/pam_appl.h> -#include <pwd.h> -#ifdef __sun -#include <fcntl.h> -#endif - -#include <glib/gi18n.h> - -#include "gdm.h" -#include "misc.h" -#include "slave.h" -#include "verify.h" -#include "errorgui.h" - -#include "gdm-common.h" -#include "gdm-log.h" -#include "gdm-daemon-config.h" - -#include "gdm-socket-protocol.h" - -#ifdef HAVE_LOGINDEVPERM -#include <libdevinfo.h> -#endif /* HAVE_LOGINDEVPERM */ -#ifdef HAVE_ADT -#include <bsm/adt.h> -#include <bsm/adt_event.h> -#endif /* HAVE_ADT */ - -/* Evil, but this way these things are passed to the child session */ -static pam_handle_t *pamh = NULL; - -static GdmDisplay *cur_gdm_disp = NULL; - -/* Hack. Used so user does not need to select username in face - * browser again if pw was wrong. Not used if username was typed - * manually */ -static char* prev_user; -static unsigned auth_retries; - -/* this is another hack */ -static gboolean did_we_ask_for_password = FALSE; - -static char *selected_user = NULL; - -static gboolean opened_session = FALSE; -static gboolean did_setcred = FALSE; - -extern char *gdm_ack_question_response; - -#ifdef HAVE_ADT -#define PW_FALSE 1 /* no password change */ -#define PW_TRUE 2 /* successful password change */ -#define PW_FAILED 3 /* failed password change */ - -static adt_session_data_t *adt_ah = NULL; /* audit session handle */ - -/* - * audit_success_login - audit successful login - * - * Entry process audit context established -- i.e., pam_setcred () - * called. - * pw_change == PW_TRUE, if successful password change audit - * required. - * pwent = authenticated user's passwd entry. - * - * Exit ADT_login (ADT_SUCCESS) audit record written - * pw_change == PW_TRUE, ADT_passwd (ADT_SUCCESS) audit - * record written. - * adt_ah = audit session established for audit_logout (); - * - */ -static void -audit_success_login (int pw_change, struct passwd *pwent) -{ - adt_event_data_t *event; /* event to generate */ - - if (adt_start_session (&adt_ah, NULL, ADT_USE_PROC_DATA) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_start_session (ADT_login): %m"); - return; - } - - if (adt_set_user (adt_ah, pwent->pw_uid, pwent->pw_gid, - pwent->pw_uid, pwent->pw_gid, NULL, ADT_USER) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_set_user (ADT_login, %s): %m", pwent->pw_name); - } - if ((event = adt_alloc_event (adt_ah, ADT_login)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, "adt_alloc_event (ADT_login): %m"); - } else if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_login, ADT_SUCCESS): %m"); - } - - if (pw_change == PW_TRUE) { - - /* Also audit password change */ - adt_free_event (event); - if ((event = adt_alloc_event (adt_ah, ADT_passwd)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_alloc_event (ADT_passwd): %m"); - } else if (adt_put_event (event, ADT_SUCCESS, - ADT_SUCCESS) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_passwd, ADT_SUCCESS): %m"); - } - } - adt_free_event (event); -} - -/* - * audit_fail_login - audit failed login - * - * Entry did_setcred == FALSE, process audit context is not established. - * TRUE, process audit context established. - * d = display structure, d->attached non 0 if local, - * d->hostname used if remote. - * pw_change == PW_FALSE, if no password change requested. - * PW_TRUE, if successful password change audit - * required. - * PW_FAILED, if failed password change audit - * required. - * pwent = NULL, or password entry to use. - * pamerr = PAM error code; reason for failure. - * - * Exit ADT_login (ADT_FAILURE) audit record written - * pw_change == PW_TRUE, ADT_passwd (ADT_FAILURE) audit - * record written. - * - */ -static void -audit_fail_login (GdmDisplay *d, int pw_change, struct passwd *pwent, - int pamerr) -{ - adt_session_data_t *ah; /* audit session handle */ - adt_event_data_t *event; /* event to generate */ - adt_termid_t *tid; /* terminal ID for failures */ - - if (did_setcred == TRUE) { - if (adt_start_session (&ah, NULL, ADT_USE_PROC_DATA) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_start_session (ADT_login, ADT_FAILURE): %m"); - return; - } - } else { - if (adt_start_session (&ah, NULL, 0) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_start_session (ADT_login, ADT_FAILURE): %m"); - return; - } - if (d->attached) { - /* login from the local host */ - if (adt_load_ttyname ("/dev/console", &tid) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_loadhostname (localhost): %m"); - } - } else { - /* login from a remote host */ - if (adt_load_hostname (d->hostname, &tid) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_loadhostname (%s): %m", d->hostname); - } - } - if (adt_set_user (ah, - pwent ? pwent->pw_uid : ADT_NO_ATTRIB, - pwent ? pwent->pw_gid : ADT_NO_ATTRIB, - pwent ? pwent->pw_uid : ADT_NO_ATTRIB, - pwent ? pwent->pw_gid : ADT_NO_ATTRIB, - tid, ADT_NEW) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_set_user (%s): %m", - pwent ? pwent->pw_name : "ADT_NO_ATTRIB"); - } - } - if ((event = adt_alloc_event (ah, ADT_login)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_alloc_event (ADT_login, ADT_FAILURE): %m"); - goto done; - } else if (adt_put_event (event, ADT_FAILURE, - ADT_FAIL_PAM + pamerr) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_login (ADT_FAIL, %s): %m", - pam_strerror (pamh, pamerr)); - } - if (pw_change != PW_FALSE) { - - /* Also audit password change */ - adt_free_event (event); - if ((event = adt_alloc_event (ah, ADT_passwd)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_alloc_event (ADT_passwd): %m"); - goto done; - } - if (pw_change == PW_TRUE) { - if (adt_put_event (event, ADT_SUCCESS, - ADT_SUCCESS) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_passwd, ADT_SUCCESS): " - "%m"); - } - } else if (pw_change == PW_FAILED) { - if (adt_put_event (event, ADT_FAILURE, - ADT_FAIL_PAM + pamerr) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_passwd, ADT_FAILURE): " - "%m"); - } - } - } - adt_free_event (event); - - done: - /* reset process audit state. this process is being reused.*/ - - if ((adt_set_user (ah, ADT_NO_AUDIT, ADT_NO_AUDIT, ADT_NO_AUDIT, - ADT_NO_AUDIT, NULL, ADT_NEW) != 0) || - (adt_set_proc (ah) != 0)) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_login (ADT_FAILURE reset, %m)"); - } - (void) adt_end_session (ah); -} - -/* - * audit_logout - audit user logout - * - * Entry adt_ah = audit session handle established by - * audit_success_login (). - * - * Exit ADT_logout (ADT_SUCCESS) audit record written - * process audit state reset. (this process is reused for - * the next login.) - * audit session adt_ah ended. - */ -static void -audit_logout (void) -{ - adt_event_data_t *event; /* event to generate */ - - if ((event = adt_alloc_event (adt_ah, ADT_logout)) == NULL) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_alloc_event (ADT_logout): %m"); - } else if (adt_put_event (event, ADT_SUCCESS, ADT_SUCCESS) != 0) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_put_event (ADT_logout, ADT_SUCCESS): %m"); - } - adt_free_event (event); - - /* reset process audit state. this process is being reused.*/ - - if ((adt_set_user (adt_ah, ADT_NO_AUDIT, ADT_NO_AUDIT, ADT_NO_AUDIT, - ADT_NO_AUDIT, NULL, ADT_NEW) != 0) || - (adt_set_proc (adt_ah) != 0)) { - - syslog (LOG_AUTH | LOG_ALERT, - "adt_set_proc (ADT_logout reset): %m"); - } - (void) adt_end_session (adt_ah); -} -#endif /* HAVE_ADT */ - -#ifdef __sun -void -solaris_xserver_cred (char *login, GdmDisplay *d, struct passwd *pwent) -{ - struct stat statbuf; - struct group *gr; - gid_t groups[NGROUPS_UMAX]; - char *home, *disp, *tmp, pipe[MAXPATHLEN], info[MAXPATHLEN]; - int displayNumber = 0; - int retval, fd, i, nb; - int ngroups; - - if (!d->attached) - return; - - if (g_access (pwent->pw_dir, F_OK) != 0) { - gdm_debug ("solaris_xserver_cred: no HOME dir access\n"); - return; - } - - /* - * Handshake with server. Make sure it created a pipe. - * Open and write. - */ - if ((tmp = strstr (d->name, ":")) != NULL) { - tmp++; - displayNumber = atoi (tmp); - } - - sprintf (pipe, "%s/%d", SDTLOGIN_DIR, displayNumber); - - if (g_stat (SDTLOGIN_DIR, &statbuf) == 0) { - if (! statbuf.st_mode & S_IFDIR) { - gdm_debug ("solaris_xserver_cred: %s is not a directory\n", - SDTLOGIN_DIR); - return; - } - } - else { - gdm_debug ("solaris_xserver_cred: %s does not exist\n", SDTLOGIN_DIR); - return; - } - - fd = open (pipe, O_RDWR); - g_unlink (pipe); - - if (fd < 0) { - gdm_debug ("solaris_xserver_cred: could not open %s\n", pipe); - return; - } - if (fstat (fd, &statbuf) == 0 ) { - if ( ! statbuf.st_mode & S_IFIFO) { - close (fd); - gdm_debug ("solaris_xserver_cred: %s is not a pipe\n", pipe); - return; - } - } else { - close (fd); - gdm_debug ("solaris_xserver_cred: %s does not exist\n", pipe); - return; - } - - sprintf (info, "GID=\"%d\"; ", pwent->pw_gid); - nb = write (fd, info, strlen (info)); - gdm_debug ("solaris_xserver_cred: %s\n", info); - - if (initgroups (login, pwent->pw_gid) == -1) { - ngroups = 0; - } else { - ngroups = getgroups (NGROUPS_UMAX, groups); - } - - for (i=0; i < ngroups; i++) { - sprintf (info, "G_LIST_ID=\"%u\" ", groups[i]); - nb = write (fd, info, strlen (info)); - gdm_debug ("solaris_xserver_cred: %s\n", info); - } - - if (ngroups > 0) { - sprintf (info, ";"); - write (fd, info, strlen (info)); - } - - sprintf (info, " HOME=\"%s\" ", pwent->pw_dir); - nb = write (fd, info, strlen (info)); - gdm_debug ("solaris_xserver_cred: %s\n", info); - - sprintf (info, " UID=\"%d\" EOF=\"\";", pwent->pw_uid); - nb = write (fd, info, strlen (info)); - gdm_debug ("solaris_xserver_cred: %s\n", info); - - /* - * Handshake with server. Make sure it read the pipe. - * - * Close file descriptor. - */ - close (fd); - - return; -} -#endif - -void -gdm_verify_select_user (const char *user) -{ - g_free (selected_user); - if (ve_string_empty (user)) - selected_user = NULL; - else - selected_user = g_strdup (user); -} - -static const char * -perhaps_translate_message (const char *msg) -{ - char *s; - const char *ret; - static GHashTable *hash = NULL; - static char *locale = NULL; - - /* if locale changes out from under us then rebuild hash table - */ - if ((locale != NULL) && - (strcmp (locale, setlocale (LC_ALL, NULL)) != 0)) { - g_assert (hash != NULL); - g_hash_table_destroy (hash); - hash = NULL; - } - - if (hash == NULL) { - g_free (locale); - locale = g_strdup (setlocale (LC_ALL, NULL)); - - /* Here we come with some fairly standard messages so that - we have as much as possible translated. Should really be - translated in pam I suppose. This way we can "change" - some of these messages to be more sane. */ - hash = g_hash_table_new (g_str_hash, g_str_equal); - /* login: is whacked always translate to Username: */ - g_hash_table_insert (hash, "login:", _("Username:")); - g_hash_table_insert (hash, "Username:", _("Username:")); - g_hash_table_insert (hash, "username:", _("Username:")); - g_hash_table_insert (hash, "Password:", _("Password:")); - g_hash_table_insert (hash, "password:", _("Password:")); - g_hash_table_insert (hash, "You are required to change your password immediately (password aged)", _("You are required to change your password immediately (password aged)")); - g_hash_table_insert (hash, "You are required to change your password immediately (root enforced)", _("You are required to change your password immediately (root enforced)")); - g_hash_table_insert (hash, "Your account has expired; please contact your system administrator", _("Your account has expired; please contact your system administrator")); - g_hash_table_insert (hash, "No password supplied", _("No password supplied")); - g_hash_table_insert (hash, "Password unchanged", _("Password unchanged")); - g_hash_table_insert (hash, "Can not get username", _("Can not get username")); - g_hash_table_insert (hash, "Retype new UNIX password:", _("Retype new UNIX password:")); - g_hash_table_insert (hash, "Enter new UNIX password:", _("Enter new UNIX password:")); - g_hash_table_insert (hash, "(current) UNIX password:", _("(current) UNIX password:")); - g_hash_table_insert (hash, "Error while changing NIS password.", _("Error while changing NIS password.")); - g_hash_table_insert (hash, "You must choose a longer password", _("You must choose a longer password")); - g_hash_table_insert (hash, "Password has been already used. Choose another.", _("Password has been already used. Choose another.")); - g_hash_table_insert (hash, "You must wait longer to change your password", _("You must wait longer to change your password")); - g_hash_table_insert (hash, "Sorry, passwords do not match", _("Sorry, passwords do not match")); - /* FIXME: what about messages which have some variables in them, perhaps try to do those as well */ - } - s = g_strstrip (g_strdup (msg)); - ret = g_hash_table_lookup (hash, s); - g_free (s); - if (ret != NULL) - return ret; - else - return msg; -} - -/* Internal PAM conversation function. Interfaces between the PAM - * authentication system and the actual greeter program */ - -static int -gdm_verify_pam_conv (int num_msg, struct pam_message **msg, - struct pam_response **resp, - void *appdata_ptr) -{ - int replies = 0; - int i; - char *s = NULL; - struct pam_response *reply = NULL; - const void *p; - const char *login; - - if (pamh == NULL) - return PAM_CONV_ERR; - - /* Should never happen unless PAM is on crack and keeps asking questions - after we told it to go away. So tell it to go away again and - maybe it will listen */ - /* well, it actually happens if there are multiple pam modules - * with conversations */ - if ( ! gdm_slave_action_pending () || selected_user) - return PAM_CONV_ERR; - - reply = malloc (sizeof (struct pam_response) * num_msg); - - if (reply == NULL) - return PAM_CONV_ERR; - - memset (reply, 0, sizeof (struct pam_response) * num_msg); - - /* Here we set the login if it wasn't already set, - * this is kind of anal, but this way we guarantee that - * the greeter always is up to date on the login */ - if (pam_get_item (pamh, PAM_USER, (void **)&p) == PAM_SUCCESS) { - login = (const char *)p; - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - } - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - for (replies = 0; replies < num_msg; replies++) { - const char *m = (*msg)[replies].msg; - m = perhaps_translate_message (m); - - switch ((*msg)[replies].msg_style) { - - /* PAM requested textual input with echo on */ - case PAM_PROMPT_ECHO_ON: - if (strcmp (m, _("Username:")) == 0) { - if ( ve_string_empty (selected_user)) { - /* this is an evil hack, but really there is no way we'll - know this is a username prompt. However we SHOULD NOT - rely on this working. The pam modules can set their - prompt to whatever they wish to */ - gdm_slave_greeter_ctl_no_ret - (GDM_MSG, _("Please enter your username")); - s = gdm_slave_greeter_ctl (GDM_PROMPT, m); - /* this will clear the message */ - gdm_slave_greeter_ctl_no_ret (GDM_MSG, ""); - } - } else { - s = gdm_slave_greeter_ctl (GDM_PROMPT, m); - } - - if (gdm_slave_greeter_check_interruption ()) { - g_free (s); - for (i = 0; i < replies; i++) - if (reply[replies].resp != NULL) - free (reply[replies].resp); - free (reply); - return PAM_CONV_ERR; - } - - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = strdup (ve_sure_string (s)); - g_free (s); - break; - - case PAM_PROMPT_ECHO_OFF: - if (strcmp (m, _("Password:")) == 0) - did_we_ask_for_password = TRUE; - /* PAM requested textual input with echo off */ - s = gdm_slave_greeter_ctl (GDM_NOECHO, m); - if (gdm_slave_greeter_check_interruption ()) { - g_free (s); - for (i = 0; i < replies; i++) - if (reply[replies].resp != NULL) - free (reply[replies].resp); - free (reply); - return PAM_CONV_ERR; - } - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = strdup (ve_sure_string (s)); - g_free (s); - break; - - case PAM_ERROR_MSG: - /* PAM sent a message that should displayed to the user */ - gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, m); - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = NULL; - break; - case PAM_TEXT_INFO: - /* PAM sent a message that should displayed to the user */ - gdm_slave_greeter_ctl_no_ret (GDM_MSG, m); - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = NULL; - break; - - default: - /* PAM has been smoking serious crack */ - for (i = 0; i < replies; i++) - if (reply[replies].resp != NULL) - free (reply[replies].resp); - free (reply); - return PAM_CONV_ERR; - } - - } - - *resp = reply; - return PAM_SUCCESS; -} - -static struct pam_conv pamc = { - &gdm_verify_pam_conv, - NULL -}; - -/* Extra message to give on queries */ -static char *extra_standalone_message = NULL; - -static int -gdm_verify_standalone_pam_conv (int num_msg, struct pam_message **msg, - struct pam_response **resp, - void *appdata_ptr) -{ - int replies = 0; - int i; - char *text; - char *question_msg; - struct pam_response *reply = NULL; - - if (pamh == NULL) - return PAM_CONV_ERR; - - reply = malloc (sizeof (struct pam_response) * num_msg); - - if (reply == NULL) - return PAM_CONV_ERR; - - memset (reply, 0, sizeof (struct pam_response) * num_msg); - - for (replies = 0; replies < num_msg; replies++) { - const char *m = (*msg)[replies].msg; - m = perhaps_translate_message (m); - switch ((*msg)[replies].msg_style) { - - case PAM_PROMPT_ECHO_ON: - if (extra_standalone_message != NULL) - text = g_strdup_printf - ("%s%s", extra_standalone_message, - m); - else - text = g_strdup (m); - - /* PAM requested textual input with echo on */ - question_msg = g_strdup_printf ("question_msg=%s$$echo=%d", text, TRUE); - - gdm_slave_send_string (GDM_SOP_SHOW_QUESTION_DIALOG, question_msg); - - g_free (question_msg); - g_free (text); - - reply[replies].resp_retcode = PAM_SUCCESS; - if (gdm_ack_question_response) { - reply[replies].resp = strdup (ve_sure_string (gdm_ack_question_response)); - g_free (gdm_ack_question_response); - gdm_ack_question_response = NULL; - } else - reply[replies].resp = NULL; - - break; - - case PAM_PROMPT_ECHO_OFF: - if (extra_standalone_message != NULL) - text = g_strdup_printf - ("%s%s", extra_standalone_message, - m); - else - text = g_strdup (m); - - /* PAM requested textual input with echo off */ - question_msg = g_strdup_printf ("question_msg=%s$$echo=%d", text, TRUE); - - gdm_slave_send_string (GDM_SOP_SHOW_QUESTION_DIALOG, question_msg); - - g_free (question_msg); - g_free (text); - - reply[replies].resp_retcode = PAM_SUCCESS; - if (gdm_ack_question_response) { - reply[replies].resp = strdup (ve_sure_string (gdm_ack_question_response)); - g_free (gdm_ack_question_response); - gdm_ack_question_response = NULL; - } else - reply[replies].resp = NULL; - - break; - - case PAM_ERROR_MSG: - /* PAM sent a message that should displayed to the user */ - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - m); - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = NULL; - break; - - case PAM_TEXT_INFO: - /* PAM sent a message that should displayed to the user */ - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_INFO, - m); - reply[replies].resp_retcode = PAM_SUCCESS; - reply[replies].resp = NULL; - break; - - default: - /* PAM has been smoking serious crack */ - for (i = 0; i < replies; i++) - if (reply[replies].resp != NULL) - free (reply[replies].resp); - free (reply); - return PAM_CONV_ERR; - } - - } - - *resp = reply; - return PAM_SUCCESS; -} - -static struct pam_conv standalone_pamc = { - &gdm_verify_standalone_pam_conv, - NULL -}; - -/* Creates a pam handle for the auto login */ -static gboolean -create_pamh (GdmDisplay *d, - const char *service, - const char *login, - struct pam_conv *conv, - const char *display, - int *pamerr) -{ - if (display == NULL) { - gdm_error (_("Cannot setup pam handle with null display")); - return FALSE; - } - - if (pamh != NULL) { - gdm_error ("create_pamh: Stale pamh around, cleaning up"); - pam_end (pamh, PAM_SUCCESS); - } - /* init things */ - pamh = NULL; - opened_session = FALSE; - did_setcred = FALSE; - - /* Initialize a PAM session for the user */ - if ((*pamerr = pam_start (service, login, conv, &pamh)) != PAM_SUCCESS) { - pamh = NULL; /* be anal */ - if (gdm_slave_action_pending ()) - gdm_error (_("Unable to establish service %s: %s\n"), - service, pam_strerror (NULL, *pamerr)); - return FALSE; - } - - /* Inform PAM of the user's tty */ -#ifdef __sun - if (d->attached) - (void) pam_set_item (pamh, PAM_TTY, "/dev/console"); - else -#endif /* sun */ - if ((*pamerr = pam_set_item (pamh, PAM_TTY, display)) != PAM_SUCCESS) { - if (gdm_slave_action_pending ()) - gdm_error (_("Can't set PAM_TTY=%s"), display); - return FALSE; - } - - if ( ! d->attached) { - /* Only set RHOST if host is remote */ - /* From the host of the display */ - if ((*pamerr = pam_set_item (pamh, PAM_RHOST, - d->hostname)) != PAM_SUCCESS) { - if (gdm_slave_action_pending ()) - gdm_error (_("Can't set PAM_RHOST=%s"), - d->hostname); - return FALSE; - } - } - - return TRUE; -} - -/** - * gdm_verify_user: - * @username: Name of user or NULL if we should ask - * @display: Name of display to register with the authentication system - * @local: boolean if local - * @allow_retry: boolean if we should allow retry logic to be enabled. - * We only want this to work for normal login, not for - * asking for the root password to cal the configurator. - * - * Provides a communication layer between the operating system's - * authentication functions and the gdmgreeter. - * - * Returns the user's login on success and NULL on failure. - */ - -gchar * -gdm_verify_user (GdmDisplay *d, - const char *username, - const gchar *display, - gboolean local, - gboolean allow_retry) -{ - gint pamerr = 0; - struct passwd *pwent = NULL; - const void *p; - char *login, *passreq, *consoleonly; - char *pam_stack = NULL; - int null_tok = 0; - gboolean credentials_set = FALSE; - gboolean error_msg_given = FALSE; - gboolean started_timer = FALSE; - -#ifdef HAVE_ADT - int pw_change = PW_FALSE; /* if got to trying to change password */ -#endif /* HAVE_ADT */ - - verify_user_again: - - pamerr = 0; - login = NULL; - error_msg_given = FALSE; - credentials_set = FALSE; - started_timer = FALSE; - null_tok = 0; - - /* start the timer for timed logins */ - if ( ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN)) && - d->timed_login_ok && - (local || gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN))) { - gdm_slave_greeter_ctl_no_ret (GDM_STARTTIMER, ""); - started_timer = TRUE; - } - - if (username != NULL) { - login = g_strdup (username); - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - } - - cur_gdm_disp = d; - - authenticate_again: - - if (prev_user && !login) { - login = g_strdup(prev_user); - } else if (login && !prev_user) { - prev_user = g_strdup(login); - auth_retries = 0; - } else if (login && prev_user && strcmp (login, prev_user)) { - g_free (prev_user); - prev_user = g_strdup (login); - auth_retries = 0; - } - - /* - * Initialize a PAM session for the user... - * Get value per-display so different displays can use different - * PAM Stacks, in case one display should use a different - * authentication mechanism than another display. - */ - pam_stack = gdm_daemon_config_get_value_string_per_display (GDM_KEY_PAM_STACK, (char *)display); - - if ( ! create_pamh (d, pam_stack, login, &pamc, display, &pamerr)) { - if (started_timer) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - g_free (pam_stack); - goto pamerr; - } - - g_free (pam_stack); - - /* - * have to unset login otherwise there is no chance to ever enter - * a different user - */ - g_free (login); - login = NULL; - - pam_set_item (pamh, PAM_USER_PROMPT, _("Username:")); - -#if 0 - /* FIXME: this makes things wait at the wrong places! such as - when running the configurator. We wish to ourselves cancel logins - without a delay, so ... evil */ -#ifdef PAM_FAIL_DELAY - pam_fail_delay (pamh, gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY) * 1000000); -#endif /* PAM_FAIL_DELAY */ -#endif - - passreq = gdm_read_default ("PASSREQ="); - if ((passreq != NULL) && - g_ascii_strcasecmp (passreq, "YES") == 0) - gdm_daemon_config_set_value_bool (GDM_KEY_PASSWORD_REQUIRED, TRUE); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_PASSWORD_REQUIRED)) - null_tok |= PAM_DISALLOW_NULL_AUTHTOK; - - gdm_verify_select_user (NULL); - - /* Start authentication session */ - did_we_ask_for_password = FALSE; - if ((pamerr = pam_authenticate (pamh, null_tok)) != PAM_SUCCESS) { - if ( ! ve_string_empty (selected_user)) { - pam_handle_t *tmp_pamh; - - /* Face browser was used to select a user, - just completely rewhack everything since it - seems various PAM implementations are - having goats with just setting PAM_USER - and trying to pam_authenticate again */ - - g_free (login); - login = selected_user; - selected_user = NULL; - - gdm_sigterm_block_push (); - gdm_sigchld_block_push (); - tmp_pamh = pamh; - pamh = NULL; - gdm_sigchld_block_pop (); - gdm_sigterm_block_pop (); - - /* FIXME: what about errors */ - /* really this has been a sucess, not a failure */ - pam_end (tmp_pamh, pamerr); - - g_free (prev_user); - prev_user = NULL; - auth_retries = 0; - - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - - goto authenticate_again; - } - - if (started_timer) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - - if (gdm_slave_action_pending ()) { - /* FIXME: see note above about PAM_FAIL_DELAY */ - /* #ifndef PAM_FAIL_DELAY */ - gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY)); - /* wait up to 100ms randomly */ - usleep (g_random_int_range (0, 100000)); - /* #endif */ /* PAM_FAIL_DELAY */ - gdm_error (_("Couldn't authenticate user")); - - if (prev_user) { - - unsigned max_auth_retries = 3; - char *val = gdm_read_default ("LOGIN_RETRIES="); - - if (val) { - max_auth_retries = atoi (val); - g_free (val); - } - - if (allow_retry == FALSE || pamerr == PAM_MAXTRIES || - ++auth_retries >= max_auth_retries) { - - g_free (prev_user); - prev_user = NULL; - auth_retries = 0; - } - } - } else { - /* cancel, configurator etc pressed */ - g_free (prev_user); - prev_user = NULL; - auth_retries = 0; - } - - goto pamerr; - } - - /* stop the timer for timed logins */ - if (started_timer) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - - g_free (login); - login = NULL; - g_free (prev_user); - prev_user = NULL; - - if ((pamerr = pam_get_item (pamh, PAM_USER, (void **)&p)) != PAM_SUCCESS) { - login = NULL; - /* is not really an auth problem, but it will - pretty much look as such, it shouldn't really - happen */ - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't authenticate user")); - goto pamerr; - } - - login = g_strdup ((const char *)p); - /* kind of anal, the greeter likely already knows, but it could have - been changed */ - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - - if ( ! gdm_slave_check_user_wants_to_log_in (login)) { - /* cleanup stuff */ - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, ""); - g_free (login); - login = NULL; - gdm_slave_greeter_ctl_no_ret (GDM_RESETOK, ""); - - gdm_verify_cleanup (d); - - goto verify_user_again; - } - - /* Check if user is root and is allowed to log in */ - consoleonly = gdm_read_default ("CONSOLE="); - if ((consoleonly != NULL) && - g_ascii_strcasecmp (consoleonly, "/dev/console") == 0) - gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT, FALSE); - - pwent = getpwnam (login); - if ( ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_ROOT) || - ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT) && ! local) ) && - pwent != NULL && - pwent->pw_uid == 0) { - gdm_error (_("Root login disallowed on display '%s'"), - display); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator " - "is not allowed to login " - "from this screen")); - /*gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, - _("Root login disallowed"));*/ - error_msg_given = TRUE; - -#ifdef HAVE_ADT - /* - * map console login not allowed as a pam_acct_mgmt () failure - * indeed that's where these checks should be made. - */ - pamerr = PAM_PERM_DENIED; -#endif /* HAVE_ADT */ - goto pamerr; - } - - if (gdm_daemon_config_get_value_bool (GDM_KEY_DISPLAY_LAST_LOGIN)) { - char *info = gdm_get_last_info (login); - gdm_slave_greeter_ctl_no_ret (GDM_MSG, info); - g_free (info); - } - - /* Check if the user's account is healthy. */ - pamerr = pam_acct_mgmt (pamh, null_tok); - switch (pamerr) { - case PAM_SUCCESS : - break; - case PAM_NEW_AUTHTOK_REQD : - if ((pamerr = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK)) != PAM_SUCCESS) { - gdm_error (_("Authentication token change failed for user %s"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe change of the authentication token failed. " - "Please try again later or contact the system administrator.")); - error_msg_given = TRUE; -#ifdef HAVE_ADT - /* Password change failed */ - pw_change = PW_FAILED; -#endif /* HAVE_ADT */ - goto pamerr; - } -#ifdef HAVE_ADT - /* Password changed */ - pw_change = PW_TRUE; -#endif /* HAVE_ADT */ - break; - case PAM_ACCT_EXPIRED : - gdm_error (_("User %s no longer permitted to access the system"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator has disabled your account.")); - error_msg_given = TRUE; - goto pamerr; - case PAM_PERM_DENIED : - gdm_error (_("User %s not permitted to gain access at this time"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator has disabled access to the system temporarily.")); - error_msg_given = TRUE; - goto pamerr; - default : - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't set acct. mgmt for %s"), login); - goto pamerr; - } - - pwent = getpwnam (login); - if (/* paranoia */ pwent == NULL || - ! gdm_setup_gids (login, pwent->pw_gid)) { - gdm_error (_("Cannot set user group for %s"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nCannot set your user group; " - "you will not be able to log in. " - "Please contact your system administrator.")); -#ifdef HAVE_ADT - /* - * map group setup error as a pam_setcred () failure - * indeed that's where this should be done. - */ - pamerr = PAM_SYSTEM_ERR; -#endif /* HAVE_ADT */ - goto pamerr; - } - - did_setcred = TRUE; - -#ifdef __sun - solaris_xserver_cred (login, d, pwent); -#endif - - /* Set credentials */ - pamerr = pam_setcred (pamh, PAM_ESTABLISH_CRED); - if (pamerr != PAM_SUCCESS) { - did_setcred = FALSE; - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't set credentials for %s"), login); - goto pamerr; - } - - credentials_set = TRUE; - opened_session = TRUE; - - /* Register the session */ - pamerr = pam_open_session (pamh, 0); - if (pamerr != PAM_SUCCESS) { - opened_session = FALSE; - /* we handle this above */ - did_setcred = FALSE; - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't open session for %s"), login); - goto pamerr; - } - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - cur_gdm_disp = NULL; - -#ifdef HAVE_LOGINDEVPERM - if (d->attached) - (void) di_devperm_login ("/dev/console", pwent->pw_uid, - pwent->pw_gid, NULL); -#endif /* HAVE_LOGINDEVPERM */ -#ifdef HAVE_ADT - audit_success_login (pw_change, pwent); -#endif /* HAVE_ADT */ - - return login; - - pamerr: -#ifdef HAVE_ADT - audit_fail_login (d, pw_change, pwent, pamerr); -#endif /* HAVE_ADT */ - - /* The verbose authentication is turned on, output the error - * message from the PAM subsystem */ - if ( ! error_msg_given && - gdm_slave_action_pending ()) { - /* I'm not sure yet if I should display this message for any other issues - heeten */ - if (pamerr == PAM_AUTH_ERR || - pamerr == PAM_USER_UNKNOWN) { - gboolean is_capslock = FALSE; - const char *basemsg; - char *msg; - char *ret; - - ret = gdm_slave_greeter_ctl (GDM_QUERY_CAPSLOCK, ""); - if ( ! ve_string_empty (ret)) - is_capslock = TRUE; - g_free (ret); - - /* Only give this message if we actually asked for - password, otherwise it would be silly to say that - the password may have been wrong */ - if (did_we_ask_for_password) { - basemsg = _("\nIncorrect username or password. " - "Letters must be typed in the correct " - "case."); - } else { - basemsg = _("\nAuthentication failed. " - "Letters must be typed in the correct " - "case."); - } - if (is_capslock) { - msg = g_strconcat (basemsg, " ", - _("Caps Lock is on."), - NULL); - } else { - msg = g_strdup (basemsg); - } - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, msg); - g_free (msg); - } else { - gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, _("Authentication failed")); - } - } - - did_setcred = FALSE; - opened_session = FALSE; - - if (pamh != NULL) { - pam_handle_t *tmp_pamh; - gdm_sigterm_block_push (); - gdm_sigchld_block_push (); - tmp_pamh = pamh; - pamh = NULL; - gdm_sigchld_block_pop (); - gdm_sigterm_block_pop (); - - /* Throw away the credentials */ - if (credentials_set) - pam_setcred (tmp_pamh, PAM_DELETE_CRED); - pam_end (tmp_pamh, pamerr); - } - pamh = NULL; - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - g_free (login); - - cur_gdm_disp = NULL; - - return NULL; -} - -/** - * gdm_verify_setup_user: - * @login: The name of the user - * @display: The name of the display - * - * This is used for auto loging in. This just sets up the login - * session for this user - */ - -gboolean -gdm_verify_setup_user (GdmDisplay *d, const gchar *login, const gchar *display, - char **new_login) -{ - gint pamerr = 0; - struct passwd *pwent = NULL; - const void *p; - char *passreq; - char *pam_stack = NULL; - char *pam_service_name = NULL; - int null_tok = 0; - gboolean credentials_set; - const char *after_login; - - credentials_set = FALSE; - -#ifdef HAVE_ADT - int pw_change = PW_FALSE; /* if got to trying to change password */ -#endif /* HAVE_ADT */ - - *new_login = NULL; - - if (login == NULL) - return FALSE; - - cur_gdm_disp = d; - - g_free (extra_standalone_message); - extra_standalone_message = g_strdup_printf ("%s (%s)", - _("Automatic login"), - login); - - /* - * Initialize a PAM session for the user... - * Get value per-display so different displays can use different - * PAM Stacks, in case one display should use a different - * authentication mechanism than another display. - */ - pam_stack = gdm_daemon_config_get_value_string_per_display (GDM_KEY_PAM_STACK, (char *)display); - pam_service_name = g_strdup_printf ("%s-autologin", pam_stack); - - if ( ! create_pamh (d, pam_service_name, login, &standalone_pamc, - display, &pamerr)) { - g_free (pam_stack); - g_free (pam_service_name); - goto setup_pamerr; - } - g_free (pam_stack); - g_free (pam_service_name); - - passreq = gdm_read_default ("PASSREQ="); - if ((passreq != NULL) && - g_ascii_strcasecmp (passreq, "YES") == 0) - gdm_daemon_config_set_value_bool (GDM_KEY_PASSWORD_REQUIRED, TRUE); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_PASSWORD_REQUIRED)) - null_tok |= PAM_DISALLOW_NULL_AUTHTOK; - - /* Start authentication session */ - did_we_ask_for_password = FALSE; - if ((pamerr = pam_authenticate (pamh, null_tok)) != PAM_SUCCESS) { - if (gdm_slave_action_pending ()) { - gdm_error (_("Couldn't authenticate user")); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("Authentication failed")); - } - goto setup_pamerr; - } - - if ((pamerr = pam_get_item (pamh, PAM_USER, (void **)&p)) != PAM_SUCCESS) { - /* is not really an auth problem, but it will - pretty much look as such, it shouldn't really - happen */ - gdm_error (_("Couldn't authenticate user")); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("Authentication failed")); - goto setup_pamerr; - } - after_login = (const char *)p; - - if (after_login != NULL /* should never be */ && - strcmp (after_login, login) != 0) { - *new_login = g_strdup (after_login); - } - -#ifdef HAVE_ADT - /* to set up for same auditing calls as in gdm_verify_user */ - pwent = getpwnam (login); -#endif /* HAVE_ADT */ - - /* Check if the user's account is healthy. */ - pamerr = pam_acct_mgmt (pamh, null_tok); - switch (pamerr) { - case PAM_SUCCESS : - break; - case PAM_NEW_AUTHTOK_REQD : - /* XXX: this is for automatic and timed logins, - * we shouldn't be asking for new pw since we never - * authenticated the user. I suppose just ignoring - * this would be OK */ -#if 0 /* don't change password */ - if ((pamerr = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK)) != PAM_SUCCESS) { - gdm_error (_("Authentication token change failed for user %s"), login); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("\nThe change of the authentication token failed. " - "Please try again later or contact the system administrator.")); -#ifdef HAVE_ADT - pw_change = PW_FAILED; -#endif /* HAVE_ADT */ - goto setup_pamerr; - } -#ifdef HAVE_ADT - pw_change = PW_TRUE; -#endif /* HAVE_ADT */ -#endif /* 0 */ - break; - case PAM_ACCT_EXPIRED : - gdm_error (_("User %s no longer permitted to access the system"), login); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("The system administrator has disabled your account.")); - goto setup_pamerr; - case PAM_PERM_DENIED : - gdm_error (_("User %s not permitted to gain access at this time"), login); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("The system administrator has disabled your access to the system temporarily.")); - goto setup_pamerr; - default : - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't set acct. mgmt for %s"), login); - goto setup_pamerr; - } - - pwent = getpwnam (login); - if (/* paranoia */ pwent == NULL || - ! gdm_setup_gids (login, pwent->pw_gid)) { - gdm_error (_("Cannot set user group for %s"), login); - gdm_errorgui_error_box (cur_gdm_disp, - GTK_MESSAGE_ERROR, - _("Cannot set your user group; " - "you will not be able to log in. " - "Please contact your system administrator.")); -#ifdef HAVE_ADT - /* - * map group setup error as a pam_setcred () failure - * indeed that's where this should be done. - */ - pamerr = PAM_SYSTEM_ERR; -#endif /* HAVE_ADT */ - goto setup_pamerr; - } - - did_setcred = TRUE; - -#ifdef __sun - solaris_xserver_cred ((char *)login, d, pwent); -#endif - - /* Set credentials */ - pamerr = pam_setcred (pamh, PAM_ESTABLISH_CRED); - if (pamerr != PAM_SUCCESS) { - did_setcred = FALSE; - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't set credentials for %s"), login); - goto setup_pamerr; - } - - credentials_set = TRUE; - opened_session = TRUE; - - /* Register the session */ - pamerr = pam_open_session (pamh, 0); - if (pamerr != PAM_SUCCESS) { - did_setcred = FALSE; - opened_session = FALSE; - /* Throw away the credentials */ - pam_setcred (pamh, PAM_DELETE_CRED); - - if (gdm_slave_action_pending ()) - gdm_error (_("Couldn't open session for %s"), login); - goto setup_pamerr; - } - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - cur_gdm_disp = NULL; - - g_free (extra_standalone_message); - extra_standalone_message = NULL; - -#ifdef HAVE_LOGINDEVPERM - if (d->attached) - (void) di_devperm_login ("/dev/console", pwent->pw_uid, - pwent->pw_gid, NULL); -#endif /* HAVE_LOGINDEVPERM */ -#ifdef HAVE_ADT - audit_success_login (pw_change, pwent); -#endif /* HAVE_ADT */ - - return TRUE; - - setup_pamerr: - -#ifdef HAVE_ADT - audit_fail_login (d, pw_change, pwent, pamerr); -#endif /* HAVE_ADT */ - - did_setcred = FALSE; - opened_session = FALSE; - if (pamh != NULL) { - pam_handle_t *tmp_pamh; - - gdm_sigterm_block_push (); - gdm_sigchld_block_push (); - tmp_pamh = pamh; - pamh = NULL; - gdm_sigchld_block_pop (); - gdm_sigterm_block_pop (); - - /* Throw away the credentials */ - if (credentials_set) - pam_setcred (tmp_pamh, PAM_DELETE_CRED); - pam_end (tmp_pamh, pamerr); - } - pamh = NULL; - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - - cur_gdm_disp = NULL; - - g_free (extra_standalone_message); - extra_standalone_message = NULL; - - return FALSE; -} - -/** - * gdm_verify_cleanup: - * - * Unregister the user's session - */ - -void -gdm_verify_cleanup (GdmDisplay *d) -{ - gid_t groups[1] = { 0 }; - cur_gdm_disp = d; - - if (pamh != NULL) { - gint pamerr; - pam_handle_t *tmp_pamh; - gboolean old_opened_session; - gboolean old_did_setcred; - - gdm_debug ("Running gdm_verify_cleanup and pamh != NULL"); - - gdm_sigterm_block_push (); - gdm_sigchld_block_push (); - tmp_pamh = pamh; - pamh = NULL; - old_opened_session = opened_session; - opened_session = FALSE; - old_did_setcred = did_setcred; - did_setcred = FALSE; - gdm_sigchld_block_pop (); - gdm_sigterm_block_pop (); - - pamerr = PAM_SUCCESS; - -#ifdef HAVE_ADT - /* - * User exiting. - * If logged in, audit logout before cleaning up - */ - if (old_opened_session && old_did_setcred) { - audit_logout (); - } -#endif /* HAVE_ADT */ - /* Close the users session */ - if (old_opened_session) { - gdm_debug ("Running pam_close_session"); - pamerr = pam_close_session (tmp_pamh, 0); - } - - /* Throw away the credentials */ - if (old_did_setcred) { - gdm_debug ("Running pam_setcred with PAM_DELETE_CRED"); - pamerr = pam_setcred (tmp_pamh, PAM_DELETE_CRED); - } - - pam_end (tmp_pamh, pamerr); - -#ifdef HAVE_LOGINDEVPERM - if (old_opened_session && old_did_setcred && d->attached) { - (void) di_devperm_logout ("/dev/console"); - /* give it back to gdm user */ - (void) di_devperm_login ("/dev/console", - gdm_daemon_config_get_gdmuid (), - gdm_daemon_config_get_gdmgid (), NULL); - } -#endif /* HAVE_LOGINDEVPERM */ - - /* Workaround to avoid gdm messages being logged as PAM_pwdb */ - gdm_log_shutdown (); - gdm_log_init (); - } - - /* Clear the group setup */ - setgid (0); - /* this will get rid of any suplementary groups etc... */ - setgroups (1, groups); - - cur_gdm_disp = NULL; - - /* reset limits */ - gdm_reset_limits (); -} - -/** - * gdm_verify_check: - * - * Check that the authentication system is correctly configured. - * Not very smart, perhaps we should just whack this. - * - * Aborts daemon on error - */ - -void -gdm_verify_check (void) -{ - pam_handle_t *ph = NULL; - - if (pam_start (gdm_daemon_config_get_value_string (GDM_KEY_PAM_STACK), NULL, - &standalone_pamc, &ph) != PAM_SUCCESS) { - ph = NULL; /* be anal */ - - gdm_log_shutdown (); - gdm_log_init (); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_CONSOLE_NOTIFY)) - gdm_text_message_dialog - (C_(N_("Can't find PAM configuration for GDM."))); - gdm_fail ("gdm_verify_check: %s", - _("Can't find PAM configuration for GDM.")); - } - - if (ph != NULL) - pam_end (ph, PAM_SUCCESS); - - gdm_log_shutdown (); - gdm_log_init (); -} - -/* used in pam */ -gboolean -gdm_verify_setup_env (GdmDisplay *d) -{ - gchar **pamenv; - - if (pamh == NULL) - return FALSE; - - /* Migrate any PAM env. variables to the user's environment */ - /* This leaks, oh well */ - if ((pamenv = pam_getenvlist (pamh))) { - gint i; - - for (i = 0 ; pamenv[i] ; i++) { - putenv (g_strdup (pamenv[i])); - } - } - - return TRUE; -} diff --git a/daemon/verify-shadow.c b/daemon/verify-shadow.c deleted file mode 100644 index da6b369c..00000000 --- a/daemon/verify-shadow.c +++ /dev/null @@ -1,488 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include <glib/gi18n.h> -#include <pwd.h> -#include <shadow.h> -#include <grp.h> -#include <sys/types.h> -#include <unistd.h> -#include <string.h> - -#if defined (CAN_CLEAR_ADMCHG) && defined (HAVE_USERSEC_H) -# include <usersec.h> -#endif /* CAN_CLEAR_ADMCHG && HAVE_USERSEC_H */ - -#ifdef HAVE_CRYPT -# include <crypt.h> -#endif /* HAVE_CRYPT */ - -#include "gdm.h" -#include "misc.h" -#include "slave.h" -#include "verify.h" -#include "errorgui.h" -#include "gdm-common.h" -#include "gdm-daemon-config.h" -#include "gdm-socket-protocol.h" - -static char *selected_user = NULL; - -void -gdm_verify_select_user (const char *user) -{ - g_free (selected_user); - if (ve_string_empty (user)) - selected_user = NULL; - else - selected_user = g_strdup (user); -} - -static void -print_cant_auth_errbox (void) -{ - gboolean is_capslock = FALSE; - const char *basemsg; - char *msg; - char *ret; - - ret = gdm_slave_greeter_ctl (GDM_QUERY_CAPSLOCK, ""); - if ( ! ve_string_empty (ret)) - is_capslock = TRUE; - g_free (ret); - - basemsg = _("\nIncorrect username or password. " - "Letters must be typed in the correct " - "case."); - if (is_capslock) { - msg = g_strconcat (basemsg, " ", - _("Caps Lock is on."), - NULL); - } else { - msg = g_strdup (basemsg); - } - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, msg); - g_free (msg); -} - -/** - * gdm_verify_user: - * @username: Name of user or NULL if we should ask - * @display: Name of display to register with the authentication system - * @local: boolean if local - * @allow_retry: boolean. Not used by verify-crypt. If this code - * allowed the user to retry, this boolean would specify - * whether to enable this feature. We only want this - * feature to work for normal login, not for asking for - * root password to call the configurator. - * - * Provides a communication layer between the operating system's - * authentication functions and the gdmgreeter. - * - * Returns the user's login on success and NULL on failure. - */ - -gchar * -gdm_verify_user (GdmDisplay *d, - const char *username, - const gchar *display, - gboolean local, - gboolean allow_retry) -{ - gchar *login, *passwd, *ppasswd; - struct passwd *pwent; - struct spwd *sp; -#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS) \ - || defined (HAVE_LOGINRESTRICTIONS) - gchar *message = NULL; -#endif -#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS) - gchar *info_msg = NULL, *response = NULL; - gint reEnter, ret; -#endif - - if (local && d->timed_login_ok) - gdm_slave_greeter_ctl_no_ret (GDM_STARTTIMER, ""); - - if (username == NULL) { - authenticate_again: - /* Ask for the user's login */ - gdm_verify_select_user (NULL); - gdm_slave_greeter_ctl_no_ret (GDM_MSG, _("Please enter your username")); - login = gdm_slave_greeter_ctl (GDM_PROMPT, _("Username:")); - if (login == NULL || - gdm_slave_greeter_check_interruption ()) { - if ( ! ve_string_empty (selected_user)) { - /* user selected */ - g_free (login); - login = selected_user; - selected_user = NULL; - } else { - /* some other interruption */ - if (local) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - g_free (login); - return NULL; - } - } - gdm_slave_greeter_ctl_no_ret (GDM_MSG, ""); - - if (gdm_daemon_config_get_value_bool (GDM_KEY_DISPLAY_LAST_LOGIN)) { - char *info = gdm_get_last_info (login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, info); - g_free (info); - } - } else { - login = g_strdup (username); - } - gdm_slave_greeter_ctl_no_ret (GDM_SETLOGIN, login); - - pwent = getpwnam (login); - - setspent (); - - /* Lookup shadow password */ - sp = getspnam (login); - - /* Use shadow password when available */ - if (sp != NULL) { - ppasswd = g_strdup (sp->sp_pwdp); - } else { - /* In case shadow password cannot be retrieved (when using NIS - authentication for example), use standard passwd */ - if (pwent != NULL && - pwent->pw_passwd != NULL) - ppasswd = g_strdup (pwent->pw_passwd); - else - /* If no password can be retrieved, set it to NULL */ - ppasswd = NULL; - } - - endspent (); - - /* Request the user's password */ - if (pwent != NULL && - ve_string_empty (ppasswd)) { - /* eeek a passwordless account */ - passwd = g_strdup (""); - } else { - passwd = gdm_slave_greeter_ctl (GDM_NOECHO, _("Password:")); - if (passwd == NULL) - passwd = g_strdup (""); - if (gdm_slave_greeter_check_interruption ()) { - if (local) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - } - - if (local) - gdm_slave_greeter_ctl_no_ret (GDM_STOPTIMER, ""); - - if (pwent == NULL) { - gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY)); - g_warning (_("Couldn't authenticate user \"%s\""), login); - - print_cant_auth_errbox (); - - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - - /* Check whether password is valid */ - if (ppasswd == NULL || (ppasswd[0] != '\0' && - strcmp (crypt (passwd, ppasswd), ppasswd) != 0)) { - gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY)); - g_warning (_("Couldn't authenticate user \"%s\""), login); - - print_cant_auth_errbox (); - - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - - if ( ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_ROOT)|| - ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT) && ! local) ) && - pwent->pw_uid == 0) { - g_warning (_("Root login disallowed on display '%s'"), display); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("The system administrator " - "is not allowed to login " - "from this screen")); - /*gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, - _("Root login disallowed"));*/ - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - -#ifdef HAVE_LOGINRESTRICTIONS - - /* Check with the 'loginrestrictions' function - if the user has been disallowed */ - if (loginrestrictions (login, 0, NULL, &message) != 0) { - g_warning (_("User %s not allowed to log in"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator " - "has disabled your " - "account.")); - g_free (login); - g_free (passwd); - g_free (ppasswd); - if (message != NULL) - free (message); - return NULL; - } - - if (message != NULL) - free (message); - message = NULL; - -#else /* ! HAVE_LOGINRESTRICTIONS */ - - /* check for the standard method of disallowing users */ - if (pwent->pw_shell != NULL && - (strcmp (pwent->pw_shell, "/sbin/nologin") == 0 || - strcmp (pwent->pw_shell, "/bin/true") == 0 || - strcmp (pwent->pw_shell, "/bin/false") == 0)) { - g_warning (_("User %s not allowed to log in"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nThe system administrator " - "has disabled your " - "account.")); - /*gdm_slave_greeter_ctl_no_ret (GDM_ERRDLG, - _("Login disabled"));*/ - g_free (login); - g_free (passwd); - g_free (ppasswd); - return NULL; - } - -#endif /* HAVE_LOGINRESTRICTIONS */ - - g_free (passwd); - g_free (ppasswd); - - if ( ! gdm_slave_check_user_wants_to_log_in (login)) { - g_free (login); - login = NULL; - goto authenticate_again; - } - - if ( ! gdm_setup_gids (login, pwent->pw_gid)) { - g_warning (_("Cannot set user group for %s"), login); - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nCannot set your user group; " - "you will not be able to log in. " - "Please contact your system administrator.")); - g_free (login); - return NULL; - } - -#if defined (HAVE_PASSWDEXPIRED) && defined (HAVE_CHPASS) - - switch (passwdexpired (login, &info_msg)) { - case 1 : - g_warning (_("Password of %s has expired"), login); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("You are required to change your password.\n" - "Please choose a new one.")); - g_free (info_msg); - - do { - ret = chpass (login, response, &reEnter, &message); - g_free (response); - - if (ret != 1) { - if (ret != 0) { - gdm_slave_greeter_ctl_no_ret (GDM_ERRBOX, - _("\nCannot change your password; " - "you will not be able to log in. " - "Please try again later or contact " - "your system administrator.")); - } else if ((reEnter != 0) && (message)) { - response = gdm_slave_greeter_ctl (GDM_NOECHO, message); - if (response == NULL) - response = g_strdup (""); - } - } - - g_free (message); - message = NULL; - - } while ( ((reEnter != 0) && (ret == 0)) - || (ret ==1) ); - - g_free (response); - g_free (message); - - if ((ret != 0) || (reEnter != 0)) { - return NULL; - } - -#if defined (CAN_CLEAR_ADMCHG) - /* The password is changed by root, clear the ADM_CHG - flag in the passwd file */ - ret = setpwdb (S_READ | S_WRITE); - if (!ret) { - upwd = getuserpw (login); - if (upwd == NULL) { - ret = -1; - } - else { - upwd->upw_flags &= ~PW_ADMCHG; - ret = putuserpw (upwd); - if (!ret) { - ret = endpwdb (); - } - } - } - - if (ret) { - gdm_errorgui_error_box (d, GTK_MESSAGE_WARNING, - _("Your password has been changed but " - "you may have to change it again. " - "Please try again later or contact " - "your system administrator.")); - } - -#else /* !CAN_CLEAR_ADMCHG */ - gdm_errorgui_error_box (d, GTK_MESSAGE_WARNING, - _("Your password has been changed but you " - "may have to change it again. Please try again " - "later or contact your system administrator.")); - -#endif /* CAN_CLEAR_ADMCHG */ - - break; - - case 2 : - g_warning (_("Password of %s has expired"), login); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("Your password has expired.\n" - "Only a system administrator can now change it")); - g_free (info_msg); - return NULL; - break; - - case -1 : - g_warning (_("Internal error on passwdexpired")); - gdm_errorgui_error_box (d, GTK_MESSAGE_ERROR, - _("An internal error occurred. You will not be able to log in.\n" - "Please try again later or contact your system administrator.")); - g_free (info_msg); - return NULL; - break; - - default : - g_free (info_msg); - break; - } - -#endif /* HAVE_PASSWDEXPIRED && HAVE_CHPASS */ - - return login; -} - -/** - * gdm_verify_setup_user: - * @login: The name of the user - * @display: The name of the display - * - * This is used for auto loging in. This just sets up the login - * session for this user - */ - -gboolean -gdm_verify_setup_user (GdmDisplay *d, - const gchar *login, - const gchar *display, - char **new_login) -{ - struct passwd *pwent; - - *new_login = NULL; - - pwent = getpwnam (login); - if (pwent == NULL) { - g_warning (_("Cannot get passwd structure for %s"), login); - return FALSE; - } - - if ( ! gdm_setup_gids (login, pwent->pw_gid)) { - g_warning (_("Cannot set user group for %s"), login); - gdm_errorgui_error_box (d, - GTK_MESSAGE_ERROR, - _("\nCannot set your user group; " - "you will not be able to log in. " - "Please contact your system administrator.")); - return FALSE; - } - - return TRUE; -} - -/** - * gdm_verify_cleanup: - * - * Unregister the user's session */ - -void -gdm_verify_cleanup (GdmDisplay *d) -{ - gid_t groups[1] = { 0 }; - - /* Clear the group setup */ - setgid (0); - /* this will get rid of any suplementary groups etc... */ - setgroups (1, groups); -} - -/** - * gdm_verify_check: - * - * Check that the authentication system is correctly configured. - * - * Aborts daemon on error - */ - -void -gdm_verify_check (void) -{ -} - -/* used in pam */ -gboolean -gdm_verify_setup_env (GdmDisplay *d) -{ - return TRUE; -} - -/* EOF */ diff --git a/daemon/verify.h b/daemon/verify.h deleted file mode 100644 index a861c6e4..00000000 --- a/daemon/verify.h +++ /dev/null @@ -1,44 +0,0 @@ -/* GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_VERIFY_H -#define GDM_VERIFY_H - -#include "gdm.h" -#include "display.h" - -/* If username is NULL, we ask, if local is FALSE, don't start - * the timed login timer */ -gchar *gdm_verify_user (GdmDisplay *d, - const char *username, - const gchar *display, - gboolean local, - gboolean allow_retry); -void gdm_verify_cleanup (GdmDisplay *d); -void gdm_verify_check (void); -void gdm_verify_select_user (const char *user); -/* used in pam */ -gboolean gdm_verify_setup_env (GdmDisplay *d); -gboolean gdm_verify_setup_user (GdmDisplay *d, - const gchar *login, - const gchar *display, - char **new_login); - -#endif /* GDM_VERIFY_H */ - -/* EOF */ diff --git a/daemon/xdmcp.c b/daemon/xdmcp.c deleted file mode 100644 index 2a07efe7..00000000 --- a/daemon/xdmcp.c +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "config.h" - -#include <glib.h> -#include <glib/gi18n.h> - -#include "display.h" -#include "gdm-daemon-config.h" -#include "gdm-log.h" - -#include "gdm-xdmcp-manager.h" -#include "xdmcp.h" - -#ifdef HAVE_LIBXDMCP - -static GdmXdmcpManager *xdmcp_manager = NULL; - -gboolean -gdm_xdmcp_init (void) -{ - xdmcp_manager = gdm_xdmcp_manager_new (); - return TRUE; -} - -void -gdm_xdmcp_run (void) -{ - if (xdmcp_manager != NULL) { - gdm_xdmcp_manager_start (xdmcp_manager, NULL); - } -} - -void -gdm_xdmcp_close (void) -{ - g_object_unref (xdmcp_manager); -} - -static void -reconnect_to_parent (GdmDisplay *to) -{ - GError *error; - gchar *command_argv[10]; - const gchar *proxyreconnect = gdm_daemon_config_get_value_string (GDM_KEY_XDMCP_PROXY_RECONNECT); - - command_argv[0] = (char *)proxyreconnect; - command_argv[1] = "--display"; - command_argv[2] = to->parent_disp; - command_argv[3] = "--display-authfile"; - command_argv[4] = to->parent_auth_file; - command_argv[5] = "--to"; - command_argv[6] = to->name; - command_argv[7] = "--to-authfile"; - command_argv[8] = to->authfile; - command_argv[9] = NULL; - - gdm_debug ("XDMCP: migrating display by running " - "'%s --display %s --display-authfile %s --to %s --to-authfile %s'", - proxyreconnect, - to->parent_disp, to->parent_auth_file, - to->name, to->authfile); - - error = NULL; - if (!g_spawn_async (NULL, command_argv, NULL, 0, NULL, NULL, NULL, &error)) { - gdm_error (_("%s: Failed to run " - "'%s --display %s --display-authfile %s --to %s --to-authfile %s': %s"), - "gdm_xdmcp_migrate", - proxyreconnect, - to->parent_disp, to->parent_auth_file, - to->name, to->authfile, - error->message); - g_error_free (error); - } -} - -void -gdm_xdmcp_migrate (GdmDisplay *from, GdmDisplay *to) -{ - if (from->type != TYPE_XDMCP_PROXY || - to->type != TYPE_XDMCP_PROXY) - return; - g_free (to->parent_disp); - to->parent_disp = from->parent_disp; - from->parent_disp = NULL; - - g_free (to->parent_auth_file); - to->parent_auth_file = from->parent_auth_file; - from->parent_auth_file = NULL; - - reconnect_to_parent (to); -} - -#else /* HAVE_LIBXDMCP */ - -/* Here come some empty stubs for no XDMCP support */ -int -gdm_xdmcp_init (void) -{ - gdm_error (_("%s: No XDMCP support"), "gdm_xdmcp_init"); - return FALSE; -} - -void -gdm_xdmcp_run (void) -{ - gdm_error (_("%s: No XDMCP support"), "gdm_xdmcp_run"); -} - -void -gdm_xdmcp_close (void) -{ - gdm_error (_("%s: No XDMCP support"), "gdm_xdmcp_close"); -} - -void -gdm_xdmcp_migrate (GdmDisplay *from, GdmDisplay *to) -{ - gdm_error (_("%s: No XDMCP support"), "gdm_xdmcp_migrate"); -} - -#endif /* HAVE_LIBXDMCP */ diff --git a/daemon/xdmcp.h b/daemon/xdmcp.h deleted file mode 100644 index d9870ffd..00000000 --- a/daemon/xdmcp.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- - * - * GDM - The GNOME Display Manager - * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net> - * - * 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 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef GDM_XDMCP_H -#define GDM_XDMCP_H - -/* Note that these are defined as empty stubs if there is no XDMCP support */ -gboolean gdm_xdmcp_init (void); -void gdm_xdmcp_run (void); -void gdm_xdmcp_close (void); - -void gdm_xdmcp_migrate (GdmDisplay *from, GdmDisplay *to); - -#endif /* GDM_XDMCP_H */ |