Commit 05e9b486 authored by 1's avatar 1 Committed by Martin Peterson

Nailed down the bug that has been haunting me the past couple of days. gdm


1999-08-11    <mkp@mkp.net>

	* daemon/auth.c: Nailed down the bug that has been haunting me the
 	past couple of days. gdm no longer corrupts ~user/.Xauthority if
 	it contains ``foreign'' cookies.

1999-08-08    <mkp@mkp.net>

	Finally merged the Ottawa megapatch:

	* daemon/auth.c: Real XAuth implementation. Doesn't rely on
 	/usr/bin/X11/xauth anymore.

	* gui/gdmlogin.c: Implemented browser functionality.

	* gui/gdmconfig.c: First shot at a graphical configuration tool.

	* gui/gdmface.c: Face selector capplet.

1999-08-07    <mkp@mkp.net>

	* Replaced gdm_putenv() with calls to setenv() as putenv() is
 	broken by specification.

1999-08-02    <mkp@mkp.net>

	* md5.c, md5.h, cookie.c: Fixed MD5 endianness problem (Reported
 	by <gewrgiou@imbc.gr>, bugzilla 3898).
parent c8f25c94
Martin Kasper Petersen <mkp@SunSITE.auc.dk>
Author:
Martin K. Petersen <mkp@mkp.net>
Contributions from:
Alan Cox <alan@redhat.com>
Carsten Schaar <nhadcasc@fs-maphy.uni-hannover.de>
Christopher Blizzard <blizzard@redhat.com>
Elliot Lee <sopwith@redhat.com>
Federico Mena Quintero <federico@nuclecu.unam.mx>
Gregory McLean <gregm@comstar.net>
Jacob Berkman <jberk+@cmu.edu>
Jeff Garzik <jgarzik@pobox.com>
Jochen Friedrich <jochen@scram.de>
Karsten Weiss <karsten@addx.au.s.shuttle.de>
Kevin Vajk <kvajk@ricochet.net>
Michael K. Johnson <johnsonm@redhat.com>
Miguel de Icaza <miguel@kernel.org>
Owen Taylor <otaylor@redhat.com>
nalin@thermo.stat.ncsu.edu
Translators:
Anders Carlsson <anders.carlsson@tordata.se>
Kjartan Maraas <kmaraas@online.no>
Pablo Saratxaga <srtxg@chanae.alphanet.ch>
Vincent Renardias <vincent@debian.org>
Tristan Tarrant <ttarrant@etnoteam.it>
1999-08-11 <mkp@mkp.net>
* daemon/auth.c: Nailed down the bug that has been haunting me the
past couple of days. gdm no longer corrupts ~user/.Xauthority if
it contains ``foreign'' cookies.
1999-08-08 <mkp@mkp.net>
Finally merged the Ottawa megapatch:
* daemon/auth.c: Real XAuth implementation. Doesn't rely on
/usr/bin/X11/xauth anymore.
* gui/gdmlogin.c: Implemented browser functionality.
* gui/gdmconfig.c: First shot at a graphical configuration tool.
* gui/gdmface.c: Face selector capplet.
1999-08-07 <mkp@mkp.net>
* Replaced gdm_putenv() with calls to setenv() as putenv() is
broken by specification.
1999-08-07 Anders Carlsson <anders.carlsson@tordata.se>
* configure.in (ALL_LINGUAS): Added sv to ALL_LINGUAS.
1999-08-02 <mkp@mkp.net>
* md5.c, md5.h, cookie.c: Fixed MD5 endianness problem (Reported
by <gewrgiou@imbc.gr>, bugzilla 3898).
1999-07-24 Tristan Tarrant <ttarrant@etnoteam.it>
* gui/gdmchooser.c (main): centre all dialogs
......
This package is actively developed and maintained.
Don't commit changes without asking mkp@mkp.net first unless you are
doing translation stuff.
Martin
SUBDIRS = config macros pixmaps daemon gui docs intl po
EXTRA_DIST = ChangeLog README.install gdm.spec
EXTRA_DIST = ChangeLog README.install RELEASENOTES
......@@ -4,10 +4,9 @@
The Gnome Display Manager is a re-implementation of the well known xdm
program. gdm consists of four separate parts: A small daemon, two
slightly different graphical login programs and a host chooser.
program.
gdm 2.0 implements all significant features required for managing
gdm 2.0beta1 implements all significant features required for managing
local and remote displays.
gdm daemon:
......@@ -26,6 +25,7 @@ gdmlogin:
o Iconified login window
o Session selection support
o Language selection support
o Face browser
gdmchooser:
......@@ -52,7 +52,3 @@ logging (see README.install) and include your syslog and
Martin K. Petersen, The Gnome Project
PS. If you find gdm useful and have a spare Sun E450 please don't
hesitate in donating it to me. Mail me for details. Thanks.
QUICK NOTES ON INSTALLATION/USE:
For security reasons a dedicated group id is needed for proper
operation! gdm assumes that the group is called `gdm'. Furthermore gdm
relies on the existence of a `nobody' user. Create these before
running make install.
First of all: gdm is a *daemon* -- not a common user application. It
requires extensive knowledge about your system setup to install and
configure. gdm isn't - and never will be - Plug and Play
(i.e. ./configure ; make install).
For security reasons a dedicated user and group id are required for
proper operation! gdm assumes that both the user and the group are
called `gdm'. Create these before running make install.
You should run ``make install'' as root to get the permissions right
on the authentication directory.
......
Indirect choosing was ripped out again. Broke too much and was way too ugly.
I came up with a better design that will definitely go in before 2.0-proper.
Otherwise all opcodes of the XDMCP 1.0 spec are supported.
gdmconfig doesn't work. It's only GUI code so far.
gdm-manual.txt should be updated and converted to SGML before gdm2 release.
I haven't quite made up my mind whether tab-completion goes back in or not.
gdmlogin should honour user geometry parameters.
WORK IN PROGRESS:
o Picon capplet for selecting the bitmap to appear in the browser.
o gdmconfig - a program for configuring the gdm.conf file.
#undef PACKAGE
#undef VERSION
#undef HAVE_LIBSM
#undef GDM_XAUTH_PATH
#undef ENABLE_NLS
#undef HAVE_CATGETS
#undef HAVE_GETTEXT
......
[appearance]
Browser=1
Completion=1
Logo=1
LogoImage=@pixmapdir@/gnome-logo-large.png
NoFaceImage=@pixmapdir@/nophoto.png
GlobalImageDir=@datadir@/faces/
Quiver=1
Iconify=1
IconFile=@pixmapdir@/gdm.xpm
Gtkrc=
[system]
ShutdownMenu=0
SuspendCommand=
UserFileCutoffSize=65536
UserIconMaxWidth=128
UserIconMaxHeight=128
DefaultPath=@bindir@:/usr/local/bin:/usr/bin/X11:/usr/bin:/bin
VerboseAuth=0
AllowRoot=0
RelaxPermissions=0
RetryDelay=3
LocaleFile=@localedir@/locale.alias
[messages]
Welcome=Welcome to %h
[daemon]
SessionDir=@sysconfdir@/gdm/Sessions
PidFile=/var/run/gdm.pid
Greeter=@bindir@/gdmlogin --disable-sound
Chooser=@bindir@/gdmchooser --disable-sound
User=gdm
Greeter=@bindir@/gdmlogin --disable-sound
Group=gdm
HaltCommand=shutdown -h now
DisplayInitDir=@sysconfdir@/gdm/Init
KillInitClients=1
PreSessionScriptDir=@sysconfdir@/gdm/PreSession
PostSessionScriptDir=@sysconfdir@/gdm/PostSession
AuthDir=@authdir@
LogDir=@authdir@
DefaultPath=/bin:/usr/bin:/usr/bin/X11:/usr/local/bin
PidFile=/var/run/gdm.pid
PostSessionScriptDir=@sysconfdir@/gdm/PostSession/
PreSessionScriptDir=@sysconfdir@/gdm/PreSession/
RebootCommand=shutdown -r now
RootPath=/sbin:/usr/sbin:/bin:/usr/bin:/usr/bin/X11:/usr/local/bin
ServAuthDir=@authdir@
SessionDir=@sysconfdir@/gdm/Sessions/
UserAuthDir=
UserAuthFBDir=/tmp
UserAuthFile=.Xauthority
User=gdm
[servers]
0=/usr/bin/X11/X
#1=/usr/bin/X11/X
[security]
AllowRoot=0
UserMaxFile=65536
RelaxPermissions=0
RetryDelay=3
VerboseAuth=1
[xdmcp]
Enable=1
Enable=0
MaxPending=4
MaxManageWait=20
MaxSessions=4
MaxSessions=16
MaxWait=30
Port=177
[gui]
GtkRC=
MaxIconWidth=128
MaxIconHeight=128
[greeter]
Browser=0
Exclude=bin,daemon,adm,lp,sync,shutdown,halt,mail,news,uucp,operator,nobody
DefaultFace=@pixmapdir@/nobody.png
GlobalFaceDir=@datadir@/faces/
Font=-adobe-helvetica-bold-r-normal-*-*-180-*-*-*-*-*-*
Icon=@pixmapdir@/gdm.xpm
DefaultLocale=english
LocaleFile=@localedir@/locale.alias
Logo=@pixmapdir@/gnome-logo-large.png
Quiver=1
SystemMenu=0
Welcome=Welcome to %h
[chooser]
ImageDir=@datadir@/hosts
DefaultImage=@pixmapdir@/nohost.png
ScanTime=3
DefaultHostImg=@pixmapdir@/nohost.png
HostImageDir=@datadir@/hosts/
[debug]
Enable=0
[servers]
0=/usr/bin/X11/X
#1=/usr/bin/X11/X
AC_INIT(daemon/gdm.h)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(gdm,2.0.0)
AM_INIT_AUTOMAKE(gdm,2.0beta1)
AM_MAINTAINER_MODE
AM_ACLOCAL_INCLUDE(macros)
......@@ -64,9 +64,10 @@ for I in $LDFLAGS $LIBS -L/usr/lib; do
fi
esac
done
if test -n "$LIBWRAP_PATH"; then
AC_MSG_RESULT(yes)
AC_HAVE_LIBRARY(nsl, LIBS="$LIBS -lnsl")
AC_CHECK_LIB(nsl, ypbind, LIBS="$LIBS -lnsl")
else
AC_MSG_RESULT(no)
fi
......@@ -88,12 +89,6 @@ if test -n "$LIBWRAP_PATH"; then
fi
LIBS="$LIBS $LIBWRAP_PATH"
AC_PATH_PROG(ac_xauth, xauth)
GDM_XAUTH_PATH=$ac_xauth
AC_DEFINE_UNQUOTED(GDM_XAUTH_PATH, "$ac_xauth")
AC_OUTPUT([
Makefile
daemon/Makefile
......
......@@ -26,5 +26,5 @@ gdm_SOURCES = \
md5.c \
md5.h
gdm_LDADD = $(GNOME_LIBDIR) $(GNOME_LIBS) -lXdmcp -lX11 $(INTLLIBS)
gdm_LDADD = $(GNOME_LIBDIR) $(GNOME_LIBS) -lXdmcp -lXau -lX11 $(INTLLIBS)
......@@ -16,8 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* This file contains the X Authentication code
/* Code for cookie handling. This really needs to be modularized to
* support other XAuth types and possibly DECnet...
*/
#include <config.h>
......@@ -28,130 +28,297 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <X11/Xauth.h>
#include "gdm.h"
static const gchar RCSid[]="$Id$";
extern gchar *GdmAuthDir;
extern gid_t GdmGroupId;
extern gchar *GdmServAuthDir;
extern gchar *GdmUserAuthDir;
extern gchar *GdmUserAuthFile;
extern gchar *GdmUserAuthFB;
extern gint GdmUserMaxFile;
extern gint GdmRelaxPerms;
extern gchar **gdm_arg_munch(gchar *);
extern void gdm_cookie_generate(GdmDisplay *d);
extern void *gdm_debug(const gchar *, ...);
extern void *gdm_error(const gchar *, ...);
extern void gdm_cookie_generate (GdmDisplay *d);
extern void gdm_debug (const gchar *, ...);
extern void gdm_error (const gchar *, ...);
extern gboolean gdm_file_check (gchar *caller, uid_t user, gchar *dir, gchar *file,
gboolean absentok, gint maxsize, gint perms);
void gdm_auth_secure_display(GdmDisplay *d);
void gdm_auth_user_add(GdmDisplay *d, gchar *home);
void gdm_auth_user_remove(GdmDisplay *d, gchar *home);
gboolean gdm_auth_secure_display (GdmDisplay *d);
gboolean gdm_auth_user_add (GdmDisplay *d, uid_t user, gchar *homedir);
void gdm_auth_user_remove (GdmDisplay *d, uid_t user);
void gdm_auth_secure_display(GdmDisplay *d)
gboolean
gdm_auth_secure_display (GdmDisplay *d)
{
gchar *authstr;
gchar **argv;
pid_t authpid;
FILE *af;
struct hostent *hentry;
struct in_addr *ia;
gchar *addr;
Xauth *xa;
guint i;
gdm_debug("gdm_auth_secure_display: Securing %s", d->name);
if (!d)
return (FALSE);
gdm_cookie_generate(d);
gdm_debug ("gdm_auth_secure_display: Setting up access for %s", d->name);
d->auth=g_strconcat(GdmAuthDir, "/", d->name, ".xauth", NULL);
if (!d->authfile)
d->authfile = g_strconcat (GdmServAuthDir, "/", d->name, ".Xauth", NULL);
if(unlink(d->auth) == -1)
gdm_debug(_("gdm_auth_secure_display: Could not unlink %s file: %s"),\
d->auth, strerror(errno));
authstr=g_strconcat(GDM_XAUTH_PATH, " -i -f ", d->auth, \
" add ", d->name, " . ", d->cookie, NULL);
argv=gdm_arg_munch(authstr);
switch(authpid=fork()) {
case 0:
execv(argv[0], argv);
gdm_error(_("gdm_auth_secure_display: Error starting xauth process: %s. Running insecure!"), strerror(errno));
return;
case -1:
gdm_error(_("gdm_auth_secure_display: Error forking xauth process. Running insecure!"));
return;
unlink (d->authfile);
af = fopen (d->authfile, "w");
if (!af)
return (FALSE);
gdm_cookie_generate (d);
/* FQDN or IP of display host */
hentry = gethostbyname (d->hostname);
if (!hentry) {
gdm_error ("gdm_auth_secure_display: Error getting hentry for %s", d->hostname);
return (FALSE);
}
/* Local access */
if (d->type == DISPLAY_LOCAL) {
gdm_debug ("gdm_auth_secure_display: Setting up socket access");
xa = g_new0 (Xauth, 1);
default:
waitpid(authpid, 0, 0); /* Wait for xauth to finish */
chown(d->auth, 0, GdmGroupId);
chmod(d->auth, S_IRUSR|S_IWUSR|S_IRGRP);
break;
if (!xa)
return (FALSE);
xa->family = FamilyLocal;
xa->address = d->hostname;
xa->address_length = strlen (d->hostname);
xa->number = g_strdup_printf ("%d", d->dispnum);
xa->number_length = 1;
xa->name = "MIT-MAGIC-COOKIE-1";
xa->name_length = 18;
xa->data = d->bcookie;
xa->data_length = strlen (d->bcookie);
XauWriteAuth (af, xa);
d->auths = g_slist_append (d->auths, xa);
}
gdm_debug ("gdm_auth_secure_display: Setting up network access");
/* Network access */
for (i=0 ; i < hentry->h_length ; i++) {
xa = g_new0 (Xauth, 1);
if (!xa)
return (FALSE);
xa->family = FamilyInternet;
addr = g_new0 (gchar, 4);
if (!addr)
return (FALSE);
ia = (struct in_addr *) hentry->h_addr_list[i];
if (!ia)
break;
memcpy (addr, &ia->s_addr, 4);
xa->address = addr;
xa->address_length = 4;
xa->number = g_strdup_printf ("%d", d->dispnum);
xa->number_length = 1;
xa->name = "MIT-MAGIC-COOKIE-1";
xa->name_length = 18;
xa->data = d->bcookie;
xa->data_length = strlen (d->bcookie);
XauWriteAuth (af, xa);
d->auths = g_slist_append (d->auths, xa);
}
fclose (af);
setenv ("XAUTHORITY", d->authfile, TRUE);
gdm_debug ("gdm_auth_secure_display: Setting up access for %s ... done", d->name);
return (TRUE);
}
void gdm_auth_user_add(GdmDisplay *d, gchar *home)
gboolean
gdm_auth_user_add (GdmDisplay *d, uid_t user, gchar *homedir)
{
gchar *authfile, *authstr;
gchar **argv;
pid_t authpid;
gchar *authdir;
gint authfd;
FILE *af;
GSList *auths = NULL;
gdm_debug("gdm_auth_user_add: Adding cookie to %s", home);
if (!d || !user)
return (FALSE);
authfile=g_strconcat(home, "/.Xauthority", NULL);
authstr=g_strconcat(GDM_XAUTH_PATH, " -i -f ", authfile, \
" add ", d->name, " . ", d->cookie, NULL);
gdm_debug ("gdm_auth_user_add: Adding cookie for %d", user);
argv=gdm_arg_munch(authstr);
g_free(authstr);
/* Determine whether UserAuthDir is specified. Otherwise ~user is used */
if (strlen (GdmUserAuthDir))
authdir = GdmUserAuthDir;
else
authdir = homedir;
switch(authpid=fork()) {
case 0:
execv(argv[0], argv);
gdm_error(_("gdm_auth_user_add: Error starting xauth process: %s"), strerror(errno));
return;
case -1:
gdm_error(_("gdm_auth_user_add: Error forking xauth process."));
return;
default:
waitpid(authpid, 0,0); /* Wait for xauth to finish */
chmod(authfile, S_IRUSR|S_IWUSR);
g_free(authfile);
break;
umask (077);
/* Find out if the Xauthority file passes the paranoia check */
if (! gdm_file_check ("gdm_auth_user_add", user, authdir, GdmUserAuthFile,
TRUE, GdmUserMaxFile, GdmRelaxPerms)) {
/* No go. Let's create a fallback file in GdmUserAuthFB (/tmp) */
d->authfb = TRUE;
d->userauth = g_strconcat (GdmUserAuthFB, "/.gdmXXXXXX", NULL);
authfd = mkstemp (d->userauth);
if (authfd == -1) {
g_free (d->userauth);
d->userauth = NULL;
return (FALSE);
}
af = fdopen (authfd, "w");
}
else { /* User's Xauthority file is ok */
d->authfb = FALSE;
d->userauth = g_strconcat (authdir, "/", GdmUserAuthFile, NULL);
/* FIXME: Better implement my own locking. The libXau one is not kosher */
if (XauLockAuth (d->userauth, 3, 3, 0) != LOCK_SUCCESS) {
g_free (d->userauth);
d->userauth = NULL;
return (FALSE);
}
af = fopen (d->userauth, "a+");
}
if (!af) {
/* Really no need to clean up here - this process is a goner anyway */
XauUnlockAuth (d->userauth);
g_free (d->userauth);
d->userauth = NULL;
return (FALSE);
}
gdm_debug ("gdm_auth_user_add: Using %s for cookies", d->userauth);
/* Write the authlist for the display to the cookie file */
auths = d->auths;
while (auths) {
XauWriteAuth (af, auths->data);
auths = auths->next;
}
fclose (af);
XauUnlockAuth (d->userauth);
setenv ("XAUTHORITY", d->userauth, TRUE);
gdm_debug ("gdm_auth_user_add: Done");
return (TRUE);
}
void gdm_auth_user_remove(GdmDisplay *d, gchar *home)
void
gdm_auth_user_remove (GdmDisplay *d, uid_t user)
{
gchar *authstr;
gchar **argv;
pid_t authpid;
FILE *af;
Xauth *xa;
GSList *keep = NULL;
gchar *authfile, *authdir;
gdm_debug("gdm_auth_user_remove: Removing cookie from %s", home);
if (!d || !d->userauth)
return;
authstr=g_strconcat(GDM_XAUTH_PATH, " -i -f ", home, "/.Xauthority", \
" remove ", d->name, NULL);
argv=gdm_arg_munch(authstr);
g_free(authstr);
gdm_debug ("gdm_auth_user_remove: Removing cookie from %s (%d)", d->userauth, d->authfb);
switch(authpid=fork()) {
case 0:
execv(argv[0], argv);
gdm_error(_("gdm_auth_user_remove: Error starting xauth process: %s"), strerror(errno));
/* If we are using the fallback cookie location, simply nuke the
* cookie file */
if (d->authfb) {
unlink (d->userauth);
g_free (d->userauth);
d->userauth = NULL;
return;
case -1:
gdm_error(_("gdm_auth_user_remove: Error forking xauth process."));
}
authfile = g_basename (d->userauth);
authdir = g_dirname (d->userauth);
/* Now, the cookie file could be owned by a malicious user who
* decided to concatenate something like /dev/kcore or his entire
* MP3 collection to it. So we better play it safe... */
if (! gdm_file_check ("gdm_auth_user_remove", user, authdir, authfile,
FALSE, GdmUserMaxFile, GdmRelaxPerms)) {
gdm_error (_("gdm_auth_user_remove: Ignoring suspicious looking cookie file %s"), d->userauth);
return;
}
g_free (authfile);
g_free (authdir);
if (XauLockAuth (d->userauth, 3, 3, 0) != LOCK_SUCCESS)
return;
default:
waitpid(authpid, 0, 0); /* Wait for xauth to finish */
break;
af = fopen (d->userauth, "r");
if (!af) {
XauUnlockAuth (d->userauth);
return;
}
/* Read the user's entire Xauth file into memory to avoid temporary file
* issues */
while ( (xa = XauReadAuth (af)) )
if (memcmp (d->bcookie, xa->data, xa->data_length))
keep = g_slist_append (keep, xa);
else
XauDisposeAuth (xa);
fclose (af);
/* Truncate and write out all cookies not belonging to this display */
af = fopen (d->userauth, "w");
if (!af) {
XauUnlockAuth (d->userauth);
return;
}
while (keep) {
XauWriteAuth (af, keep->data);
XauDisposeAuth (keep->data);
keep = keep->next;
}
g_slist_free (keep);
fclose (af);
XauUnlockAuth (d->userauth);
g_free (d->userauth);
d->userauth = NULL;
return;
}
/* EOF */
......@@ -19,7 +19,7 @@
/*
* Functions for generating MIT-MAGIC-COOKIEs.
*
* This code was derived (stolen!) from mcookie.c written by Rik Faith
* This code was derived (i.e. stolen) from mcookie.c written by Rik Faith
* <faith@cs.unc.edu>
*
*/
......@@ -51,13 +51,13 @@ struct rngs {
#define RNGS (sizeof(rngs)/sizeof(struct rngs))
void gdm_cookie_generate(GdmDisplay *);
void gdm_cookie_generate (GdmDisplay *);
void
gdm_cookie_generate(GdmDisplay *d)
gdm_cookie_generate (GdmDisplay *d)
{
int i;
struct MD5Context ctx;
struct GdmMD5Context ctx;
unsigned char digest[16];
unsigned char buf[MAXBUFFERSIZE];
int fd;
......@@ -68,38 +68,43 @@ gdm_cookie_generate(GdmDisplay *d)
char sub[8];
char cookie[40];
sub[0]='\0';
cookie[0]='\0';
sub[0] = '\0';
cookie[0] = '\0';
MD5Init( &ctx );
gettimeofday( &tv, &tz );
MD5Update( &ctx, (unsigned char *)&tv, sizeof( tv ) );
gdm_md5_init (&ctx);
gettimeofday (&tv, &tz);
gdm_md5_update (&ctx, (unsigned char *) &tv, sizeof (tv));
pid = getppid();
MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
gdm_md5_update (&ctx, (unsigned char *) &pid, sizeof (pid));
pid = getpid();
MD5Update( &ctx, (unsigned char *)&pid, sizeof( pid ));
gdm_md5_update (&ctx, (unsigned char *) &pid, sizeof (pid));