Commit 405013a3 authored by Jiri (George) Lebl's avatar Jiri (George) Lebl Committed by George Lebl

change some g_strconcat's to g_build_filename's to address #118040. still


Thu Jul 24 14:58:23 2003  George Lebl <jirka@5z.com>

	* daemon/gdm.c, daemon/slave.c, daemon/auth.c: change some
	  g_strconcat's to g_build_filename's to address #118040.
	  still more need to be converted

	* gdm.spec.in, daemon/gdm.h, config/gdm.conf.in, config/Makefile.am,
	  configure.in: By default use logdir of /var/log/gdm just
	  like redhat does it

	* daemon/gdm.c: check logdir to exist and if not set it to
	  ServAuthDir

	* gdm.spec.in, daemon/gdm.c, config/Makefile.am:  Make the
	  ServAuthDir permissions to be 1770 with owenership root.gdm.
	  That makes it impossible for the gdm user to run DoS attacks
	  against the gdm daemon (though without any process limits set
	  it can still somewhat do that)

	* daemon/slave.c, daemon/display.c, daemon/gdm.c, daemon/misc.c,
	  daemon/server.c: Hunt more races and hangs.  Make sure we really
	  don't do anything bad in signal handlers by making a setjmp
	  at the beginning of the slave_start function and returning
	  there from signal handlers to do final cleanup kind of stuff.
	  Also when we are receiving TERM signals while waiting on stuff
	  to die, be very un-nice to things and SIGKILL them.  Also stop
	  using sleep if we might be using alarm at the same time.

	* daemon/display.c: whack non-useful signal block push on unmanage,
	  and if we get a TERM signal while waiting on the slave, then send
	  a TERM signal to the slave again.

	* daemon/errorgui.c: set USER, USERNAME and LOGNAME to "gdm" so that
	  they don't end up root by some mistake

	* daemon/slave.c: Use home of root rather then /root for the home
	  directory of gdmsetup.  Also if we can't change to the home
	  directory chdir to / instead of leaving it at servauthdir.
	  Be anal about COOKIEs in the logfile.  Also when things go
	  just a bit wrong and not completely whacko, don't ABORT but
	  just REMANAGE, the toplevel loop of death will handle things
	  for us correctly.  And setsid a very close to the start of
	  the session to avoid a race ABORTing a display by mistake.

	* daemon/slave.c: make the PostLogin behave just like PostSession
	  with respect to the return value

	* daemon/verify-pam.c: avoid races on termination with the
	  verify_cleanup and handle some cases where crashes may (but
	  should not) occur.

	* daemon/gdm.c: whack unneeded signal blockers (the main daemon
	  is all async with a nice mainloop)

	* gui/gdmchooser.c: handle HUP gracefully, when one of the
	  config options we care about changes just restart self
	  instead of

	* gui/gdmlogin.c, gui/greeter/greeter_item_ulist.c: make
	  the username bold

	* docs/C/gdm.xml: update the PostLogin behaviour and the permissions
	  on the ServAuthDir
