Commit 4a386a31 authored by Jiri (George) Lebl's avatar Jiri (George) Lebl Committed by George Lebl

Add some semi randomness spinners which are spun on somewhat random

Fri Aug 15 12:14:58 2003  George Lebl <jirka@5z.com>

	* daemon/cookie.[ch], daemon/slave.c, daemon/xdmcp.c, daemon/gdm.c:
	  Add some semi randomness spinners which are spun on somewhat random
	  occasions.  This should add to our entropy a bit especially on
	  systems without /dev/random (20 bytes of semi randomness is added
	  this way).  And try /dev/srandom on openbsd.

	* daemon/cookie.c: don't read the buffer max from /dev/random, but
	  only the required size, the (there's no need to md5 512 bytes of
	  truly random data just to get 16 bytes).  Require 32 bytes from
	  /dev/random (this is what openssl does apparently), also from
	  openssl, /dev/random still sometimes blocks, so set up a select
	  loop for it that waits 10ms at most.  Also try /dev/mem as one of
	  the files in case we can't get enough entropy from /dev/random.

	* daemon/slave.c: some G_UNLIKELY/G_LIKELY code from yesterday
	  that was still uncommitted

	* daemon/auth.c: set egid as well as euid when testing for root
	  squashing

	* gui/gdmXnestchooser.c: add some IGNORE_EINTR

	* gui/gdmchooser.c: make sure the ARRAY8's are initialized
	  to zero so that we don't possibly crash on bad return packet.
