summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-04-03 14:50:43 +1000
committerDamien Miller <djm@mindrot.org>2000-04-03 14:50:43 +1000
commit040f3831fcc4c2e338ab15cb55cb43d95deb390e (patch)
tree2e459b4d6e4aa4fe64bf59ae2cc4126533aa3385
parentb38eff8e4ff901df9cf1113a9f14d64c3565a401 (diff)
- Wrote entropy collection routines for systems that lack /dev/random
and EGD
-rw-r--r--ChangeLog4
-rw-r--r--Makefile.in2
-rw-r--r--README9
-rw-r--r--acconfig.h30
-rw-r--r--bsd-misc.c68
-rw-r--r--bsd-misc.h61
-rw-r--r--configure.in51
-rw-r--r--entropy.c436
-rw-r--r--entropy.h35
-rw-r--r--random.c124
-rw-r--r--random.h41
-rw-r--r--rsa.c19
12 files changed, 597 insertions, 283 deletions
diff --git a/ChangeLog b/ChangeLog
index 585686e2..978c4082 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+20000403
+ - Wrote entropy collection routines for systems that lack /dev/random
+ and EGD
+
20000401
- Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure)
- [auth.c session.c sshd.c auth.h]
diff --git a/Makefile.in b/Makefile.in
index 43870d5f..89b40848 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -31,7 +31,7 @@ LDFLAGS=-L. @LDFLAGS@
TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
-LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o key.o log.o match.o mpaux.o nchan.o packet.o radix.o random.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
+LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o key.o log.o match.o mpaux.o nchan.o packet.o radix.o entropy.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
SSHOBJS= ssh.o sshconnect.o log-client.o readconf.o clientloop.o
diff --git a/README b/README
index ecd82c4d..450d81c5 100644
--- a/README
+++ b/README
@@ -32,11 +32,6 @@ The PAM support is now more functional than the popular packages of
commercial ssh-1.2.x. It checks "account" and "session" modules for
all logins, not just when using password authentication.
-All new code is released under a XFree style license, which is very
-liberal. Please refer to the source files for details. The code in
-bsd-*.[ch] is from the OpenBSD project and has its own license (again,
-see the source files for details).
-
OpenSSH depends on Zlib[2], OpenSSL[3] and optionally PAM[4] and
Dante[6]. To build the GNOME[5] pass-phrase requester
(--with-gnome-askpass), you will need the GNOME libraries installed.
@@ -64,10 +59,6 @@ This version of SSH is based upon code retrieved from the OpenBSD CVS
repository which in turn was based on the last free
version of SSH released by Tatu Ylonen.
-Code in bsd-misc.[ch] and gnome-ssh-askpass.c is Copyright 1999 Damien
-Miller & Internet Business Solutions and is released under a X11-style
-license (see source files for details).
-
References -
[1] http://www.lothar.com/tech/crypto/
diff --git a/acconfig.h b/acconfig.h
index 32764f09..cbb3a97c 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -24,17 +24,8 @@
/* Location of random number pool */
#undef RANDOM_POOL
-/* Are we using the Entropy gathering daemon */
-#undef HAVE_EGD
-
-/* Define if using the Dante SOCKS library. */
-#undef HAVE_DANTE
-
-/* Define if using the Socks4 SOCKS library. */
-#undef HAVE_SOCKS4
-
-/* Define if using the Socks5 SOCKS library. */
-#undef HAVE_SOCKS5
+/* Location of EGD random number socket */
+#undef EGD_SOCKET
/* Define if you want to install preformatted manpages.*/
#undef MANTYPE
@@ -159,6 +150,23 @@
/* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
#undef IPV4_IN_IPV6
+/* Programs used in entropy collection */
+#undef PROG_LS
+#undef PROG_NETSTAT
+#undef PROG_ARP
+#undef PROG_IFCONFIG
+#undef PROG_PS
+#undef PROG_W
+#undef PROG_WHO
+#undef PROG_LAST
+#undef PROG_LASTLOG
+#undef PROG_DF
+#undef PROG_VMSTAT
+#undef PROG_UPTIME
+#undef PROG_IPCS
+#undef PROG_TAIL
+
+
@BOTTOM@
/* ******************* Shouldn't need to edit below this line ************** */
diff --git a/bsd-misc.c b/bsd-misc.c
index dd1f6a47..3186c86d 100644
--- a/bsd-misc.c
+++ b/bsd-misc.c
@@ -1,38 +1,31 @@
/*
-**
-** OpenBSD replacement routines
-**
-** Damien Miller <djm@ibs.com.au>
-**
-** Copyright 1999 Damien Miller
-** Copyright 1999 Internet Business Solutions
-**
-** Permission is hereby granted, free of charge, to any person
-** obtaining a copy of this software and associated documentation
-** files (the "Software"), to deal in the Software without
-** restriction, including without limitation the rights to use, copy,
-** modify, merge, publish, distribute, sublicense, and/or sell copies
-** of the Software, and to permit persons to whom the Software is
-** furnished to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be
-** included in all copies or substantial portions of the Software.
-**
-** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
-** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET
-** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-** OR OTHER DEALINGS IN THE SOFTWARE.
-**
-** Except as contained in this notice, the name of Internet Business
-** Solutions shall not be used in advertising or otherwise to promote
-** the sale, use or other dealings in this Software without prior
-** written authorization from Internet Business Solutions.
-**
-*/
+ * Copyright (c) 1999-2000 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Markus Friedl.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#include "config.h"
@@ -52,7 +45,7 @@
#include "xmalloc.h"
#include "ssh.h"
#include "bsd-misc.h"
-#include "random.h"
+#include "entropy.h"
#ifndef HAVE_ARC4RANDOM
@@ -125,8 +118,11 @@ void arc4random_stir(void)
if (rc4 == NULL)
rc4 = xmalloc(sizeof(*rc4));
+
+ seed_rng();
+ RAND_bytes(rand_buf, sizeof(rand_buf));
+ seed_rng();
- get_random_bytes(rand_buf, sizeof(rand_buf));
rc4_key(rc4, rand_buf, sizeof(rand_buf));
memset(rand_buf, 0, sizeof(rand_buf));
}
diff --git a/bsd-misc.h b/bsd-misc.h
index 9d499c80..cdf8e2b6 100644
--- a/bsd-misc.h
+++ b/bsd-misc.h
@@ -1,38 +1,31 @@
/*
-**
-** OpenBSD replacement routines
-**
-** Damien Miller <djm@ibs.com.au>
-**
-** Copyright 1999 Damien Miller
-** Copyright 1999 Internet Business Solutions
-**
-** Permission is hereby granted, free of charge, to any person
-** obtaining a copy of this software and associated documentation
-** files (the "Software"), to deal in the Software without
-** restriction, including without limitation the rights to use, copy,
-** modify, merge, publish, distribute, sublicense, and/or sell copies
-** of the Software, and to permit persons to whom the Software is
-** furnished to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be
-** included in all copies or substantial portions of the Software.
-**
-** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
-** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET
-** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-** OR OTHER DEALINGS IN THE SOFTWARE.
-**
-** Except as contained in this notice, the name of Internet Business
-** Solutions shall not be used in advertising or otherwise to promote
-** the sale, use or other dealings in this Software without prior
-** written authorization from Internet Business Solutions.
-**
-*/
+ * Copyright (c) 1999-2000 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Markus Friedl.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
#ifndef _BSD_MISC_H
#define _BSD_MISC_H
diff --git a/configure.in b/configure.in
index 2d2fbe1a..6c9ea312 100644
--- a/configure.in
+++ b/configure.in
@@ -12,6 +12,36 @@ AC_CHECK_PROG(AR, ar, ar)
AC_PATH_PROG(PERL, perl)
AC_SUBST(PERL)
+# We may need these for entropy collection
+AC_PATH_PROG(PROG_LS, ls)
+AC_DEFINE_UNQUOTED(PROG_LS, "$PROG_LS")
+AC_PATH_PROG(PROG_NETSTAT, netstat)
+AC_DEFINE_UNQUOTED(PROG_NETSTAT, "$PROG_NETSTAT")
+AC_PATH_PROG(PROG_ARP, arp)
+AC_DEFINE_UNQUOTED(PROG_ARP, "$PROG_ARP")
+AC_PATH_PROG(PROG_IFCONFIG, ifconfig)
+AC_DEFINE_UNQUOTED(PROG_IFCONFIG, "$PROG_IFCONFIG")
+AC_PATH_PROG(PROG_PS, ps)
+AC_DEFINE_UNQUOTED(PROG_PS, "$PROG_PS")
+AC_PATH_PROG(PROG_W, w)
+AC_DEFINE_UNQUOTED(PROG_W, "$PROG_W")
+AC_PATH_PROG(PROG_WHO, who)
+AC_DEFINE_UNQUOTED(PROG_WHO, "$PROG_WHO")
+AC_PATH_PROG(PROG_LAST, last)
+AC_DEFINE_UNQUOTED(PROG_LAST, "$PROG_LAST")
+AC_PATH_PROG(PROG_LASTLOG, lastlog)
+AC_DEFINE_UNQUOTED(PROG_LASTLOG, "$PROG_LASTLOG")
+AC_PATH_PROG(PROG_DF, df)
+AC_DEFINE_UNQUOTED(PROG_DF, "$PROG_DF")
+AC_PATH_PROG(PROG_VMSTAT, vmstat)
+AC_DEFINE_UNQUOTED(PROG_VMSTAT, "$PROG_VMSTAT")
+AC_PATH_PROG(PROG_UPTIME, uptime)
+AC_DEFINE_UNQUOTED(PROG_UPTIME, "$PROG_UPTIME")
+AC_PATH_PROG(PROG_IPCS, ipcs)
+AC_DEFINE_UNQUOTED(PROG_UPTIME, "$PROG_UPTIME")
+AC_PATH_PROG(PROG_TAIL, tail)
+AC_DEFINE_UNQUOTED(PROG_TAIL, "$PROG_TAIL")
+
if test -z "$LD" ; then
LD=$CC
fi
@@ -110,7 +140,7 @@ fi
AC_CHECK_HEADERS(bstring.h endian.h lastlog.h login.h maillock.h netdb.h netgroup.h paths.h poll.h pty.h shadow.h security/pam_appl.h sys/bitypes.h sys/bsdtty.h sys/cdefs.h sys/poll.h sys/select.h sys/stropts.h sys/sysmacros.h sys/time.h sys/ttcompat.h stddef.h util.h utmp.h utmpx.h)
# Checks for library functions.
-AC_CHECK_FUNCS(arc4random bindresvport_af freeaddrinfo gai_strerror getaddrinfo getnameinfo innetgr md5_crypt mkdtemp openpty rresvport_af setenv seteuid setlogin setproctitle setreuid snprintf strlcat strlcpy updwtmpx vsnprintf _getpty)
+AC_CHECK_FUNCS(arc4random bindresvport_af clock freeaddrinfo gai_strerror getaddrinfo getnameinfo getrusage innetgr md5_crypt mkdtemp openpty rresvport_af setenv seteuid setlogin setproctitle setreuid snprintf strlcat strlcpy updwtmpx vsnprintf _getpty)
AC_CHECK_FUNC(login,
[AC_DEFINE(HAVE_LOGIN)],
@@ -604,8 +634,10 @@ AC_CHECK_FILE("/dev/ptc",
AC_ARG_WITH(random,
[ --with-random=FILE read randomness from FILE (default=/dev/urandom)],
[
- RANDOM_POOL="$withval";
- AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL")
+ if test "x$withval" != "xno" ; then
+ RANDOM_POOL="$withval";
+ AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL")
+ fi
],
[
# Check for random device
@@ -623,18 +655,13 @@ AC_ARG_WITH(random,
AC_ARG_WITH(egd-pool,
[ --with-egd-pool=FILE read randomness from EGD pool FILE (default none)],
[
- RANDOM_POOL="$withval";
- AC_DEFINE(HAVE_EGD)
- AC_SUBST(RANDOM_POOL)
- AC_DEFINE_UNQUOTED(RANDOM_POOL, "$RANDOM_POOL")
+ if test "x$withval" != "xno" ; then
+ EGD_SOCKET="$withval";
+ AC_DEFINE_UNQUOTED(EGD_SOCKET, "$EGD_SOCKET")
+ fi
]
)
-# Make sure we have some random number support
-if test -z "$RANDOM_POOL" -a -z "$EGD_POOL"; then
- AC_MSG_ERROR([No random device found, and no EGD random pool specified])
-fi
-
AC_ARG_WITH(catman,
[ --with-catman=man|cat Install preformatted manpages[no]],
[
diff --git a/entropy.c b/entropy.c
new file mode 100644
index 00000000..16731775
--- /dev/null
+++ b/entropy.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2000 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Markus Friedl.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+
+#include "ssh.h"
+#include "xmalloc.h"
+
+#ifdef HAVE_OPENSSL
+# include <openssl/rand.h>
+# include <openssl/sha.h>
+#endif
+#ifdef HAVE_SSL
+# include <ssl/rand.h>
+# include <ssl/sha.h>
+#endif
+
+RCSID("$Id: entropy.c,v 1.1 2000/04/03 04:50:45 damien Exp $");
+
+#ifdef EGD_SOCKET
+#ifndef offsetof
+# define offsetof(type, member) ((size_t) &((type *)0)->member)
+#endif
+/* Collect entropy from EGD */
+void get_random_bytes(unsigned char *buf, int len)
+{
+ static int egd_socket = -1;
+ int c;
+ char egd_message[2] = { 0x02, 0x00 };
+ struct sockaddr_un addr;
+ int addr_len;
+
+ memset(&addr, '\0', sizeof(addr));
+ addr.sun_family = AF_UNIX;
+
+ /* FIXME: compile time check? */
+ if (sizeof(EGD_SOCKET) > sizeof(addr.sun_path))
+ fatal("Random pool path is too long");
+
+ strcpy(addr.sun_path, EGD_SOCKET);
+
+ addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(EGD_SOCKET);
+
+ if (egd_socket == -1) {
+ egd_socket = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (egd_socket == -1)
+ fatal("Couldn't create AF_UNIX socket: %s", strerror(errno));
+ if (connect(egd_socket, (struct sockaddr*)&addr, addr_len) == -1)
+ fatal("Couldn't connect to EGD socket \"%s\": %s", addr.sun_path, strerror(errno));
+ }
+
+ if (len > 255)
+ fatal("Too many bytes to read from EGD");
+
+ /* Send blocking read request to EGD */
+ egd_message[1] = len;
+
+ c = atomicio(write, egd_socket, egd_message, sizeof(egd_message));
+ if (c == -1)
+ fatal("Couldn't write to EGD socket \"%s\": %s", EGD_SOCKET, strerror(errno));
+
+ c = atomicio(read, egd_socket, buf, len);
+ if (c <= 0)
+ fatal("Couldn't read from EGD socket \"%s\": %s", EGD_SOCKET, strerror(errno));
+
+ close(EGD_SOCKET);
+}
+#else /* !EGD_SOCKET */
+#ifdef RANDOM_POOL
+/* Collect entropy from /dev/urandom or pipe */
+void get_random_bytes(unsigned char *buf, int len)
+{
+ static int random_pool = -1;
+ int c;
+
+ if (random_pool == -1) {
+ random_pool = open(RANDOM_POOL, O_RDONLY);
+ if (random_pool == -1)
+ fatal("Couldn't open random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
+ }
+
+ verbose("randfd: %i", random_pool);
+
+ c = atomicio(read, random_pool, buf, len);
+ if (c <= 0)
+ fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
+}
+#endif /* RANDOM_POOL */
+#endif /* EGD_SOCKET */
+
+#if !defined(EGD_SOCKET) && !defined(RANDOM_POOL)
+/*
+ * FIXME: proper entropy estimations. All current values are guesses
+ * FIXME: Need timeout for slow moving programs
+ * FIXME: More entropy sources
+ */
+
+double stir_from_system(void);
+double stir_from_programs(void);
+double stir_gettimeofday(double entropy_estimate);
+double stir_clock(double entropy_estimate);
+double stir_rusage(int who, double entropy_estimate);
+double hash_output_from_command(const char *path, const char **args, char *hash);
+
+typedef struct
+{
+ /* Proportion of data that is entropy */
+ double rate;
+ /* Path to executable */
+ const char *path;
+ /* argv to pass to executable */
+ const char *args[5];
+} entropy_source_t;
+
+entropy_source_t entropy_sources[] = {
+#ifdef PROG_LS
+ { 0.002, PROG_LS, { "ls", "-alni", "/var/log", NULL } },
+ { 0.002, PROG_LS, { "ls", "-alni", "/var/adm", NULL } },
+ { 0.002, PROG_LS, { "ls", "-alni", "/var/mail", NULL } },
+ { 0.002, PROG_LS, { "ls", "-alni", "/var/spool/mail", NULL } },
+ { 0.002, PROG_LS, { "ls", "-alni", "/proc", NULL } },
+ { 0.002, PROG_LS, { "ls", "-alni", "/tmp", NULL } },
+#endif
+#ifdef PROG_NETSTAT
+ { 0.005, PROG_NETSTAT, { "netstat","-an", NULL, NULL } },
+ { 0.010, PROG_NETSTAT, { "netstat","-in", NULL, NULL } },
+ { 0.002, PROG_NETSTAT, { "netstat","-rn", NULL, NULL } },
+ { 0.002, PROG_NETSTAT, { "netstat","-s", NULL, NULL } },
+#endif
+#ifdef PROG_ARP
+ { 0.002, PROG_ARP, { "arp","-a","-n", NULL } },
+#endif
+#ifdef PROG_IFCONFIG
+ { 0.002, PROG_IFCONFIG, { "ifconfig", "-a", NULL, NULL } },
+#endif
+#ifdef PROG_PS
+ { 0.003, PROG_PS, { "ps", "laxww", NULL, NULL } },
+ { 0.003, PROG_PS, { "ps", "-al", NULL, NULL } },
+ { 0.003, PROG_PS, { "ps", "-efl", NULL, NULL } },
+#endif
+#ifdef PROG_W
+ { 0.005, PROG_W, { "w", NULL, NULL, NULL } },
+#endif
+#ifdef PROG_WHO
+ { 0.001, PROG_WHO, { "who","-i", NULL, NULL } },
+#endif
+#ifdef PROG_LAST
+ { 0.001, PROG_LAST, { "last", NULL, NULL, NULL } },
+#endif
+#ifdef PROG_LASTLOG
+ { 0.001, PROG_LASTLOG, { "lastlog", NULL, NULL, NULL } },
+#endif
+#ifdef PROG_DF
+ { 0.010, PROG_DF, { "df", NULL, NULL, NULL } },
+ { 0.010, PROG_DF, { "df", "-i", NULL, NULL } },
+#endif
+#ifdef PROG_VMSTAT
+ { 0.010, PROG_VMSTAT, { "vmstat", NULL, NULL, NULL } },
+#endif
+#ifdef PROG_UPTIME
+ { 0.001, PROG_UPTIME, { "uptime", NULL, NULL, NULL } },
+#endif
+#ifdef PROG_IPCS
+ { 0.001, PROG_IPCS, { "-a", NULL, NULL, NULL } },
+#endif
+#ifdef PROG_TAIL
+ { 0.001, PROG_TAIL, { "tail", "-200", "/var/log/messages", NULL, NULL } },
+ { 0.001, PROG_TAIL, { "tail", "-200", "/var/log/syslog", NULL, NULL } },
+ { 0.001, PROG_TAIL, { "tail", "-200", "/var/adm/messages", NULL, NULL } },
+ { 0.001, PROG_TAIL, { "tail", "-200", "/var/adm/syslog", NULL, NULL } },
+ { 0.001, PROG_TAIL, { "tail", "-200", "/var/log/maillog", NULL, NULL } },
+ { 0.001, PROG_TAIL, { "tail", "-200", "/var/adm/maillog", NULL, NULL } },
+#endif
+ { 0.000, NULL, { NULL, NULL, NULL, NULL, NULL } },
+};
+
+
+double
+stir_from_system(void)
+{
+ double total_entropy_estimate;
+ long int i;
+
+ total_entropy_estimate = 0;
+
+ i = getpid();
+ RAND_add(&i, sizeof(i), 0.1);
+ total_entropy_estimate += 0.1;
+
+ i = getppid();
+ RAND_add(&i, sizeof(i), 0.1);
+ total_entropy_estimate += 0.1;
+
+ i = getuid();
+ RAND_add(&i, sizeof(i), 0.0);
+ i = getgid();
+ RAND_add(&i, sizeof(i), 0.0);
+
+ total_entropy_estimate += stir_gettimeofday(1.0);
+ total_entropy_estimate += stir_clock(0.2);
+ total_entropy_estimate += stir_rusage(RUSAGE_SELF, 2.0);
+
+ return(total_entropy_estimate);
+}
+
+double
+stir_from_programs(void)
+{
+ int i;
+ int c;
+ double entropy_estimate;
+ double total_entropy_estimate;
+ char hash[SHA_DIGEST_LENGTH];
+
+ /*
+ * Run through list of programs twice to catch differences
+ */
+ total_entropy_estimate = 0;
+ for(i = 0; i < 2; i++) {
+ c = 0;
+ while (entropy_sources[c].path != NULL) {
+ /* Hash output from command */
+ entropy_estimate = hash_output_from_command(entropy_sources[c].path,
+ entropy_sources[c].args, hash);
+
+ /* Scale back entropy estimate according to command's rate */
+ entropy_estimate *= entropy_sources[c].rate;
+
+ /* Upper bound of entropy estimate is SHA_DIGEST_LENGTH */
+ if (entropy_estimate > SHA_DIGEST_LENGTH)
+ entropy_estimate = SHA_DIGEST_LENGTH;
+
+ /* * Scale back estimates for subsequent passes through list */
+ entropy_estimate /= 10.0 * (i + 1.0);
+
+ /* Stir it in */
+ RAND_add(hash, sizeof(hash), entropy_estimate);
+
+/* FIXME: turn this off later */
+#if 1
+ debug("Got %0.2f bytes of entropy from %s", entropy_estimate,
+ entropy_sources[c].path);
+#endif
+
+ total_entropy_estimate += entropy_estimate;
+
+ /* Execution times should be a little unpredictable */
+ total_entropy_estimate += stir_gettimeofday(0.05);
+ total_entropy_estimate += stir_clock(0.05);
+ total_entropy_estimate += stir_rusage(RUSAGE_SELF, 0.1);
+ total_entropy_estimate += stir_rusage(RUSAGE_CHILDREN, 0.1);
+
+ c++;
+ }
+ }
+
+ return(total_entropy_estimate);
+}
+
+double
+stir_gettimeofday(double entropy_estimate)
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) == -1)
+ fatal("Couldn't gettimeofday: %s", strerror(errno));
+
+ RAND_add(&tv, sizeof(tv), entropy_estimate);
+
+ return(entropy_estimate);
+}
+
+double
+stir_clock(double entropy_estimate)
+{
+#ifdef HAVE_CLOCK
+ clock_t c;
+
+ c = clock();
+ RAND_add(&c, sizeof(c), entropy_estimate);
+
+ return(entropy_estimate);
+#else /* _HAVE_CLOCK */
+ return(0);
+#endif /* _HAVE_CLOCK */
+}
+
+double
+stir_rusage(int who, double entropy_estimate)
+{
+#ifdef HAVE_GETRUSAGE
+ struct rusage ru;
+
+ if (getrusage(who, &ru) == -1)
+ fatal("Couldn't getrusage: %s", strerror(errno));
+
+ RAND_add(&ru, sizeof(ru), 0.1);
+
+ return(entropy_estimate);
+#else /* _HAVE_GETRUSAGE */
+ return(0);
+#endif /* _HAVE_GETRUSAGE */
+}
+
+double
+hash_output_from_command(const char *path, const char **args, char *hash)
+{
+ static int devnull = -1;
+ int p[2];
+ pid_t pid;
+ int status;
+ char buf[2048];
+ int bytes_read;
+ int total_bytes_read;
+ SHA_CTX sha;
+
+ if (devnull == -1) {
+ devnull = open("/dev/null", O_RDWR);
+ if (devnull == -1)
+ fatal("Couldn't open /dev/null: %s", strerror(errno));
+ }
+
+ if (pipe(p) == -1)
+ fatal("Couldn't open pipe: %s", strerror(errno));
+
+ switch (pid = fork()) {
+ case -1: /* Error */
+ close(p[0]);
+ close(p[1]);
+ fatal("Couldn't fork: %s", strerror(errno));
+ /* NOTREACHED */
+ case 0: /* Child */
+ close(0);
+ close(1);
+ close(2);
+ dup2(devnull, 0);
+ dup2(p[1], 1);
+ dup2(p[1], 2);
+ close(p[0]);
+ close(p[1]);
+ close(devnull);
+
+ execv(path, (char**)args);
+ debug("(child) Couldn't exec '%s': %s", path, strerror(errno));
+ _exit(-1);
+ default: /* Parent */
+ break;
+ }
+
+ RAND_add(&pid, sizeof(&pid), 0.0);
+
+ close(p[1]);
+
+ /* Hash output from child */
+ SHA1_Init(&sha);
+ total_bytes_read = 0;
+ while ((bytes_read = read(p[0], buf, sizeof(buf))) > 0) {
+ SHA1_Update(&sha, buf, bytes_read);
+ total_bytes_read += bytes_read;
+ RAND_add(&bytes_read, sizeof(&bytes_read), 0.0);
+ }
+ SHA1_Final(hash, &sha);
+
+ close(p[0]);
+
+ if (waitpid(pid, &status, 0) == -1) {
+ error("Couldn't wait for child '%s' completion: %s", path,
+ strerror(errno));
+ return(-1);
+ }
+
+ RAND_add(&status, sizeof(&status), 0.0);
+
+ if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
+ return(0.0);
+ else
+ return(total_bytes_read);
+}
+#endif /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */
+
+#if defined(EGD_SOCKET) || defined(RANDOM_POOL)
+/*
+ * Seed OpenSSL's random number pool from Kernel random number generator
+ * or EGD
+ */
+void
+seed_rng(void)
+{
+ char buf[32];
+
+ debug("Seeding random number generator");
+ get_random_bytes(buf, sizeof(buf));
+ RAND_add(buf, sizeof(buf), sizeof(buf));
+ memset(buf, '\0', sizeof(buf));
+}
+#else /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */
+/*
+ * Conditionally Seed OpenSSL's random number pool syscalls and program output
+ */
+void
+seed_rng(void)
+{
+ if (!RAND_status()) {
+ debug("Seeding random number generator.");
+ debug("%i bytes from system calls", (int)stir_from_system());
+ debug("%i bytes from programs", (int)stir_from_programs());
+ debug("OpenSSL random status is now %i\n", RAND_status());
+ }
+}
+#endif /* defined(EGD_SOCKET) || defined(RANDOM_POOL) */
diff --git a/entropy.h b/entropy.h
new file mode 100644
index 00000000..ec425a0c
--- /dev/null
+++ b/entropy.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 1999-2000 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Markus Friedl.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RANDOMS_H
+#define _RANDOMS_H
+
+void seed_rng(void);
+
+#endif /* _RANDOMS_H */
diff --git a/random.c b/random.c
deleted file mode 100644
index 06c8d2b3..00000000
--- a/random.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-**
-** Random number collection
-**
-** Damien Miller <djm@ibs.com.au>
-**
-** Copyright 1999 Damien Miller
-**
-** Permission is hereby granted, free of charge, to any person
-** obtaining a copy of this software and associated documentation
-** files (the "Software"), to deal in the Software without
-** restriction, including without limitation the rights to use, copy,
-** modify, merge, publish, distribute, sublicense, and/or sell copies
-** of the Software, and to permit persons to whom the Software is
-** furnished to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be
-** included in all copies or substantial portions of the Software.
-**
-** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
-** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET
-** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-** OR OTHER DEALINGS IN THE SOFTWARE.
-**
-** Except as contained in this notice, the name of Internet Business
-** Solutions shall not be used in advertising or otherwise to promote
-** the sale, use or other dealings in this Software without prior
-** written authorization from Internet Business Solutions.
-**
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <fcntl.h>
-#ifdef HAVE_STDDEF_H
-#include <stddef.h>
-#endif
-
-#include "ssh.h"
-#include "xmalloc.h"
-#include "random.h"
-
-#ifndef offsetof
-# define offsetof(type, member) ((size_t) &((type *)0)->member)
-#endif
-
-#ifdef HAVE_EGD
-
-/* Collect entropy from EGD */
-void get_random_bytes(unsigned char *buf, int len)
-{
- static int random_pool;
- int c;
- char egd_message[2] = { 0x02, 0x00 };
- struct sockaddr_un addr;
- int addr_len;
-
- memset(&addr, '\0', sizeof(addr));
- addr.sun_family = AF_UNIX;
-
- /* FIXME: compile time check? */
- if (sizeof(RANDOM_POOL) > sizeof(addr.sun_path))
- fatal("Random pool path is too long");
-
- strcpy(addr.sun_path, RANDOM_POOL);
-
- addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(RANDOM_POOL);
-
- random_pool = socket(AF_UNIX, SOCK_STREAM, 0);
-
- if (random_pool == -1)
- fatal("Couldn't create AF_UNIX socket: %s", strerror(errno));
-
- if (connect(random_pool, (struct sockaddr*)&addr, addr_len) == -1)
- fatal("Couldn't connect to EGD socket \"%s\": %s", addr.sun_path, strerror(errno));
-
- if (len > 255)
- fatal("Too many bytes to read from EGD");
-
- /* Send blocking read request to EGD */
- egd_message[1] = len;
-
- c = atomicio(write, random_pool, egd_message, sizeof(egd_message));
- if (c == -1)
- fatal("Couldn't write to EGD socket \"%s\": %s", RANDOM_POOL, strerror(errno));
-
- c = atomicio(read, random_pool, buf, len);
- if (c <= 0)
- fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
-
- close(random_pool);
-}
-#else /* HAVE_EGD */
-
-/* Collect entropy from /dev/urandom or pipe */
-void get_random_bytes(unsigned char *buf, int len)
-{
- static int random_pool;
- int c;
-
- random_pool = open(RANDOM_POOL, O_RDONLY);
- if (random_pool == -1)
- fatal("Couldn't open random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
-
- c = atomicio(read, random_pool, buf, len);
- if (c <= 0)
- fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno));
-
- close(random_pool);
-}
-
-#endif /* HAVE_EGD */
diff --git a/random.h b/random.h
deleted file mode 100644
index 6eb9f3a9..00000000
--- a/random.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-**
-** Random number collection
-**
-** Damien Miller <djm@ibs.com.au>
-**
-** Copyright 1999 Damien Miller
-**
-** Permission is hereby granted, free of charge, to any person
-** obtaining a copy of this software and associated documentation
-** files (the "Software"), to deal in the Software without
-** restriction, including without limitation the rights to use, copy,
-** modify, merge, publish, distribute, sublicense, and/or sell copies
-** of the Software, and to permit persons to whom the Software is
-** furnished to do so, subject to the following conditions:
-**
-** The above copyright notice and this permission notice shall be
-** included in all copies or substantial portions of the Software.
-**
-** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-** KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-** WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
-** AND NONINFRINGEMENT. IN NO EVENT SHALL DAMIEN MILLER OR INTERNET
-** BUSINESS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
-** OR OTHER DEALINGS IN THE SOFTWARE.
-**
-** Except as contained in this notice, the name of Internet Business
-** Solutions shall not be used in advertising or otherwise to promote
-** the sale, use or other dealings in this Software without prior
-** written authorization from Internet Business Solutions.
-**
-*/
-
-#ifndef _RANDOM_H
-#define _RANDOM_H
-
-void get_random_bytes(unsigned char *buf, int len);
-
-#endif /* _RANDOM_H */
diff --git a/rsa.c b/rsa.c
index babbf2b7..19160902 100644
--- a/rsa.c
+++ b/rsa.c
@@ -35,28 +35,15 @@
*/
#include "includes.h"
-RCSID("$Id: rsa.c,v 1.11 2000/03/17 12:40:16 damien Exp $");
+RCSID("$Id: rsa.c,v 1.12 2000/04/03 04:50:46 damien Exp $");
#include "rsa.h"
#include "ssh.h"
#include "xmalloc.h"
-#include "random.h"
+#include "entropy.h"
int rsa_verbose = 1;
-/*
- * Seed OpenSSL's random number generator
- */
-void
-seed_rng()
-{
- char buf[64];
-
- get_random_bytes(buf, sizeof(buf));
- RAND_seed(buf, sizeof(buf));
- memset(buf, 0, sizeof(buf));
-}
-
int
rsa_alive()
{
@@ -109,6 +96,8 @@ rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits)
if (key == NULL)
fatal("rsa_generate_key: key generation failed.");
+ seed_rng();
+
/* Copy public key parameters */
pub->n = BN_new();
BN_copy(pub->n, key->n);