parent 38ad2d1c
Thu Jul 24 14:58:23 2003 George Lebl <jirka@5z.com>
* daemon/gdm.c, daemon/slave.c, daemon/auth.c: change some
g_strconcat's to g_build_filename's to address #118040.
still more need to be converted
* gdm.spec.in, daemon/gdm.h, config/gdm.conf.in, config/Makefile.am,
configure.in: By default use logdir of /var/log/gdm just
like redhat does it
* daemon/gdm.c: check logdir to exist and if not set it to
ServAuthDir
* gdm.spec.in, daemon/gdm.c, config/Makefile.am: Make the
ServAuthDir permissions to be 1770 with owenership root.gdm.
That makes it impossible for the gdm user to run DoS attacks
against the gdm daemon (though without any process limits set
it can still somewhat do that)
* daemon/slave.c, daemon/display.c, daemon/gdm.c, daemon/misc.c,
daemon/server.c: Hunt more races and hangs. Make sure we really
don't do anything bad in signal handlers by making a setjmp
at the beginning of the slave_start function and returning
there from signal handlers to do final cleanup kind of stuff.
Also when we are receiving TERM signals while waiting on stuff
to die, be very un-nice to things and SIGKILL them. Also stop
using sleep if we might be using alarm at the same time.
* daemon/display.c: whack non-useful signal block push on unmanage,
and if we get a TERM signal while waiting on the slave, then send
a TERM signal to the slave again.
* daemon/errorgui.c: set USER, USERNAME and LOGNAME to "gdm" so that
they don't end up root by some mistake
* daemon/slave.c: Use home of root rather then /root for the home
directory of gdmsetup. Also if we can't change to the home
directory chdir to / instead of leaving it at servauthdir.
Be anal about COOKIEs in the logfile. Also when things go
just a bit wrong and not completely whacko, don't ABORT but
just REMANAGE, the toplevel loop of death will handle things
for us correctly. And setsid a very close to the start of
the session to avoid a race ABORTing a display by mistake.
* daemon/slave.c: make the PostLogin behave just like PostSession
with respect to the return value
* daemon/verify-pam.c: avoid races on termination with the
verify_cleanup and handle some cases where crashes may (but
should not) occur.
* daemon/gdm.c: whack unneeded signal blockers (the main daemon
is all async with a nice mainloop)
* gui/gdmchooser.c: handle HUP gracefully, when one of the
config options we care about changes just restart self
instead of
* gui/gdmlogin.c, gui/greeter/greeter_item_ulist.c: make
the username bold
* docs/C/gdm.xml: update the PostLogin behaviour and the permissions
on the ServAuthDir
Wed Jul 23 15:13:33 2003 George Lebl <jirka@5z.com>
* Release 2.4.2.98
......
......@@ -12,6 +12,9 @@ thing and just ignore the ping if a signal comes, not sure how this will play wi
the X stuff and if this would completely whack us out. The other option is to have
a separate "pinger process" but that seems to heavyweight.
All the GUIs running as the gdm user should have some resource limits set to
make it hard to do DoS attacks by somehow exploiting a leak or some such.
Small TODO things:
- If we can't setup pam display user visible errors and not just syslog stuff
......
......@@ -27,6 +27,7 @@
#undef EXPANDED_GDMCONFIGDIR
#undef EXPANDED_LOCALEDIR
#undef EXPANDED_AUTHDIR
#undef EXPANDED_LOGDIR
#undef EXPANDED_SYSCONFDIR
#undef EXPANDED_SESSDIR
#undef X_SERVER
......
......@@ -5,6 +5,7 @@ localedir = $(sysconfdir)/gdm
sessdir = $(sysconfdir)/dm/Sessions
initdir = $(sysconfdir)/gdm/Init
authdir = $(localstatedir)/gdm
logdir = $(localstatedir)/gdm
gnomercdir = $(sysconfdir)/gdm
postdir = $(sysconfdir)/gdm/PostSession
predir = $(sysconfdir)/gdm/PreSession
......@@ -121,10 +122,16 @@ install-data-hook: gdm.conf Xsession gnome.desktop Default.desktop CDE.desktop D
chmod 755 $(DESTDIR)$(gnomercdir); \
fi
if test '!' -d $(DESTDIR)$(logdir); then \
$(mkinstalldirs) $(DESTDIR)$(logdir); \
chown root.root $(DESTDIR)$(logdir); \
chmod 755 $(DESTDIR)$(logdir); \
fi
if test '!' -d $(DESTDIR)$(authdir); then \
$(mkinstalldirs) $(DESTDIR)$(authdir); \
chown gdm.gdm $(DESTDIR)$(authdir); \
chmod 750 $(DESTDIR)$(authdir); \
chown root.gdm $(DESTDIR)$(authdir); \
chmod 1770 $(DESTDIR)$(authdir); \
fi
system=`uname`; \
......
......@@ -59,7 +59,7 @@ Group=gdm
# To try to kill all clients started at greeter time or in the Init script.
# doesn't always work, only if those clients have a window of their own
KillInitClients=true
LogDir=@EXPANDED_AUTHDIR@
LogDir=@EXPANDED_LOGDIR@
# You should probably never change this value unless you have a weird setup
PidFile=/var/run/gdm.pid
# Note that a post login script is run before a PreSession script.
......
......@@ -498,6 +498,11 @@ EXPANDED_AUTHDIR=`eval echo $AUTHDIR_TMP`
AC_SUBST(EXPANDED_AUTHDIR)
AC_DEFINE_UNQUOTED(EXPANDED_AUTHDIR,"$EXPANDED_AUTHDIR")
LOGDIR_TMP="$localstatedir/log/gdm"
EXPANDED_LOGDIR=`eval echo $LOGDIR_TMP`
AC_SUBST(EXPANDED_LOGDIR)
AC_DEFINE_UNQUOTED(EXPANDED_LOGDIR,"$EXPANDED_LOGDIR")
if test -x /usr/X11R6/bin/X; then
X_PATH="/usr/bin/X11:/usr/X11R6/bin:/opt/X11R6/bin"
X_SERVER_PATH="/usr/X11R6/bin"
......
......@@ -178,7 +178,7 @@ gdm_auth_secure_display (GdmDisplay *d)
/* Note, Xnest can't use the ServAuthDir unless running as
* root, which is rare anyway, unless the user is a wanker */
d->authfile = g_strconcat (GdmUserAuthFB, "/.gdmXXXXXX", NULL);
d->authfile = g_build_filename (GdmUserAuthFB, ".gdmXXXXXX", NULL);
umask (077);
authfd = g_mkstemp (d->authfile);
......@@ -438,7 +438,7 @@ try_user_add_again:
if (authdir == NULL)
d->userauth = NULL;
else
d->userauth = g_strconcat (authdir, "/", GdmUserAuthFile, NULL);
d->userauth = g_build_filename (authdir, GdmUserAuthFile, NULL);
/* Find out if the Xauthority file passes the paranoia check */
if (automatic_tmp_dir ||
......@@ -450,7 +450,7 @@ try_user_add_again:
/* No go. Let's create a fallback file in GdmUserAuthFB (/tmp) */
d->authfb = TRUE;
g_free (d->userauth);
d->userauth = g_strconcat (GdmUserAuthFB, "/.gdmXXXXXX", NULL);
d->userauth = g_build_filename (GdmUserAuthFB, ".gdmXXXXXX", NULL);
authfd = g_mkstemp (d->userauth);
if (authfd == -1) {
......
......@@ -43,6 +43,7 @@ extern gboolean GdmXdmcp;
extern gint xdmcp_sessions;
extern gint flexi_servers;
extern gint xdmcp_pending;
extern gboolean gdm_in_final_cleanup;
extern GSList *displays;
extern GdmConnection *fifoconn;
extern GdmConnection *pipeconn;
......@@ -249,28 +250,12 @@ gdm_display_manage (GdmDisplay *d)
d->slave_notify_fd = fds[0];
if (d->type == TYPE_LOCAL) {
gdm_slave_start (d);
/* if we ever return, bad things are happening */
gdm_server_stop (d);
_exit (DISPLAY_ABORT);
} else if (SERVER_IS_FLEXI (d)) {
gdm_slave_start (d);
gdm_server_stop (d);
/* we expect to return after the session finishes */
_exit (DISPLAY_REMANAGE);
} else if (d->type == TYPE_XDMCP &&
d->dispstat == XDMCP_MANAGED) {
gdm_slave_start (d);
gdm_server_stop (d);
/* we expect to return after the session finishes */
_exit (DISPLAY_REMANAGE);
}
gdm_slave_start (d);
/* should never retern */
/* yaikes, how did we ever get here, though I suppose
* it could be possible if XMDCP thing wasn't really set up */
/* yaikes, how did we ever get here? */
gdm_server_stop (d);
_exit (DISPLAY_ABORT);
_exit (DISPLAY_REMANAGE);
break;
......@@ -327,12 +312,25 @@ gdm_display_unmanage (GdmDisplay *d)
d->name, (int)d->slavepid);
/* Kill slave */
gdm_sigchld_block_push ();
if (d->slavepid > 1 &&
kill (d->slavepid, SIGTERM) == 0)
ve_waitpid_no_signal (d->slavepid, 0, 0);
kill (d->slavepid, SIGTERM) == 0) {
int ret;
wait_again:
errno = 0;
ret = waitpid (d->slavepid, NULL, 0);
if (ret < 0 &&
errno == EINTR) {
/* rekill the slave to tell it to
hurry up and die if we're getting
killed ourselves */
if (ve_signal_was_notified (SIGTERM) ||
ve_signal_was_notified (SIGINT)) {
kill (d->slavepid, SIGTERM);
}
goto wait_again;
}
}
d->slavepid = 0;
gdm_sigchld_block_pop ();
if (d->type == TYPE_LOCAL)
d->dispstat = DISPLAY_DEAD;
......
......@@ -211,6 +211,10 @@ setup_dialog (GdmDisplay *d, const char *name, int closefdexcept)
openlog ("gdm", LOG_PID, LOG_DAEMON);
ve_setenv ("LOGNAME", GdmUser, TRUE);
ve_setenv ("USER", GdmUser, TRUE);
ve_setenv ("USERNAME", GdmUser, TRUE);
ve_setenv ("DISPLAY", d->name, TRUE);
ve_unsetenv ("XAUTHORITY");
......
......@@ -101,6 +101,7 @@ gboolean gdm_emergency_server = FALSE;
gboolean gdm_first_login = TRUE;
int gdm_in_signal = 0;
gboolean gdm_in_final_cleanup = FALSE;
/* Configuration options */
gchar *GdmUser = NULL;
......@@ -212,6 +213,51 @@ compare_displays (gconstpointer a, gconstpointer b)
return 0;
}
static void
check_servauthdir (struct stat *statbuf)
{
/* Enter paranoia mode */
if (stat (GdmServAuthDir, statbuf) == -1) {
char *s = g_strdup_printf
(_("Server Authorization directory "
"(daemon/ServAuthDir) is set to %s "
"but this does not exist. Please "
"correct gdm configuration %s and "
"restart gdm."), GdmServAuthDir,
GDM_CONFIG_FILE);
gdm_text_message_dialog (s);
GdmPidFile = NULL;
gdm_fail (_("%s: Authdir %s does not exist. Aborting."), "gdm_config_parse", GdmServAuthDir);
}
if (! S_ISDIR (statbuf->st_mode)) {
char *s = g_strdup_printf
(_("Server Authorization directory "
"(daemon/ServAuthDir) is set to %s "
"but this is not a directory. Please "
"correct gdm configuration %s and "
"restart gdm."), GdmServAuthDir,
GDM_CONFIG_FILE);
gdm_text_message_dialog (s);
GdmPidFile = NULL;
gdm_fail (_("%s: Authdir %s is not a directory. Aborting."), "gdm_config_parse", GdmServAuthDir);
}
}
static void
check_logdir (void)
{
struct stat statbuf;
if (stat (GdmLogDir, &statbuf) == -1 ||
! S_ISDIR (statbuf.st_mode)) {
gdm_error (_("%s: Logdir %s does not exist or isn't a directory. Using ServAuthDir %s."), "gdm_config_parse",
GdmLogDir, GdmServAuthDir);
g_free (GdmLogDir);
GdmLogDir = g_strdup (GdmServAuthDir);
}
}
/**
* gdm_config_parse:
*
......@@ -400,8 +446,10 @@ gdm_config_parse (void)
gdm_fail (_("%s: No authdir specified."), "gdm_config_parse");
}
if (ve_string_empty (GdmLogDir))
GdmLogDir = GdmServAuthDir;
if (ve_string_empty (GdmLogDir)) {
g_free (GdmLogDir);
GdmLogDir = g_strdup (GdmServAuthDir);
}
if (ve_string_empty (GdmSessDir))
gdm_error (_("%s: No sessions directory specified."), "gdm_config_parse");
......@@ -640,35 +688,23 @@ gdm_config_parse (void)
g_free (bin);
/* Enter paranoia mode */
if (stat (GdmServAuthDir, &statbuf) == -1) {
char *s = g_strdup_printf
(_("Server Authorization directory "
"(daemon/ServAuthDir) is set to %s "
"but this does not exist. Please "
"correct gdm configuration %s and "
"restart gdm."), GdmServAuthDir,
GDM_CONFIG_FILE);
gdm_text_message_dialog (s);
GdmPidFile = NULL;
gdm_fail (_("%s: Authdir %s does not exist. Aborting."), "gdm_config_parse", GdmServAuthDir);
}
check_servauthdir (&statbuf);
if (! S_ISDIR (statbuf.st_mode)) {
char *s = g_strdup_printf
(_("Server Authorization directory "
"(daemon/ServAuthDir) is set to %s "
"but this is not a directory. Please "
"correct gdm configuration %s and "
"restart gdm."), GdmServAuthDir,
GDM_CONFIG_FILE);
gdm_text_message_dialog (s);
GdmPidFile = NULL;
gdm_fail (_("%s: Authdir %s is not a directory. Aborting."), "gdm_config_parse", GdmServAuthDir);
}
seteuid (0);
setegid (0);
/* Now set things up for us as */
chown (GdmServAuthDir, 0, GdmGroupId);
chmod (GdmServAuthDir, (S_IRWXU|S_IRWXG|S_ISVTX));
setegid (GdmGroupId);
seteuid (GdmUserId);
/* again paranoid */
check_servauthdir (&statbuf);
if (statbuf.st_uid != GdmUserId || statbuf.st_gid != GdmGroupId) {
if (statbuf.st_uid != 0 || statbuf.st_gid != GdmGroupId) {
char *s = g_strdup_printf
(_("Server Authorization directory "
"(daemon/ServAuthDir) is set to %s "
......@@ -681,28 +717,30 @@ gdm_config_parse (void)
gdm_text_message_dialog (s);
GdmPidFile = NULL;
gdm_fail (_("%s: Authdir %s is not owned by user %s, group %s. Aborting."), "gdm_config_parse",
GdmServAuthDir, GdmUser, GdmGroup);
GdmServAuthDir, gdm_root_user (), GdmGroup);
}
if (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRGRP|S_IXGRP)) {
if (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX)) {
char *s = g_strdup_printf
(_("Server Authorization directory "
"(daemon/ServAuthDir) is set to %s "
"but has the wrong permissions, it "
"should have permissions of 0750. "
"should have permissions of %o. "
"Please correct the permissions or "
"the gdm configuration %s and "
"restart gdm."),
GdmServAuthDir, GDM_CONFIG_FILE);
GdmServAuthDir, (S_IRWXU|S_IRWXG|S_ISVTX), GDM_CONFIG_FILE);
gdm_text_message_dialog (s);
GdmPidFile = NULL;
gdm_fail (_("%s: Authdir %s has wrong permissions %o. Should be 0750. Aborting."), "gdm_config_parse",
GdmServAuthDir, statbuf.st_mode);
gdm_fail (_("%s: Authdir %s has wrong permissions %o. Should be %o. Aborting."), "gdm_config_parse",
GdmServAuthDir, statbuf.st_mode, (S_IRWXU|S_IRWXG|S_ISVTX));
}
seteuid (0);
setegid (0);
check_logdir ();
/* Check that user authentication is properly configured */
gdm_verify_check ();
......@@ -814,7 +852,7 @@ gdm_final_cleanup (void)
gdm_debug ("gdm_final_cleanup");
gdm_sigchld_block_push ();
gdm_in_final_cleanup = TRUE;
if (extra_process > 1) {
/* we sigterm extra processes, and we
......@@ -823,8 +861,6 @@ gdm_final_cleanup (void)
extra_process = 0;
}
gdm_sigchld_block_pop ();
list = g_slist_copy (displays);
for (li = list; li != NULL; li = li->next) {
GdmDisplay *d = li->data;
......@@ -1839,11 +1875,9 @@ send_slave_ack (GdmDisplay *d, const char *resp)
g_free (not);
}
}
gdm_sigchld_block_push ();
if (d->slavepid > 1) {
kill (d->slavepid, SIGUSR2);
}
gdm_sigchld_block_pop ();
}
static void
......@@ -1856,11 +1890,9 @@ send_slave_command (GdmDisplay *d, const char *command)
write (d->master_notify_fd, cmd, strlen (cmd));
g_free (cmd);
}
gdm_sigchld_block_push ();
if (d->slavepid > 1) {
kill (d->slavepid, SIGUSR2);
}
gdm_sigchld_block_pop ();
}
......@@ -2265,10 +2297,10 @@ gdm_handle_message (GdmConnection *conn, const char *msg, gpointer data)
GSList *li;
for (li = displays; li != NULL; li = li->next) {
GdmDisplay *d = li->data;
gdm_sigchld_block_push ();
if (d->greetpid > 1)
kill (d->greetpid, SIGHUP);
gdm_sigchld_block_pop ();
else if (d->chooserpid > 1)
kill (d->chooserpid, SIGHUP);
}
} else if (strncmp (msg, GDM_SOP_WRITE_X_SERVERS " ",
strlen (GDM_SOP_WRITE_X_SERVERS " ")) == 0) {
......@@ -2659,10 +2691,8 @@ notify_displays_int (const char *key, int val)
gdm_fdprintf (disp->master_notify_fd,
"%c%s %d\n",
GDM_SLAVE_NOTIFY_KEY, key, val);
gdm_sigchld_block_push ();
if (disp->slavepid > 1)
kill (disp->slavepid, SIGUSR2);
gdm_sigchld_block_pop ();
}
}
}
......@@ -2677,10 +2707,8 @@ notify_displays_string (const char *key, const char *val)
gdm_fdprintf (disp->master_notify_fd,
"%c%s %s\n",
GDM_SLAVE_NOTIFY_KEY, key, val);
gdm_sigchld_block_push ();
if (disp->slavepid > 1)
kill (disp->slavepid, SIGUSR2);
gdm_sigchld_block_pop ();
}
}
}
......
......@@ -134,7 +134,7 @@ enum {
#define GDM_KEY_HALT "daemon/HaltCommand=/usr/bin/poweroff;/sbin/poweroff;/sbin/shutdown -h now;/usr/sbin/shutdown -h now"
#define GDM_KEY_INITDIR "daemon/DisplayInitDir=" EXPANDED_SYSCONFDIR "/gdm/Init"
#define GDM_KEY_KILLIC "daemon/KillInitClients=true"
#define GDM_KEY_LOGDIR "daemon/LogDir=" EXPANDED_AUTHDIR
#define GDM_KEY_LOGDIR "daemon/LogDir=" EXPANDED_LOGDIR
#define GDM_KEY_PATH "daemon/DefaultPath=/bin:/usr/bin:" X_CONF_PATH ":" EXPANDED_BINDIR
#define GDM_KEY_PIDFILE "daemon/PidFile=/var/run/gdm.pid"
#define GDM_KEY_POSTSESS "daemon/PostSessionScriptDir=" EXPANDED_SYSCONFDIR "/gdm/PostSession/"
......
......@@ -1240,6 +1240,13 @@ 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)
......@@ -1247,13 +1254,24 @@ jumpback_sighandler (int 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 (do_jumpback) {
do_jumpback = FALSE;
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;
......
......@@ -173,8 +173,12 @@ gdm_server_reinit (GdmDisplay *disp)
gdm_sigchld_block_pop ();
/* a hack we have no way of knowing when the server died */
sleep (1);
return;
}
/* Do note the interaction of this Setjmp and the signal
handlers and the Setjmp in slave.c */
if (Setjmp (reinitjmp) == 0) {
/* come here and we'll whack the server and wait to get
an xio error */
......@@ -192,6 +196,7 @@ gdm_server_reinit (GdmDisplay *disp)
XCloseDisplay (disp->dsp);
disp->dsp = NULL;
}
sleep (1);
Longjmp (reinitjmp, 1);
}
gdm_sigchld_block_pop ();
......@@ -218,6 +223,8 @@ gdm_server_reinit (GdmDisplay *disp)
void
gdm_server_stop (GdmDisplay *disp)
{
static gboolean waiting_for_server = FALSE;
if (disp == NULL)
return;
......@@ -242,13 +249,23 @@ gdm_server_stop (GdmDisplay *disp)
/* 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, 0, 0);
waiting_for_server = FALSE;
}
}
disp->servpid = 0;
if (servpid > 1 &&
kill (servpid, SIGTERM) == 0)
ve_waitpid_no_signal (servpid, 0, 0);
gdm_sigchld_block_pop ();
gdm_server_whack_lockfile (disp);
......
This diff is collapsed.
......@@ -122,10 +122,13 @@ gdm_verify_pam_conv (int num_msg, const struct pam_message **msg,
char *s;
struct pam_response *reply = NULL;
const char *login;
if (pamh == NULL)
return PAM_CONV_ERR;
reply = malloc (sizeof (struct pam_response) * num_msg);
if (!reply)
if (reply == NULL)
return PAM_CONV_ERR;
memset (reply, 0, sizeof (struct pam_response) * num_msg);
......@@ -261,9 +264,12 @@ gdm_verify_standalone_pam_conv (int num_msg, const struct pam_message **msg,
char *s, *text;
struct pam_response *reply = NULL;
if (pamh == NULL)
return PAM_CONV_ERR;
reply = malloc (sizeof (struct pam_response) * num_msg);
if (!reply)
if (reply == NULL)
return PAM_CONV_ERR;
memset (reply, 0, sizeof (struct pam_response) * num_msg);
......@@ -894,16 +900,22 @@ gdm_verify_cleanup (GdmDisplay *d)
if (pamh != NULL) {
gint pamerr;
pam_handle_t *tmp_pamh;
gdm_debug ("Running gdm_verify_cleanup and pamh != NULL");
gdm_sigterm_block_push ();
tmp_pamh = pamh;
pamh = NULL;
gdm_sigterm_block_pop ();
/* Close the users session */
pamerr = pam_close_session (pamh, 0);
pamerr = pam_close_session (tmp_pamh, 0);
/* Throw away the credentials */
pamerr = pam_setcred (pamh, PAM_DELETE_CRED);
pamerr = pam_setcred (tmp_pamh, PAM_DELETE_CRED);
if (pamh != NULL)
pam_end (pamh, pamerr);
pamh = NULL;
pam_end (tmp_pamh, pamerr);
/* Workaround to avoid gdm messages being logged as PAM_pwdb */
closelog ();
......
......@@ -574,7 +574,9 @@
if you need to (though you should use the
<filename>pam_mount</filename> module if you can for this).
You have the $USER and $DISPLAY environment variables set for this script,
and again it is run as root.
and again it is run as root. The script should return 0 on success
as otherwise the user won't be logged in. This is not true for
failsafe session showever.
</para>
<para>
......@@ -585,9 +587,9 @@
script for local session management or accounting stuff. The
$USER environment variable contains the login of the
authenticated user and $DISPLAY is set to the current display.
The script should return 0 on success. Any
The script should return 0 on success. Any
other value will cause GDM to terminate the current login
process.
process. This is not true for failsafe sessions however.
Also $X_SERVERS environmental variable is set and this points
to a fake generated x servers file for use with the
sessreg accounting program.
......@@ -1014,7 +1016,7 @@
<synopsis>RootPath=/sbin:/usr/sbin:/bin:/usr/bin:/usr/bin/X11:/usr/local/bin</synopsis>
<para>
Specifies the path which will be set in the root's
session and the {Init,PreSession,PostSession} scripts
session and the {Init,PostLogin,PreSession,PostSession} scripts
executed by GDM.
</para>
</listitem>
......@@ -1027,11 +1029,20 @@
<para>
Directory containing the X authentication files for the
individual displays. Should be owned by
<filename>gdm.gdm</filename> with permissions 750.
<filename>root.gdm</filename> with permissions 1770.
That is should be owned by root, with gdm group having
full write permissions and the directory should be
sticky and others should have no permission to the directory.
This way the gdm user can't remove files owned
by root in that directory, while still being able to
write its own files there. GDM will attempt to change
permissions for you when it's first run if the permissions
are not the above.
This directory is also used for other private files that
the daemon needs to store. Other user should not
the daemon needs to store. Other users should not
have any way to get into this directory and read/change
it's contents.
it's contents. Anybody who can read this directory can
connect to any display on this machine.
</para>
</listitem>
</varlistentry>
......
......@@ -134,7 +134,8 @@ exit 0
# %{_datadir}/pixmaps/*
# %{_datadir}/gnome/help/gdm/*
# %{_datadir}/gnome/help/gdmsetup/*
%attr(750, gdm, gdm) %dir %{localstatedir}/gdm
%attr(1770, root, gdm) %dir %{localstatedir}/gdm
%attr(755, root, root) %dir %{localstatedir}/log/gdm
%changelog
......
......@@ -83,6 +83,7 @@ static gint connection_type = 0;
static void gdm_chooser_abort (const gchar *format, ...) G_GNUC_PRINTF (1, 2);
static void gdm_chooser_warn (const gchar *format, ...) G_GNUC_PRINTF (1, 2);
static void set_background (void);
/* Exported for glade */
void gdm_chooser_cancel (void);
......@@ -112,6 +113,10 @@ static guint scan_time_handler = 0;
static int ping_tries = PING_TRIES;
static guint ping_try_handler = 0;
/* set in the main function */
static char **stored_argv = NULL;
static int stored_argc = 0;
/* Fixetyfix */
int XdmcpReallocARRAY8 (ARRAY8Ptr array, int length);
......@@ -142,6 +147,7 @@ static gchar *GdmHostIconDir;
static gchar *GdmHostDefaultIcon;
static gchar *GdmGtkRC;
static gchar *GdmHosts;
static gchar *GdmHostsOrig;
static gboolean GdmBroadcast;
static gboolean GdmAllowAdd;
static gchar *GdmBackgroundColor;
......@@ -1055,6 +1061,7 @@ gdm_chooser_parse_config (void)
/* note that command line arguments will prevail over these */
GdmHosts = ve_config_get_string (cfg, GDM_KEY_HOSTS);
GdmHostsOrig = g_strdup (GdmHosts);
GdmBroadcast = ve_config_get_bool (cfg, GDM_KEY_BROADCAST);
/* if broadcasting, then append BROADCAST to hosts */
if (GdmBroadcast) {
......@@ -1250,24 +1257,111 @@ gdm_chooser_gui_init (void)
}
}
static gboolean
string_same (VeConfig *config, const char *cur, const char *key)
{
char *val = ve_config_get_string (config, key);
if (strcmp (ve_sure_string (cur), ve_sure_string (val)) == 0) {
g_free (val);
return TRUE;
} else {
g_free (val);
return FALSE;