parent 32c21017
Fri Aug 15 12:14:58 2003 George Lebl <jirka@5z.com>
* daemon/cookie.[ch], daemon/slave.c, daemon/xdmcp.c, daemon/gdm.c:
Add some semi randomness spinners which are spun on somewhat random
occasions. This should add to our entropy a bit especially on
systems without /dev/random (20 bytes of semi randomness is added
this way). And try /dev/srandom on openbsd.
* daemon/cookie.c: don't read the buffer max from /dev/random, but
only the required size, the (there's no need to md5 512 bytes of
truly random data just to get 16 bytes). Require 32 bytes from
/dev/random (this is what openssl does apparently), also from
openssl, /dev/random still sometimes blocks, so set up a select
loop for it that waits 10ms at most. Also try /dev/mem as one of
the files in case we can't get enough entropy from /dev/random.
* daemon/slave.c: some G_UNLIKELY/G_LIKELY code from yesterday
that was still uncommitted
* daemon/auth.c: set egid as well as euid when testing for root
squashing
* gui/gdmXnestchooser.c: add some IGNORE_EINTR
* gui/gdmchooser.c: make sure the ARRAY8's are initialized
to zero so that we don't possibly crash on bad return packet.
Fri Aug 15 Brian Cameron <Brian.Cameron@Sun.COM>
* daemon/misc.h: Provide a #define for __PRETTY_FUNCTION__
......
......@@ -395,15 +395,19 @@ try_open_read_as_root (const char *file)
{
int fd;
uid_t oldeuid = geteuid ();
uid_t oldegid = getegid ();
setegid (0);
seteuid (0);
fd = open (file, O_RDONLY);
if G_UNLIKELY (fd < 0) {
seteuid (oldeuid);
setegid (oldegid);
return FALSE;
} else {
close (fd);
seteuid (oldeuid);
setegid (oldegid);
return TRUE;
}
}
......
/* 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>
*
......@@ -43,16 +44,43 @@
struct rngs {
const char *path;
int length;
off_t seek;
} rngs[] = {
{ "/dev/random", 16 },
{ "/dev/urandom", 128 },
{ "/proc/stat", MAXBUFFERSIZE },
{ "/proc/loadavg", MAXBUFFERSIZE },
{ "/dev/audio", MAXBUFFERSIZE },
{ "/dev/random", 32, 0 },
#ifdef __OpenBSD__
{ "/dev/srandom", 32, 0 },
#endif
{ "/dev/urandom", 128, 0 },
{ "/proc/stat", MAXBUFFERSIZE, 0 },
{ "/proc/loadavg", MAXBUFFERSIZE, 0 },
{ "/dev/mem", MAXBUFFERSIZE, 0x100000 },
{ "/dev/audio", MAXBUFFERSIZE, 0 },
};
#define RNGS (sizeof(rngs)/sizeof(struct rngs))
/* Some semi random spinners to spin,
* this is 20 bytes of semi random data */
#define RANDNUMS 5
static int randnums[RANDNUMS];
/* 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)
{
int i;
struct timeval tv;
struct timezone tz;
gettimeofday (&tv, &tz);
srand (tv.tv_usec + tv.tv_sec);
for (i = 0; i < RANDNUMS; i++)
randnums[i] += rand ();
}
void
gdm_cookie_generate (GdmDisplay *d)
......@@ -64,24 +92,50 @@ gdm_cookie_generate (GdmDisplay *d)
int fd;
pid_t pid;
int r;
struct timeval tv;
struct timezone tz;
char cookie[40 /* 2*16 == 32, so 40 is enough */];
cookie[0] = '\0';
gdm_md5_init (&ctx);
gettimeofday (&tv, &tz);
gdm_md5_update (&ctx, (unsigned char *) &tv, sizeof (tv));
/* spin the spinners according to current time */
gdm_random_tick ();
gdm_md5_update (&ctx, (unsigned char *) randnums, sizeof (int) * RANDNUMS);
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 < RNGS; i++) {
if ((fd = open (rngs[i].path, O_RDONLY|O_NONBLOCK)) >= 0) {
IGNORE_EINTR (r = read (fd, buf, sizeof (buf)));
fd = open (rngs[i].path, O_RDONLY|O_NONBLOCK
#ifdef O_NOCTTY
|O_NOCTTY
#endif
#ifdef O_NOFOLLOW
|O_NOFOLLOW
#endif
);
if (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 (rngs[i].seek > 0)
lseek (fd, rngs[i].seek, SEEK_SET);
if (select (fd+1, &rfds, NULL, NULL, &tv) > 0) {
IGNORE_EINTR (r = read (fd, buf, MIN (sizeof (buf), rngs[i].length)));
}
if (r > 0)
gdm_md5_update (&ctx, buf, r);
......
......@@ -22,6 +22,9 @@
#include "gdm.h"
void gdm_cookie_generate (GdmDisplay *);
/* Add some more time based randomness, should be done
* at less predictable events */
void gdm_random_tick (void);
#endif /* GDM_COOKIE_H */
......
......@@ -56,6 +56,7 @@
#include "choose.h"
#include "getvt.h"
#include "gdm-net.h"
#include "cookie.h"
/* Local functions */
static void gdm_config_parse (void);
......@@ -1560,6 +1561,9 @@ main_daemon_abrt (int sig)
static gboolean
mainloop_sig_callback (int sig, gpointer data)
{
/* signals are at somewhat random times aren't they? */
gdm_random_tick ();
gdm_debug ("mainloop_sig_callback: Got signal %d", (int)sig);
switch (sig)
{
......@@ -1778,6 +1782,8 @@ main (int argc, char *argv[])
int nextopt;
const char *charset;
gdm_random_tick ();
gdm_main_pid = getpid ();
/* We here ensure descriptors 0, 1 and 2 */
......
......@@ -1546,7 +1546,14 @@ gdm_safe_fopen_w (const char *file)
{
int fd;
IGNORE_EINTR (unlink (file));
fd = open (file, O_EXCL|O_CREAT|O_TRUNC|O_WRONLY, 0644);
fd = open (file, O_EXCL|O_CREAT|O_TRUNC|O_WRONLY
#ifdef O_NOCTTY
|O_NOCTTY
#endif
#ifdef O_NOFOLLOW
|O_NOFOLLOW
#endif
, 0644);
if (fd < 0)
return NULL;
return fdopen (fd, "w");
......@@ -1559,14 +1566,24 @@ gdm_safe_fopen_ap (const char *file)
int fd;
if (access (file, F_OK) == 0) {
fd = open (file, O_APPEND|O_RDWR
#ifdef O_NOCTTY
|O_NOCTTY
#endif
#ifdef O_NOFOLLOW
fd = open (file, O_APPEND|O_RDWR|O_NOFOLLOW);
#else
fd = open (file, O_APPEND|O_RDWR);
|O_NOFOLLOW
#endif
);
} else {
/* doesn't exist, open with O_EXCL */
fd = open (file, O_EXCL|O_CREAT|O_RDWR, 0644);
fd = open (file, O_EXCL|O_CREAT|O_RDWR
#ifdef O_NOCTTY
|O_NOCTTY
#endif
#ifdef O_NOFOLLOW
|O_NOFOLLOW
#endif
, 0644);
}
if (fd < 0)
return NULL;
......
......@@ -515,7 +515,7 @@ gdm_slave_start (GdmDisplay *display)
sigprocmask (SIG_UNBLOCK, &mask, NULL);
if (display == NULL) {
if G_UNLIKELY (display == NULL) {
/* saaay ... what? */
_exit (DISPLAY_REMANAGE);
}
......@@ -545,7 +545,7 @@ gdm_slave_start (GdmDisplay *display)
sigemptyset (&alrm.sa_mask);
sigaddset (&alrm.sa_mask, SIGALRM);
if (sigaction (SIGALRM, &alrm, NULL) < 0)
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));
......@@ -558,8 +558,8 @@ gdm_slave_start (GdmDisplay *display)
sigaddset (&term.sa_mask, SIGTERM);
sigaddset (&term.sa_mask, SIGINT);
if ((sigaction (SIGTERM, &term, NULL) < 0) ||
(sigaction (SIGINT, &term, NULL) < 0))
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));
......@@ -570,7 +570,7 @@ gdm_slave_start (GdmDisplay *display)
sigemptyset (&child.sa_mask);
sigaddset (&child.sa_mask, SIGCHLD);
if (sigaction (SIGCHLD, &child, NULL) < 0)
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));
......@@ -580,7 +580,7 @@ gdm_slave_start (GdmDisplay *display)
sigemptyset (&usr2.sa_mask);
sigaddset (&usr2.sa_mask, SIGUSR2);
if (sigaction (SIGUSR2, &usr2, NULL) < 0)
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));
......@@ -611,7 +611,7 @@ gdm_slave_start (GdmDisplay *display)
(the_time - first_time) > 60) {
first_time = the_time;
death_count = 0;
} else if (death_count > 6) {
} else if G_UNLIKELY (death_count > 6) {
gdm_slave_quick_exit (DISPLAY_ABORT);
}
......@@ -625,12 +625,12 @@ gdm_slave_start (GdmDisplay *display)
} else {
/* OK about to start again so rebake our cookies and reinit
* the server */
if ( ! gdm_auth_secure_display (d)) {
if G_UNLIKELY ( ! gdm_auth_secure_display (d)) {
gdm_slave_quick_exit (DISPLAY_REMANAGE);
}
gdm_slave_send_string (GDM_SOP_COOKIE, d->cookie);
if ( ! gdm_server_reinit (d)) {
if G_UNLIKELY ( ! gdm_server_reinit (d)) {
gdm_error ("Error reinitilizing server");
gdm_slave_quick_exit (DISPLAY_REMANAGE);
}
......@@ -825,7 +825,7 @@ gdm_slave_check_user_wants_to_log_in (const char *user)
return TRUE;
gdm_slave_send_string (GDM_SOP_QUERYLOGIN, user);
if (gdm_ack_response == NULL)
if G_LIKELY (ve_string_empty (gdm_ack_response))
return TRUE;
vec = g_strsplit (gdm_ack_response, ",", -1);
if (vec == NULL)
......@@ -840,7 +840,7 @@ gdm_slave_check_user_wants_to_log_in (const char *user)
g_strfreev (vec);
if G_LIKELY ( ! loggedin)
if ( ! loggedin)
return TRUE;
but[0] = _("Log in anyway");
......@@ -916,6 +916,8 @@ gdm_slave_run (GdmDisplay *display)
d = display;
gdm_random_tick ();
if G_UNLIKELY (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);
......@@ -1357,14 +1359,14 @@ run_config (GdmDisplay *display, struct passwd *pwent)
openlog ("gdm", LOG_PID, LOG_DAEMON);
IGNORE_EINTR (chdir (pwent->pw_dir));
if (errno != 0)
if G_UNLIKELY (errno != 0)
IGNORE_EINTR (chdir ("/"));
/* exec the configurator */
argv = ve_split (GdmConfigurator);
if (argv != NULL &&
argv[0] != NULL &&
access (argv[0], X_OK) == 0)
if G_LIKELY (argv != NULL &&
argv[0] != NULL &&
access (argv[0], X_OK) == 0)
IGNORE_EINTR (execv (argv[0], argv));
gdm_error_box (d,
......@@ -1461,7 +1463,7 @@ gdm_slave_wait_for_login (void)
do_timed_login = FALSE;
do_configurator = FALSE;
if (do_restart_greeter) {
if G_UNLIKELY (do_restart_greeter) {
do_restart_greeter = FALSE;
restart_the_greeter ();
}
......@@ -1487,7 +1489,7 @@ gdm_slave_wait_for_login (void)
* do_timed_login and do_restart_greeter after any call
* to gdm_verify_user */
if (do_restart_greeter) {
if G_UNLIKELY (do_restart_greeter) {
do_restart_greeter = FALSE;
restart_the_greeter ();
continue;
......@@ -1495,7 +1497,7 @@ gdm_slave_wait_for_login (void)
check_notifies_now ();
if (do_configurator) {
if G_UNLIKELY (do_configurator) {
struct passwd *pwent;
gboolean oldAllowRoot;
......@@ -1527,7 +1529,7 @@ gdm_slave_wait_for_login (void)
d->console);
GdmAllowRoot = oldAllowRoot;
if (do_restart_greeter) {
if G_UNLIKELY (do_restart_greeter) {
do_restart_greeter = FALSE;
restart_the_greeter ();
continue;
......@@ -1555,7 +1557,7 @@ gdm_slave_wait_for_login (void)
}
/* the user is a wanker */
if (do_configurator) {
if G_UNLIKELY (do_configurator) {
do_configurator = FALSE;
gdm_slave_greeter_ctl_no_ret (GDM_RESET, "");
continue;
......@@ -1840,7 +1842,7 @@ run_pictures (void)
fp = fopen (picfile, "r");
g_free (picfile);
if (fp == NULL) {
if G_UNLIKELY (fp == NULL) {
seteuid (0);
setegid (GdmGroupId);
......@@ -1852,7 +1854,7 @@ run_pictures (void)
ret = gdm_slave_greeter_ctl (GDM_READPIC, tmp);
g_free (tmp);
if (ret == NULL || strcmp (ret, "OK") != 0) {
if G_UNLIKELY (ret == NULL || strcmp (ret, "OK") != 0) {
fclose (fp);
g_free (ret);
seteuid (0);
......@@ -1882,7 +1884,7 @@ run_pictures (void)
/* write until we succeed in writing something */
IGNORE_EINTR (written = write (greeter_fd_out, buf, bytes));
if (written < 0 && errno == EPIPE) {
if G_UNLIKELY (written < 0 && errno == EPIPE) {
/* something very, very bad has happened */
gdm_slave_quick_exit (DISPLAY_REMANAGE);
}
......@@ -1906,11 +1908,11 @@ run_pictures (void)
fclose (fp);
/* eek, this "could" happen, so just send some garbage */
while (i < s.st_size) {
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 (bytes < 0 && errno == EPIPE) {
if G_UNLIKELY (bytes < 0 && errno == EPIPE) {
/* something very, very bad has happened */
gdm_slave_quick_exit (DISPLAY_REMANAGE);
}
......@@ -2055,17 +2057,17 @@ gdm_slave_greeter (void)
openlog ("gdm", LOG_PID, LOG_DAEMON);
if (setgid (GdmGroupId) < 0)
if G_UNLIKELY (setgid (GdmGroupId) < 0)
gdm_child_exit (DISPLAY_ABORT,
_("%s: Couldn't set groupid to %d"),
"gdm_slave_greeter", GdmGroupId);
if (initgroups (GdmUser, GdmGroupId) < 0)
if G_UNLIKELY (initgroups (GdmUser, GdmGroupId) < 0)
gdm_child_exit (DISPLAY_ABORT,
_("%s: initgroups() failed for %s"),
"gdm_slave_greeter", GdmUser);
if (setuid (GdmUserId) < 0)
if G_UNLIKELY (setuid (GdmUserId) < 0)
gdm_child_exit (DISPLAY_ABORT,
_("%s: Couldn't set userid to %d"),
"gdm_slave_greeter", GdmUserId);
......@@ -3997,6 +3999,9 @@ gdm_slave_greeter_ctl (char cmd, const char *str)
}
} 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 {
......
......@@ -96,6 +96,7 @@
#include "misc.h"
#include "choose.h"
#include "xdmcp.h"
#include "cookie.h"
int gdm_xdmcpfd = -1;
......@@ -359,6 +360,9 @@ gdm_xdmcp_decode_packet (GIOChannel *source, GIOCondition cond, gpointer data)
"MANAGED_FORWARD", "GOT_MANAGED_FORWARD"
};
/* packets come at somewhat random times */
gdm_random_tick ();
if (cond != G_IO_IN)
gdm_debug ("gdm_xdmcp_decode_packet: GIOCondition %d", (int)cond);
......
......@@ -73,11 +73,11 @@ get_free_display (void)
if (connect (sock, (struct sockaddr *)&serv_addr,
sizeof (serv_addr)) >= 0 ||
errno != ECONNREFUSED) {
close (sock);
IGNORE_EINTR (close (sock));
continue;
}
close (sock);
IGNORE_EINTR (close (sock));
/* if lock file exists and the process exists */
g_snprintf (buf, sizeof (buf), "/tmp/.X%d-lock", i);
......@@ -602,9 +602,9 @@ main (int argc, char *argv[])
if (fork () > 0) {
_exit (0);
}
close (0);
close (1);
close (2);
IGNORE_EINTR (close (0));
IGNORE_EINTR (close (1));
IGNORE_EINTR (close (2));
open ("/dev/null", O_RDWR);
open ("/dev/null", O_RDONLY);
open ("/dev/null", O_RDONLY);
......
......@@ -380,7 +380,7 @@ gdm_chooser_decode_packet (GIOChannel *source,
struct hostent *he;
gchar *hostname = NULL;
gchar *status = NULL;
ARRAY8 auth, host, stat;
ARRAY8 auth = {0}, host = {0}, stat = {0};
GdmChooserHost *gh;
int pipe_buf;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment