summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2011-05-05 13:48:37 +1000
committerDamien Miller <djm@mindrot.org>2011-05-05 13:48:37 +1000
commitf22019bdbfb986daf24428a9d37f9fe9bb3ff7ad (patch)
treee23aa2864fccb6f4097d962aa14f9d78ca02a929
parent68790fedef210e03e36534b111e2f27b858170b4 (diff)
- (djm) [Makefile.in WARNING.RNG aclocal.m4 buildpkg.sh.in configure.ac]
[entropy.c ssh-add.c ssh-agent.c ssh-keygen.c ssh-keyscan.c] [ssh-keysign.c ssh-pkcs11-helper.c ssh-rand-helper.8 ssh-rand-helper.c] [ssh.c ssh_prng_cmds.in sshd.c contrib/aix/buildbff.sh] [regress/README.regress] Remove ssh-rand-helper and all its tentacles. PRNGd seeding has been rolled into entropy.c directly. Thanks to tim@ for testing on affected platforms.
-rw-r--r--.cvsignore2
-rw-r--r--ChangeLog7
-rw-r--r--INSTALL6
-rw-r--r--Makefile.in50
-rw-r--r--WARNING.RNG95
-rw-r--r--aclocal.m412
-rw-r--r--buildpkg.sh.in7
-rw-r--r--configure.ac249
-rwxr-xr-xcontrib/aix/buildbff.sh11
-rw-r--r--entropy.c238
-rw-r--r--regress/README.regress6
-rw-r--r--ssh-add.c1
-rw-r--r--ssh-agent.c1
-rw-r--r--ssh-keygen.c1
-rw-r--r--ssh-keyscan.c1
-rw-r--r--ssh-keysign.c1
-rw-r--r--ssh-pkcs11-helper.c1
-rw-r--r--ssh-rand-helper.894
-rw-r--r--ssh-rand-helper.c932
-rw-r--r--ssh.c1
-rw-r--r--ssh_prng_cmds.in75
-rw-r--r--sshd.c1
22 files changed, 237 insertions, 1555 deletions
diff --git a/.cvsignore b/.cvsignore
index 8dd3ddff9..9baaa3b4e 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -22,8 +22,6 @@ ssh-keygen
22ssh-keyscan 22ssh-keyscan
23ssh-keysign 23ssh-keysign
24ssh-pkcs11-helper 24ssh-pkcs11-helper
25ssh-rand-helper
26ssh_prng_cmds
27sshd 25sshd
28stamp-h.in 26stamp-h.in
29survey 27survey
diff --git a/ChangeLog b/ChangeLog
index 0105a95ec..25fe5918f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,13 @@
120110505 120110505
2 - (djm) [defines.h] Move up include of netinet/ip.h for IPTOS 2 - (djm) [defines.h] Move up include of netinet/ip.h for IPTOS
3 definitions. From des AT des.no 3 definitions. From des AT des.no
4 - (djm) [Makefile.in WARNING.RNG aclocal.m4 buildpkg.sh.in configure.ac]
5 [entropy.c ssh-add.c ssh-agent.c ssh-keygen.c ssh-keyscan.c]
6 [ssh-keysign.c ssh-pkcs11-helper.c ssh-rand-helper.8 ssh-rand-helper.c]
7 [ssh.c ssh_prng_cmds.in sshd.c contrib/aix/buildbff.sh]
8 [regress/README.regress] Remove ssh-rand-helper and all its
9 tentacles. PRNGd seeding has been rolled into entropy.c directly.
10 Thanks to tim@ for testing on affected platforms.
4 11
520110221 1220110221
6 - (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the 13 - (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the
diff --git a/INSTALL b/INSTALL
index 09dfd666d..0031dea85 100644
--- a/INSTALL
+++ b/INSTALL
@@ -16,9 +16,7 @@ The remaining items are optional.
16 16
17NB. If you operating system supports /dev/random, you should configure 17NB. If you operating system supports /dev/random, you should configure
18OpenSSL to use it. OpenSSH relies on OpenSSL's direct support of 18OpenSSL to use it. OpenSSH relies on OpenSSL's direct support of
19/dev/random, or failing that, either prngd or egd. If you don't have 19/dev/random, or failing that, either prngd or egd
20any of these you will have to rely on ssh-rand-helper, which is inferior
21to a good kernel-based solution or prngd.
22 20
23PRNGD: 21PRNGD:
24 22
@@ -262,4 +260,4 @@ Please refer to the "reporting bugs" section of the webpage at
262http://www.openssh.com/ 260http://www.openssh.com/
263 261
264 262
265$Id: INSTALL,v 1.85 2010/02/11 22:34:22 djm Exp $ 263$Id: INSTALL,v 1.86 2011/05/05 03:48:37 djm Exp $
diff --git a/Makefile.in b/Makefile.in
index d0263779b..f5b147619 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
1# $Id: Makefile.in,v 1.321 2011/01/25 01:16:16 djm Exp $ 1# $Id: Makefile.in,v 1.322 2011/05/05 03:48:37 djm Exp $
2 2
3# uncomment if you run a non bourne compatable shell. Ie. csh 3# uncomment if you run a non bourne compatable shell. Ie. csh
4#SHELL = @SH@ 4#SHELL = @SH@
@@ -26,7 +26,6 @@ ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass
26SFTP_SERVER=$(libexecdir)/sftp-server 26SFTP_SERVER=$(libexecdir)/sftp-server
27SSH_KEYSIGN=$(libexecdir)/ssh-keysign 27SSH_KEYSIGN=$(libexecdir)/ssh-keysign
28SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper 28SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
29RAND_HELPER=$(libexecdir)/ssh-rand-helper
30PRIVSEP_PATH=@PRIVSEP_PATH@ 29PRIVSEP_PATH=@PRIVSEP_PATH@
31SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ 30SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
32STRIP_OPT=@STRIP_OPT@ 31STRIP_OPT=@STRIP_OPT@
@@ -39,7 +38,6 @@ PATHS= -DSSHDIR=\"$(sysconfdir)\" \
39 -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \ 38 -D_PATH_SSH_PKCS11_HELPER=\"$(SSH_PKCS11_HELPER)\" \
40 -D_PATH_SSH_PIDDIR=\"$(piddir)\" \ 39 -D_PATH_SSH_PIDDIR=\"$(piddir)\" \
41 -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \ 40 -D_PATH_PRIVSEP_CHROOT_DIR=\"$(PRIVSEP_PATH)\" \
42 -DSSH_RAND_HELPER=\"$(RAND_HELPER)\"
43 41
44CC=@CC@ 42CC=@CC@
45LD=@LD@ 43LD=@LD@
@@ -61,10 +59,7 @@ LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
61EXEEXT=@EXEEXT@ 59EXEEXT=@EXEEXT@
62MANFMT=@MANFMT@ 60MANFMT=@MANFMT@
63 61
64INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ 62TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
65INSTALL_SSH_RAND_HELPER=@INSTALL_SSH_RAND_HELPER@
66
67TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) ssh-rand-helper${EXEEXT} sftp-server$(EXEEXT) sftp$(EXEEXT)
68 63
69LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \ 64LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
70 canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \ 65 canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
@@ -96,15 +91,14 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
96 sftp-server.o sftp-common.o \ 91 sftp-server.o sftp-common.o \
97 roaming_common.o roaming_serv.o 92 roaming_common.o roaming_serv.o
98 93
99MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out 94MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
100MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 95MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
101MANTYPE = @MANTYPE@ 96MANTYPE = @MANTYPE@
102 97
103CONFIGFILES=sshd_config.out ssh_config.out moduli.out 98CONFIGFILES=sshd_config.out ssh_config.out moduli.out
104CONFIGFILES_IN=sshd_config ssh_config moduli 99CONFIGFILES_IN=sshd_config ssh_config moduli
105 100
106PATHSUBS = \ 101PATHSUBS = \
107 -e 's|/etc/ssh/ssh_prng_cmds|$(sysconfdir)/ssh_prng_cmds|g' \
108 -e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \ 102 -e 's|/etc/ssh/ssh_config|$(sysconfdir)/ssh_config|g' \
109 -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \ 103 -e 's|/etc/ssh/ssh_known_hosts|$(sysconfdir)/ssh_known_hosts|g' \
110 -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \ 104 -e 's|/etc/ssh/sshd_config|$(sysconfdir)/sshd_config|g' \
@@ -124,7 +118,7 @@ PATHSUBS = \
124 118
125FIXPATHSCMD = $(SED) $(PATHSUBS) 119FIXPATHSCMD = $(SED) $(PATHSUBS)
126 120
127all: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) 121all: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
128 122
129$(LIBSSH_OBJS): Makefile.in config.h 123$(LIBSSH_OBJS): Makefile.in config.h
130$(SSHOBJS): Makefile.in config.h 124$(SSHOBJS): Makefile.in config.h
@@ -175,9 +169,6 @@ sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o s
175sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o 169sftp$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o
176 $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT) 170 $(LD) -o $@ progressmeter.o sftp.o sftp-client.o sftp-common.o sftp-glob.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
177 171
178ssh-rand-helper${EXEEXT}: $(LIBCOMPAT) libssh.a ssh-rand-helper.o
179 $(LD) -o $@ ssh-rand-helper.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
180
181# test driver for the loginrec code - not built by default 172# test driver for the loginrec code - not built by default
182logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o 173logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
183 $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS) 174 $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
@@ -198,11 +189,6 @@ $(CONFIGFILES): $(CONFIGFILES_IN)
198 conffile=`echo $@ | sed 's/.out$$//'`; \ 189 conffile=`echo $@ | sed 's/.out$$//'`; \
199 $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@ 190 $(FIXPATHSCMD) $(srcdir)/$${conffile} > $@
200 191
201ssh_prng_cmds.out: ssh_prng_cmds
202 if test ! -z "$(INSTALL_SSH_PRNG_CMDS)"; then \
203 $(PERL) $(srcdir)/fixprogs ssh_prng_cmds $(ENT); \
204 fi
205
206# fake rule to stop make trying to compile moduli.o into a binary "moduli.o" 192# fake rule to stop make trying to compile moduli.o into a binary "moduli.o"
207moduli: 193moduli:
208 echo 194 echo
@@ -215,7 +201,7 @@ clean: regressclean
215distclean: regressclean 201distclean: regressclean
216 rm -f *.o *.a $(TARGETS) logintest config.cache config.log 202 rm -f *.o *.a $(TARGETS) logintest config.cache config.log
217 rm -f *.out core opensshd.init openssh.xml 203 rm -f *.out core opensshd.init openssh.xml
218 rm -f Makefile buildpkg.sh config.h config.status ssh_prng_cmds 204 rm -f Makefile buildpkg.sh config.h config.status
219 rm -f survey.sh openbsd-compat/regress/Makefile *~ 205 rm -f survey.sh openbsd-compat/regress/Makefile *~
220 rm -rf autom4te.cache 206 rm -rf autom4te.cache
221 (cd openbsd-compat && $(MAKE) distclean) 207 (cd openbsd-compat && $(MAKE) distclean)
@@ -242,9 +228,9 @@ distprep: catman-do
242 $(AUTORECONF) 228 $(AUTORECONF)
243 -rm -rf autom4te.cache 229 -rm -rf autom4te.cache
244 230
245install: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config 231install: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf host-key check-config
246install-nokeys: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files install-sysconf 232install-nokeys: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files install-sysconf
247install-nosysconf: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) install-files 233install-nosysconf: $(CONFIGFILES) $(MANPAGES) $(TARGETS) install-files
248 234
249check-config: 235check-config:
250 -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config 236 -$(DESTDIR)$(sbindir)/sshd -t -f $(DESTDIR)$(sysconfdir)/sshd_config
@@ -265,9 +251,6 @@ install-files:
265 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT) 251 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keygen$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keygen$(EXEEXT)
266 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT) 252 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-keyscan$(EXEEXT) $(DESTDIR)$(bindir)/ssh-keyscan$(EXEEXT)
267 $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) 253 $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT)
268 if test ! -z "$(INSTALL_SSH_RAND_HELPER)" ; then \
269 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-rand-helper$(EXEEXT) $(DESTDIR)$(libexecdir)/ssh-rand-helper$(EXEEXT) ; \
270 fi
271 $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) 254 $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
272 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) 255 $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
273 $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) 256 $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT)
@@ -282,9 +265,6 @@ install-files:
282 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 265 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
283 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 266 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
284 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 267 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
285 if [ ! -z "$(INSTALL_SSH_RAND_HELPER)" ]; then \
286 $(INSTALL) -m 644 ssh-rand-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8 ; \
287 fi
288 $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 268 $(INSTALL) -m 644 sftp.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
289 $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 269 $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
290 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 270 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
@@ -308,13 +288,6 @@ install-sysconf:
308 else \ 288 else \
309 echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \ 289 echo "$(DESTDIR)$(sysconfdir)/sshd_config already exists, install will not overwrite"; \
310 fi 290 fi
311 @if [ -f ssh_prng_cmds ] && [ ! -z "$(INSTALL_SSH_PRNG_CMDS)" ]; then \
312 if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_prng_cmds ] ; then \
313 $(INSTALL) -m 644 ssh_prng_cmds.out $(DESTDIR)$(sysconfdir)/ssh_prng_cmds; \
314 else \
315 echo "$(DESTDIR)$(sysconfdir)/ssh_prng_cmds already exists, install will not overwrite"; \
316 fi ; \
317 fi
318 @if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \ 291 @if [ ! -f $(DESTDIR)$(sysconfdir)/moduli ]; then \
319 if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \ 292 if [ -f $(DESTDIR)$(sysconfdir)/primes ]; then \
320 echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \ 293 echo "moving $(DESTDIR)$(sysconfdir)/primes to $(DESTDIR)$(sysconfdir)/moduli"; \
@@ -361,7 +334,6 @@ host-key-force: ssh-keygen$(EXEEXT)
361uninstallall: uninstall 334uninstallall: uninstall
362 -rm -f $(DESTDIR)$(sysconfdir)/ssh_config 335 -rm -f $(DESTDIR)$(sysconfdir)/ssh_config
363 -rm -f $(DESTDIR)$(sysconfdir)/sshd_config 336 -rm -f $(DESTDIR)$(sysconfdir)/sshd_config
364 -rm -f $(DESTDIR)$(sysconfdir)/ssh_prng_cmds
365 -rmdir $(DESTDIR)$(sysconfdir) 337 -rmdir $(DESTDIR)$(sysconfdir)
366 -rmdir $(DESTDIR)$(bindir) 338 -rmdir $(DESTDIR)$(bindir)
367 -rmdir $(DESTDIR)$(sbindir) 339 -rmdir $(DESTDIR)$(sbindir)
@@ -383,7 +355,6 @@ uninstall:
383 -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) 355 -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT)
384 -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) 356 -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
385 -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) 357 -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT)
386 -rm -f $(DESTDIR)$(RAND_HELPER)$(EXEEXT)
387 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 358 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1
388 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 359 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1
389 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 360 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1
@@ -392,7 +363,6 @@ uninstall:
392 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1 363 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/sftp.1
393 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1 364 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-keyscan.1
394 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 365 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
395 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-rand-helper.8
396 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 366 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8
397 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 367 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
398 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 368 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
@@ -462,7 +432,7 @@ survey: survey.sh ssh
462send-survey: survey 432send-survey: survey
463 mail portable-survey@mindrot.org <survey 433 mail portable-survey@mindrot.org <survey
464 434
465package: $(CONFIGFILES) ssh_prng_cmds.out $(MANPAGES) $(TARGETS) 435package: $(CONFIGFILES) $(MANPAGES) $(TARGETS)
466 if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \ 436 if [ "@MAKE_PACKAGE_SUPPORTED@" = yes ]; then \
467 sh buildpkg.sh; \ 437 sh buildpkg.sh; \
468 fi 438 fi
diff --git a/WARNING.RNG b/WARNING.RNG
deleted file mode 100644
index 97da74ff7..000000000
--- a/WARNING.RNG
+++ /dev/null
@@ -1,95 +0,0 @@
1This document contains a description of portable OpenSSH's random
2number collection code. An alternate reading of this text could
3well be titled "Why I should pressure my system vendor to supply
4/dev/random in their OS".
5
6Why is this important? OpenSSH depends on good, unpredictable numbers
7for generating keys, performing digital signatures and forming
8cryptographic challenges. If the random numbers that it uses are
9predictable, then the strength of the whole system is compromised.
10
11A particularly pernicious problem arises with DSA keys (used by the
12ssh2 protocol). Performing a DSA signature (which is required for
13authentication), entails the use of a 160 bit random number. If an
14attacker can predict this number, then they can deduce your *private*
15key and impersonate you or your hosts.
16
17If you are using the builtin random number support (configure will
18tell you if this is the case), then read this document in its entirety.
19Alternately, you can use Lutz Jaenicke's PRNGd - a small daemon which
20collects random numbers and makes them available by a socket.
21
22Please also request that your OS vendor provides a kernel-based random
23number collector (/dev/random) in future versions of your operating
24systems by default.
25
26On to the description...
27
28The portable OpenSSH contains random number collection support for
29systems which lack a kernel entropy pool (/dev/random).
30
31This collector (as of 3.1 and beyond) comes as an external application
32that allows the local admin to decide on how to implement entropy
33collection.
34
35The default entropy collector operates by executing the programs listed
36in ($etcdir)/ssh_prng_cmds, reading their output and adding it to the
37PRNG supplied by OpenSSL (which is hash-based). It also stirs in the
38output of several system calls and timings from the execution of the
39programs that it runs.
40
41The ssh_prng_cmds file also specifies a 'rate' for each program. This
42represents the number of bits of randomness per byte of output from
43the specified program.
44
45The random number code will also read and save a seed file to
46~/.ssh/prng_seed. This contents of this file are added to the random
47number generator at startup. The goal here is to maintain as much
48randomness between sessions as possible.
49
50The default entropy collection code has two main problems:
51
521. It is slow.
53
54Executing each program in the list can take a large amount of time,
55especially on slower machines. Additionally some program can take a
56disproportionate time to execute.
57
58Tuning the random helper can be done by running ./ssh-random-helper in
59very verbose mode ("-vvv") and identifying the commands that are taking
60excessive amounts of time or hanging altogher. Any problem commands can
61be modified or removed from ssh_prng_cmds.
62
63The default entropy collector will timeout programs which take too long
64to execute, the actual timeout used can be adjusted with the
65--with-entropy-timeout configure option. OpenSSH will not try to
66re-execute programs which have not been found, have had a non-zero
67exit status or have timed out more than a couple of times.
68
692. Estimating the real 'rate' of program outputs is non-trivial
70
71The shear volume of the task is problematic: there are currently
72around 50 commands in the ssh_prng_cmds list, portable OpenSSH
73supports at least 12 different OSs. That is already 600 sets of data
74to be analysed, without taking into account the numerous differences
75between versions of each OS.
76
77On top of this, the different commands can produce varying amounts of
78usable data depending on how busy the machine is, how long it has been
79up and various other factors.
80
81To make matters even more complex, some of the commands are reporting
82largely the same data as other commands (eg. the various "ps" calls).
83
84
85How to avoid the default entropy code?
86
87The best way is to read the OpenSSL documentation and recompile OpenSSL
88to use prngd or egd. Some platforms (like earily solaris) have 3rd
89party /dev/random devices that can be also used for this task.
90
91If you are forced to use ssh-rand-helper consider still downloading
92prngd/egd and configure OpenSSH using --with-prngd-port=xx or
93--with-prngd-socket=xx (refer to INSTALL for more information).
94
95$Id: WARNING.RNG,v 1.8 2005/05/26 01:47:54 djm Exp $
diff --git a/aclocal.m4 b/aclocal.m4
index b68a47080..83b241f7b 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,4 +1,4 @@
1dnl $Id: aclocal.m4,v 1.6 2005/09/19 16:33:39 tim Exp $ 1dnl $Id: aclocal.m4,v 1.7 2011/05/05 03:48:37 djm Exp $
2dnl 2dnl
3dnl OpenSSH-specific autoconf macros 3dnl OpenSSH-specific autoconf macros
4dnl 4dnl
@@ -33,16 +33,6 @@ AC_DEFUN(OSSH_CHECK_HEADER_FOR_FIELD, [
33 fi 33 fi
34]) 34])
35 35
36dnl OSSH_PATH_ENTROPY_PROG(variablename, command):
37dnl Tidiness function, sets 'undef' if not found, and does the AC_SUBST
38AC_DEFUN(OSSH_PATH_ENTROPY_PROG, [
39 AC_PATH_PROG($1, $2)
40 if test -z "[$]$1" ; then
41 $1="undef"
42 fi
43 AC_SUBST($1)
44])
45
46dnl Check for socklen_t: historically on BSD it is an int, and in 36dnl Check for socklen_t: historically on BSD it is an int, and in
47dnl POSIX 1g it is a type of its own, but some platforms use different 37dnl POSIX 1g it is a type of its own, but some platforms use different
48dnl types for the argument to getsockopt, getpeername, etc. So we 38dnl types for the argument to getsockopt, getpeername, etc. So we
diff --git a/buildpkg.sh.in b/buildpkg.sh.in
index 22c66fbd4..4de9d42e4 100644
--- a/buildpkg.sh.in
+++ b/buildpkg.sh.in
@@ -229,8 +229,6 @@ perl -p -i -e "s/#PrintMotd yes/PrintMotd no/" \
229# We don't want to overwrite config files on multiple installs 229# We don't want to overwrite config files on multiple installs
230mv $FAKE_ROOT${sysconfdir}/ssh_config $FAKE_ROOT${sysconfdir}/ssh_config.default 230mv $FAKE_ROOT${sysconfdir}/ssh_config $FAKE_ROOT${sysconfdir}/ssh_config.default
231mv $FAKE_ROOT${sysconfdir}/sshd_config $FAKE_ROOT${sysconfdir}/sshd_config.default 231mv $FAKE_ROOT${sysconfdir}/sshd_config $FAKE_ROOT${sysconfdir}/sshd_config.default
232[ -f $FAKE_ROOT${sysconfdir}/ssh_prng_cmds ] && \
233mv $FAKE_ROOT${sysconfdir}/ssh_prng_cmds $FAKE_ROOT${sysconfdir}/ssh_prng_cmds.default
234 232
235# local tweeks here 233# local tweeks here
236[ -s "${POST_MAKE_INSTALL_FIXES}" ] && . ${POST_MAKE_INSTALL_FIXES} 234[ -s "${POST_MAKE_INSTALL_FIXES}" ] && . ${POST_MAKE_INSTALL_FIXES}
@@ -317,11 +315,6 @@ cat > postinstall << _EOF
317[ -f \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config ] || \\ 315[ -f \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config ] || \\
318 cp -p \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config.default \\ 316 cp -p \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config.default \\
319 \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config 317 \${PKG_INSTALL_ROOT}${sysconfdir}/sshd_config
320[ -f \${PKG_INSTALL_ROOT}${sysconfdir}/ssh_prng_cmds.default ] && {
321 [ -f \${PKG_INSTALL_ROOT}${sysconfdir}/ssh_prng_cmds ] || \\
322 cp -p \${PKG_INSTALL_ROOT}${sysconfdir}/ssh_prng_cmds.default \\
323 \${PKG_INSTALL_ROOT}${sysconfdir}/ssh_prng_cmds
324}
325 318
326# make rc?.d dirs only if we are doing a test install 319# make rc?.d dirs only if we are doing a test install
327[ -n "${TEST_DIR}" ] && [ $DO_SMF -ne 1 ] && { 320[ -n "${TEST_DIR}" ] && [ $DO_SMF -ne 1 ] && {
diff --git a/configure.ac b/configure.ac
index c8d90ea0d..573c09710 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
1# $Id: configure.ac,v 1.471 2011/01/26 20:38:58 tim Exp $ 1# $Id: configure.ac,v 1.472 2011/05/05 03:48:37 djm Exp $
2# 2#
3# Copyright (c) 1999-2004 Damien Miller 3# Copyright (c) 1999-2004 Damien Miller
4# 4#
@@ -15,7 +15,7 @@
15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 16
17AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) 17AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org])
18AC_REVISION($Revision: 1.471 $) 18AC_REVISION($Revision: 1.472 $)
19AC_CONFIG_SRCDIR([ssh.c]) 19AC_CONFIG_SRCDIR([ssh.c])
20AC_LANG([C]) 20AC_LANG([C])
21 21
@@ -2299,113 +2299,15 @@ AC_RUN_IFELSE(
2299 ], 2299 ],
2300 [ 2300 [
2301 AC_MSG_RESULT([no]) 2301 AC_MSG_RESULT([no])
2302 # Default to use of the rand helper if OpenSSL doesn't
2303 # seed itself
2304 USE_RAND_HELPER=yes
2305 ], 2302 ],
2306 [ 2303 [
2307 AC_MSG_WARN([cross compiling: assuming yes]) 2304 AC_MSG_WARN([cross compiling: assuming yes])
2308 # This is safe, since all recent OpenSSL versions will 2305 # This is safe, since we will fatal() at runtime if
2309 # complain at runtime if not seeded correctly. 2306 # OpenSSL is not seeded correctly.
2310 OPENSSL_SEEDS_ITSELF=yes 2307 OPENSSL_SEEDS_ITSELF=yes
2311 ] 2308 ]
2312) 2309)
2313 2310
2314# Check for PAM libs
2315PAM_MSG="no"
2316AC_ARG_WITH([pam],
2317 [ --with-pam Enable PAM support ],
2318 [
2319 if test "x$withval" != "xno" ; then
2320 if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \
2321 test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then
2322 AC_MSG_ERROR([PAM headers not found])
2323 fi
2324
2325 saved_LIBS="$LIBS"
2326 AC_CHECK_LIB([dl], [dlopen], , )
2327 AC_CHECK_LIB([pam], [pam_set_item], , [AC_MSG_ERROR([*** libpam missing])])
2328 AC_CHECK_FUNCS([pam_getenvlist])
2329 AC_CHECK_FUNCS([pam_putenv])
2330 LIBS="$saved_LIBS"
2331
2332 PAM_MSG="yes"
2333
2334 SSHDLIBS="$SSHDLIBS -lpam"
2335 AC_DEFINE([USE_PAM], [1],
2336 [Define if you want to enable PAM support])
2337
2338 if test $ac_cv_lib_dl_dlopen = yes; then
2339 case "$LIBS" in
2340 *-ldl*)
2341 # libdl already in LIBS
2342 ;;
2343 *)
2344 SSHDLIBS="$SSHDLIBS -ldl"
2345 ;;
2346 esac
2347 fi
2348 fi
2349 ]
2350)
2351
2352# Check for older PAM
2353if test "x$PAM_MSG" = "xyes" ; then
2354 # Check PAM strerror arguments (old PAM)
2355 AC_MSG_CHECKING([whether pam_strerror takes only one argument])
2356 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
2357#include <stdlib.h>
2358#if defined(HAVE_SECURITY_PAM_APPL_H)
2359#include <security/pam_appl.h>
2360#elif defined (HAVE_PAM_PAM_APPL_H)
2361#include <pam/pam_appl.h>
2362#endif
2363 ]], [[
2364(void)pam_strerror((pam_handle_t *)NULL, -1);
2365 ]])], [AC_MSG_RESULT([no])], [
2366 AC_DEFINE([HAVE_OLD_PAM], [1],
2367 [Define if you have an old version of PAM
2368 which takes only one argument to pam_strerror])
2369 AC_MSG_RESULT([yes])
2370 PAM_MSG="yes (old library)"
2371
2372 ])
2373fi
2374
2375# Do we want to force the use of the rand helper?
2376AC_ARG_WITH([rand-helper],
2377 [ --with-rand-helper Use subprocess to gather strong randomness ],
2378 [
2379 if test "x$withval" = "xno" ; then
2380 # Force use of OpenSSL's internal RNG, even if
2381 # the previous test showed it to be unseeded.
2382 if test -z "$OPENSSL_SEEDS_ITSELF" ; then
2383 AC_MSG_WARN([*** Forcing use of OpenSSL's non-self-seeding PRNG])
2384 OPENSSL_SEEDS_ITSELF=yes
2385 USE_RAND_HELPER=""
2386 fi
2387 else
2388 USE_RAND_HELPER=yes
2389 fi
2390 ],
2391)
2392
2393# Which randomness source do we use?
2394if test ! -z "$OPENSSL_SEEDS_ITSELF" && test -z "$USE_RAND_HELPER" ; then
2395 # OpenSSL only
2396 AC_DEFINE([OPENSSL_PRNG_ONLY], [1],
2397 [Define if you want OpenSSL's internally seeded PRNG only])
2398 RAND_MSG="OpenSSL internal ONLY"
2399 INSTALL_SSH_RAND_HELPER=""
2400elif test ! -z "$USE_RAND_HELPER" ; then
2401 # install rand helper
2402 RAND_MSG="ssh-rand-helper"
2403 INSTALL_SSH_RAND_HELPER="yes"
2404fi
2405AC_SUBST([INSTALL_SSH_RAND_HELPER])
2406
2407### Configuration of ssh-rand-helper
2408
2409# PRNGD TCP socket 2311# PRNGD TCP socket
2410AC_ARG_WITH([prngd-port], 2312AC_ARG_WITH([prngd-port],
2411 [ --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT], 2313 [ --with-prngd-port=PORT read entropy from PRNGD/EGD TCP localhost:PORT],
@@ -2460,7 +2362,7 @@ AC_ARG_WITH([prngd-socket],
2460 ], 2362 ],
2461 [ 2363 [
2462 # Check for existing socket only if we don't have a random device already 2364 # Check for existing socket only if we don't have a random device already
2463 if test "$USE_RAND_HELPER" = yes ; then 2365 if test "x$OPENSSL_SEEDS_ITSELF" != "xyes" ; then
2464 AC_MSG_CHECKING([for PRNGD/EGD socket]) 2366 AC_MSG_CHECKING([for PRNGD/EGD socket])
2465 # Insert other locations here 2367 # Insert other locations here
2466 for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do 2368 for sock in /var/run/egd-pool /dev/egd-pool /etc/entropy; do
@@ -2479,19 +2381,79 @@ AC_ARG_WITH([prngd-socket],
2479 ] 2381 ]
2480) 2382)
2481 2383
2482# Change default command timeout for hashing entropy source 2384# Which randomness source do we use?
2483entropy_timeout=200 2385if test ! -z "$PRNGD_PORT" ; then
2484AC_ARG_WITH([entropy-timeout], 2386 RAND_MSG="PRNGd port $PRNGD_PORT"
2485 [ --with-entropy-timeout Specify entropy gathering command timeout (msec)], 2387elif test ! -z "$PRNGD_SOCKET" ; then
2388 RAND_MSG="PRNGd socket $PRNGD_SOCKET"
2389elif test ! -z "$OPENSSL_SEEDS_ITSELF" ; then
2390 AC_DEFINE([OPENSSL_PRNG_ONLY], [1],
2391 [Define if you want OpenSSL's internally seeded PRNG only])
2392 RAND_MSG="OpenSSL internal ONLY"
2393else
2394 AC_MSG_ERROR([OpenSSH has no source of random numbers. Please configure OpenSSL with an entropy source or re-run configure using one of the --with-prngd-port or --with-prngd-socket options])
2395fi
2396
2397# Check for PAM libs
2398PAM_MSG="no"
2399AC_ARG_WITH([pam],
2400 [ --with-pam Enable PAM support ],
2486 [ 2401 [
2487 if test -n "$withval" && test "x$withval" != "xno" && \ 2402 if test "x$withval" != "xno" ; then
2488 test "x${withval}" != "xyes"; then 2403 if test "x$ac_cv_header_security_pam_appl_h" != "xyes" && \
2489 entropy_timeout=$withval 2404 test "x$ac_cv_header_pam_pam_appl_h" != "xyes" ; then
2405 AC_MSG_ERROR([PAM headers not found])
2406 fi
2407
2408 saved_LIBS="$LIBS"
2409 AC_CHECK_LIB([dl], [dlopen], , )
2410 AC_CHECK_LIB([pam], [pam_set_item], , [AC_MSG_ERROR([*** libpam missing])])
2411 AC_CHECK_FUNCS([pam_getenvlist])
2412 AC_CHECK_FUNCS([pam_putenv])
2413 LIBS="$saved_LIBS"
2414
2415 PAM_MSG="yes"
2416
2417 SSHDLIBS="$SSHDLIBS -lpam"
2418 AC_DEFINE([USE_PAM], [1],
2419 [Define if you want to enable PAM support])
2420
2421 if test $ac_cv_lib_dl_dlopen = yes; then
2422 case "$LIBS" in
2423 *-ldl*)
2424 # libdl already in LIBS
2425 ;;
2426 *)
2427 SSHDLIBS="$SSHDLIBS -ldl"
2428 ;;
2429 esac
2430 fi
2490 fi 2431 fi
2491 ] 2432 ]
2492) 2433)
2493AC_DEFINE_UNQUOTED([ENTROPY_TIMEOUT_MSEC], [$entropy_timeout], 2434
2494 [Builtin PRNG command timeout]) 2435# Check for older PAM
2436if test "x$PAM_MSG" = "xyes" ; then
2437 # Check PAM strerror arguments (old PAM)
2438 AC_MSG_CHECKING([whether pam_strerror takes only one argument])
2439 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
2440#include <stdlib.h>
2441#if defined(HAVE_SECURITY_PAM_APPL_H)
2442#include <security/pam_appl.h>
2443#elif defined (HAVE_PAM_PAM_APPL_H)
2444#include <pam/pam_appl.h>
2445#endif
2446 ]], [[
2447(void)pam_strerror((pam_handle_t *)NULL, -1);
2448 ]])], [AC_MSG_RESULT([no])], [
2449 AC_DEFINE([HAVE_OLD_PAM], [1],
2450 [Define if you have an old version of PAM
2451 which takes only one argument to pam_strerror])
2452 AC_MSG_RESULT([yes])
2453 PAM_MSG="yes (old library)"
2454
2455 ])
2456fi
2495 2457
2496SSH_PRIVSEP_USER=sshd 2458SSH_PRIVSEP_USER=sshd
2497AC_ARG_WITH([privsep-user], 2459AC_ARG_WITH([privsep-user],
@@ -2507,56 +2469,6 @@ AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"],
2507 [non-privileged user for privilege separation]) 2469 [non-privileged user for privilege separation])
2508AC_SUBST([SSH_PRIVSEP_USER]) 2470AC_SUBST([SSH_PRIVSEP_USER])
2509 2471
2510# We do this little dance with the search path to insure
2511# that programs that we select for use by installed programs
2512# (which may be run by the super-user) come from trusted
2513# locations before they come from the user's private area.
2514# This should help avoid accidentally configuring some
2515# random version of a program in someone's personal bin.
2516
2517OPATH=$PATH
2518PATH=/bin:/usr/bin
2519test -h /bin 2> /dev/null && PATH=/usr/bin
2520test -d /sbin && PATH=$PATH:/sbin
2521test -d /usr/sbin && PATH=$PATH:/usr/sbin
2522PATH=$PATH:/etc:$OPATH
2523
2524# These programs are used by the command hashing source to gather entropy
2525OSSH_PATH_ENTROPY_PROG([PROG_LS], [ls])
2526OSSH_PATH_ENTROPY_PROG([PROG_NETSTAT], [netstat])
2527OSSH_PATH_ENTROPY_PROG([PROG_ARP], [arp])
2528OSSH_PATH_ENTROPY_PROG([PROG_IFCONFIG], [ifconfig])
2529OSSH_PATH_ENTROPY_PROG([PROG_JSTAT], [jstat])
2530OSSH_PATH_ENTROPY_PROG([PROG_PS], [ps])
2531OSSH_PATH_ENTROPY_PROG([PROG_SAR], [sar])
2532OSSH_PATH_ENTROPY_PROG([PROG_W], [w])
2533OSSH_PATH_ENTROPY_PROG([PROG_WHO], [who])
2534OSSH_PATH_ENTROPY_PROG([PROG_LAST], [last])
2535OSSH_PATH_ENTROPY_PROG([PROG_LASTLOG], [lastlog])
2536OSSH_PATH_ENTROPY_PROG([PROG_DF], [df])
2537OSSH_PATH_ENTROPY_PROG([PROG_VMSTAT], [vmstat])
2538OSSH_PATH_ENTROPY_PROG([PROG_UPTIME], [uptime])
2539OSSH_PATH_ENTROPY_PROG([PROG_IPCS], [ipcs])
2540OSSH_PATH_ENTROPY_PROG([PROG_TAIL], [tail])
2541# restore PATH
2542PATH=$OPATH
2543
2544# Where does ssh-rand-helper get its randomness from?
2545INSTALL_SSH_PRNG_CMDS=""
2546if test ! -z "$INSTALL_SSH_RAND_HELPER" ; then
2547 if test ! -z "$PRNGD_PORT" ; then
2548 RAND_HELPER_MSG="TCP localhost:$PRNGD_PORT"
2549 elif test ! -z "$PRNGD_SOCKET" ; then
2550 RAND_HELPER_MSG="Unix domain socket \"$PRNGD_SOCKET\""
2551 else
2552 RAND_HELPER_MSG="Command hashing (timeout $entropy_timeout)"
2553 RAND_HELPER_CMDHASH=yes
2554 INSTALL_SSH_PRNG_CMDS="yes"
2555 fi
2556fi
2557AC_SUBST([INSTALL_SSH_PRNG_CMDS])
2558
2559
2560# Cheap hack to ensure NEWS-OS libraries are arranged right. 2472# Cheap hack to ensure NEWS-OS libraries are arranged right.
2561if test ! -z "$SONY" ; then 2473if test ! -z "$SONY" ; then
2562 LIBS="$LIBS -liberty"; 2474 LIBS="$LIBS -liberty";
@@ -4157,7 +4069,7 @@ AC_SUBST([TEST_SSH_IPV6], [$TEST_SSH_IPV6])
4157AC_EXEEXT 4069AC_EXEEXT
4158AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \ 4070AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
4159 openbsd-compat/Makefile openbsd-compat/regress/Makefile \ 4071 openbsd-compat/Makefile openbsd-compat/regress/Makefile \
4160 ssh_prng_cmds survey.sh]) 4072 survey.sh])
4161AC_OUTPUT 4073AC_OUTPUT
4162 4074
4163# Print summary of options 4075# Print summary of options
@@ -4212,9 +4124,6 @@ echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
4212echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" 4124echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
4213echo " BSD Auth support: $BSD_AUTH_MSG" 4125echo " BSD Auth support: $BSD_AUTH_MSG"
4214echo " Random number source: $RAND_MSG" 4126echo " Random number source: $RAND_MSG"
4215if test ! -z "$USE_RAND_HELPER" ; then
4216echo " ssh-rand-helper collects from: $RAND_HELPER_MSG"
4217fi
4218 4127
4219echo "" 4128echo ""
4220 4129
@@ -4246,14 +4155,6 @@ if test "x$PAM_MSG" = "xyes" ; then
4246 echo "" 4155 echo ""
4247fi 4156fi
4248 4157
4249if test ! -z "$RAND_HELPER_CMDHASH" ; then
4250 echo "WARNING: you are using the builtin random number collection "
4251 echo "service. Please read WARNING.RNG and request that your OS "
4252 echo "vendor includes kernel-based random number collection in "
4253 echo "future versions of your OS."
4254 echo ""
4255fi
4256
4257if test ! -z "$NO_PEERCHECK" ; then 4158if test ! -z "$NO_PEERCHECK" ; then
4258 echo "WARNING: the operating system that you are using does not" 4159 echo "WARNING: the operating system that you are using does not"
4259 echo "appear to support getpeereid(), getpeerucred() or the" 4160 echo "appear to support getpeereid(), getpeerucred() or the"
diff --git a/contrib/aix/buildbff.sh b/contrib/aix/buildbff.sh
index ca4bf0210..81d8cc301 100755
--- a/contrib/aix/buildbff.sh
+++ b/contrib/aix/buildbff.sh
@@ -1,7 +1,7 @@
1#!/bin/sh 1#!/bin/sh
2# 2#
3# buildbff.sh: Create AIX SMIT-installable OpenSSH packages 3# buildbff.sh: Create AIX SMIT-installable OpenSSH packages
4# $Id: buildbff.sh,v 1.12 2010/04/18 03:35:00 dtucker Exp $ 4# $Id: buildbff.sh,v 1.13 2011/05/05 03:48:41 djm Exp $
5# 5#
6# Author: Darren Tucker (dtucker at zip dot com dot au) 6# Author: Darren Tucker (dtucker at zip dot com dot au)
7# This file is placed in the public domain and comes with absolutely 7# This file is placed in the public domain and comes with absolutely
@@ -156,13 +156,6 @@ do
156 mv $FAKE_ROOT/$sysconfdir/$cfgfile $FAKE_ROOT/$sysconfdir/$cfgfile.default 156 mv $FAKE_ROOT/$sysconfdir/$cfgfile $FAKE_ROOT/$sysconfdir/$cfgfile.default
157done 157done
158 158
159# AIX 5.3 and newer have /dev/random and don't create ssh_prng_cmds
160if [ -f $FAKE_ROOT/$sysconfdir/ssh_prng_cmds ]
161then
162 mv $FAKE_ROOT/$sysconfdir/ssh_prng_cmds \
163 $FAKE_ROOT/$sysconfdir/ssh_prng_cmds.default
164fi
165
166# 159#
167# Generate lpp control files. 160# Generate lpp control files.
168# working dir is $FAKE_ROOT but files are generated in dir above 161# working dir is $FAKE_ROOT but files are generated in dir above
@@ -197,7 +190,7 @@ cat <<EOF >>../openssh.post_i
197#!/bin/sh 190#!/bin/sh
198 191
199echo Creating configs from defaults if necessary. 192echo Creating configs from defaults if necessary.
200for cfgfile in ssh_config sshd_config ssh_prng_cmds 193for cfgfile in ssh_config sshd_config
201do 194do
202 if [ ! -f $sysconfdir/\$cfgfile ] 195 if [ ! -f $sysconfdir/\$cfgfile ]
203 then 196 then
diff --git a/entropy.c b/entropy.c
index a82166258..2d6d3ec52 100644
--- a/entropy.c
+++ b/entropy.c
@@ -25,19 +25,19 @@
25#include "includes.h" 25#include "includes.h"
26 26
27#include <sys/types.h> 27#include <sys/types.h>
28#include <sys/wait.h> 28#include <sys/socket.h>
29 29#ifdef HAVE_SYS_UN_H
30#ifdef HAVE_SYS_STAT_H 30# include <sys/un.h>
31# include <sys/stat.h>
32#endif 31#endif
33 32
34#ifdef HAVE_FCNTL_H 33#include <netinet/in.h>
35# include <fcntl.h> 34#include <arpa/inet.h>
36#endif 35
37#include <stdarg.h> 36#include <errno.h>
38#include <string.h>
39#include <signal.h> 37#include <signal.h>
38#include <string.h>
40#include <unistd.h> 39#include <unistd.h>
40#include <stddef.h> /* for offsetof */
41 41
42#include <openssl/rand.h> 42#include <openssl/rand.h>
43#include <openssl/crypto.h> 43#include <openssl/crypto.h>
@@ -54,118 +54,128 @@
54/* 54/*
55 * Portable OpenSSH PRNG seeding: 55 * Portable OpenSSH PRNG seeding:
56 * If OpenSSL has not "internally seeded" itself (e.g. pulled data from 56 * If OpenSSL has not "internally seeded" itself (e.g. pulled data from
57 * /dev/random), then we execute a "ssh-rand-helper" program which 57 * /dev/random), then collect RANDOM_SEED_SIZE bytes of randomness from
58 * collects entropy and writes it to stdout. The child program must 58 * PRNGd.
59 * write at least RANDOM_SEED_SIZE bytes. The child is run with stderr
60 * attached, so error/debugging output should be visible.
61 *
62 * XXX: we should tell the child how many bytes we need.
63 */ 59 */
64
65#ifndef OPENSSL_PRNG_ONLY 60#ifndef OPENSSL_PRNG_ONLY
61
66#define RANDOM_SEED_SIZE 48 62#define RANDOM_SEED_SIZE 48
67static uid_t original_uid, original_euid;
68#endif
69 63
70void 64/*
71seed_rng(void) 65 * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon
66 * listening either on 'tcp_port', or via Unix domain socket at *
67 * 'socket_path'.
68 * Either a non-zero tcp_port or a non-null socket_path must be
69 * supplied.
70 * Returns 0 on success, -1 on error
71 */
72int
73get_random_bytes_prngd(unsigned char *buf, int len,
74 unsigned short tcp_port, char *socket_path)
72{ 75{
73#ifndef OPENSSL_PRNG_ONLY 76 int fd, addr_len, rval, errors;
74 int devnull; 77 u_char msg[2];
75 int p[2]; 78 struct sockaddr_storage addr;
76 pid_t pid; 79 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
77 int ret; 80 struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr;
78 unsigned char buf[RANDOM_SEED_SIZE]; 81 mysig_t old_sigpipe;
79 mysig_t old_sigchld; 82
83 /* Sanity checks */
84 if (socket_path == NULL && tcp_port == 0)
85 fatal("You must specify a port or a socket");
86 if (socket_path != NULL &&
87 strlen(socket_path) >= sizeof(addr_un->sun_path))
88 fatal("Random pool path is too long");
89 if (len <= 0 || len > 255)
90 fatal("Too many bytes (%d) to read from PRNGD", len);
91
92 memset(&addr, '\0', sizeof(addr));
93
94 if (tcp_port != 0) {
95 addr_in->sin_family = AF_INET;
96 addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
97 addr_in->sin_port = htons(tcp_port);
98 addr_len = sizeof(*addr_in);
99 } else {
100 addr_un->sun_family = AF_UNIX;
101 strlcpy(addr_un->sun_path, socket_path,
102 sizeof(addr_un->sun_path));
103 addr_len = offsetof(struct sockaddr_un, sun_path) +
104 strlen(socket_path) + 1;
105 }
80 106
81 if (RAND_status() == 1) { 107 old_sigpipe = mysignal(SIGPIPE, SIG_IGN);
82 debug3("RNG is ready, skipping seeding"); 108
83 return; 109 errors = 0;
110 rval = -1;
111reopen:
112 fd = socket(addr.ss_family, SOCK_STREAM, 0);
113 if (fd == -1) {
114 error("Couldn't create socket: %s", strerror(errno));
115 goto done;
84 } 116 }
85 117
86 debug3("Seeding PRNG from %s", SSH_RAND_HELPER); 118 if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) {
87 119 if (tcp_port != 0) {
88 if ((devnull = open("/dev/null", O_RDWR)) == -1) 120 error("Couldn't connect to PRNGD port %d: %s",
89 fatal("Couldn't open /dev/null: %s", strerror(errno)); 121 tcp_port, strerror(errno));
90 if (pipe(p) == -1) 122 } else {
91 fatal("pipe: %s", strerror(errno)); 123 error("Couldn't connect to PRNGD socket \"%s\": %s",
92 124 addr_un->sun_path, strerror(errno));
93 old_sigchld = signal(SIGCHLD, SIG_DFL);
94 if ((pid = fork()) == -1)
95 fatal("Couldn't fork: %s", strerror(errno));
96 if (pid == 0) {
97 dup2(devnull, STDIN_FILENO);
98 dup2(p[1], STDOUT_FILENO);
99 /* Keep stderr open for errors */
100 close(p[0]);
101 close(p[1]);
102 close(devnull);
103
104 if (original_uid != original_euid &&
105 ( seteuid(getuid()) == -1 ||
106 setuid(original_uid) == -1) ) {
107 fprintf(stderr, "(rand child) setuid(%li): %s\n",
108 (long int)original_uid, strerror(errno));
109 _exit(1);
110 } 125 }
111 126 goto done;
112 execl(SSH_RAND_HELPER, "ssh-rand-helper", NULL);
113 fprintf(stderr, "(rand child) Couldn't exec '%s': %s\n",
114 SSH_RAND_HELPER, strerror(errno));
115 _exit(1);
116 } 127 }
117 128
118 close(devnull); 129 /* Send blocking read request to PRNGD */
119 close(p[1]); 130 msg[0] = 0x02;
131 msg[1] = len;
120 132
121 memset(buf, '\0', sizeof(buf)); 133 if (atomicio(vwrite, fd, msg, sizeof(msg)) != sizeof(msg)) {
122 ret = atomicio(read, p[0], buf, sizeof(buf)); 134 if (errno == EPIPE && errors < 10) {
123 if (ret == -1) 135 close(fd);
124 fatal("Couldn't read from ssh-rand-helper: %s", 136 errors++;
137 goto reopen;
138 }
139 error("Couldn't write to PRNGD socket: %s",
125 strerror(errno)); 140 strerror(errno));
126 if (ret != sizeof(buf)) 141 goto done;
127 fatal("ssh-rand-helper child produced insufficient data"); 142 }
128
129 close(p[0]);
130 143
131 if (waitpid(pid, &ret, 0) == -1) 144 if (atomicio(read, fd, buf, len) != (size_t)len) {
132 fatal("Couldn't wait for ssh-rand-helper completion: %s", 145 if (errno == EPIPE && errors < 10) {
146 close(fd);
147 errors++;
148 goto reopen;
149 }
150 error("Couldn't read from PRNGD socket: %s",
133 strerror(errno)); 151 strerror(errno));
134 signal(SIGCHLD, old_sigchld); 152 goto done;
135 153 }
136 /* We don't mind if the child exits upon a SIGPIPE */
137 if (!WIFEXITED(ret) &&
138 (!WIFSIGNALED(ret) || WTERMSIG(ret) != SIGPIPE))
139 fatal("ssh-rand-helper terminated abnormally");
140 if (WEXITSTATUS(ret) != 0)
141 fatal("ssh-rand-helper exit with exit status %d", ret);
142
143 RAND_add(buf, sizeof(buf), sizeof(buf));
144 memset(buf, '\0', sizeof(buf));
145 154
146#endif /* OPENSSL_PRNG_ONLY */ 155 rval = 0;
147 if (RAND_status() != 1) 156done:
148 fatal("PRNG is not seeded"); 157 mysignal(SIGPIPE, old_sigpipe);
158 if (fd != -1)
159 close(fd);
160 return rval;
149} 161}
150 162
151void 163static int
152init_rng(void) 164seed_from_prngd(unsigned char *buf, size_t bytes)
153{ 165{
154 /* 166#ifdef PRNGD_PORT
155 * OpenSSL version numbers: MNNFFPPS: major minor fix patch status 167 debug("trying egd/prngd port %d", PRNGD_PORT);
156 * We match major, minor, fix and status (not patch) 168 if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == 0)
157 */ 169 return 0;
158 if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) 170#endif
159 fatal("OpenSSL version mismatch. Built against %lx, you " 171#ifdef PRNGD_SOCKET
160 "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); 172 debug("trying egd/prngd socket %s", PRNGD_SOCKET);
161 173 if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == 0)
162#ifndef OPENSSL_PRNG_ONLY 174 return 0;
163 original_uid = getuid();
164 original_euid = geteuid();
165#endif 175#endif
176 return -1;
166} 177}
167 178
168#ifndef OPENSSL_PRNG_ONLY
169void 179void
170rexec_send_rng_seed(Buffer *m) 180rexec_send_rng_seed(Buffer *m)
171{ 181{
@@ -191,4 +201,34 @@ rexec_recv_rng_seed(Buffer *m)
191 RAND_add(buf, len, len); 201 RAND_add(buf, len, len);
192 } 202 }
193} 203}
204#endif /* OPENSSL_PRNG_ONLY */
205
206void
207seed_rng(void)
208{
209#ifndef OPENSSL_PRNG_ONLY
210 unsigned char buf[RANDOM_SEED_SIZE];
194#endif 211#endif
212 /*
213 * OpenSSL version numbers: MNNFFPPS: major minor fix patch status
214 * We match major, minor, fix and status (not patch)
215 */
216 if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L)
217 fatal("OpenSSL version mismatch. Built against %lx, you "
218 "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
219
220#ifndef OPENSSL_PRNG_ONLY
221 if (RAND_status() == 1) {
222 debug3("RNG is ready, skipping seeding");
223 return;
224 }
225
226 if (seed_from_prngd(buf, sizeof(buf)) == -1)
227 fatal("Could not obtain seed from PRNGd");
228 RAND_add(buf, sizeof(buf), sizeof(buf));
229 memset(buf, '\0', sizeof(buf));
230
231#endif /* OPENSSL_PRNG_ONLY */
232 if (RAND_status() != 1)
233 fatal("PRNG is not seeded");
234}
diff --git a/regress/README.regress b/regress/README.regress
index da9bb6a99..82e4cc751 100644
--- a/regress/README.regress
+++ b/regress/README.regress
@@ -93,10 +93,6 @@ Failed tests can be difficult to diagnose. Suggestions:
93 93
94Known Issues. 94Known Issues.
95 95
96- If your build requires ssh-rand-helper regress tests will fail
97 unless ssh-rand-helper is in pre-installed (the path to
98 ssh-rand-helper is hard coded).
99
100- Similarly, if you do not have "scp" in your system's $PATH then the 96- Similarly, if you do not have "scp" in your system's $PATH then the
101 multiplex scp tests will fail (since the system's shell startup scripts 97 multiplex scp tests will fail (since the system's shell startup scripts
102 will determine where the shell started by sshd will look for scp). 98 will determine where the shell started by sshd will look for scp).
@@ -105,4 +101,4 @@ Known Issues.
105 test to fail. The old behaviour can be restored by setting (and 101 test to fail. The old behaviour can be restored by setting (and
106 exporting) _POSIX2_VERSION=199209 before running the tests. 102 exporting) _POSIX2_VERSION=199209 before running the tests.
107 103
108$Id: README.regress,v 1.11 2010/08/16 21:04:29 djm Exp $ 104$Id: README.regress,v 1.12 2011/05/05 03:48:42 djm Exp $
diff --git a/ssh-add.c b/ssh-add.c
index 125d6645b..94b68ac18 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -372,7 +372,6 @@ main(int argc, char **argv)
372 sanitise_stdfd(); 372 sanitise_stdfd();
373 373
374 __progname = ssh_get_progname(argv[0]); 374 __progname = ssh_get_progname(argv[0]);
375 init_rng();
376 seed_rng(); 375 seed_rng();
377 376
378 OpenSSL_add_all_algorithms(); 377 OpenSSL_add_all_algorithms();
diff --git a/ssh-agent.c b/ssh-agent.c
index afba413d7..ae204b145 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1154,7 +1154,6 @@ main(int ac, char **av)
1154 OpenSSL_add_all_algorithms(); 1154 OpenSSL_add_all_algorithms();
1155 1155
1156 __progname = ssh_get_progname(av[0]); 1156 __progname = ssh_get_progname(av[0]);
1157 init_rng();
1158 seed_rng(); 1157 seed_rng();
1159 1158
1160 while ((ch = getopt(ac, av, "cdksa:t:")) != -1) { 1159 while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
diff --git a/ssh-keygen.c b/ssh-keygen.c
index c95e4ab29..d379b1a2c 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1817,7 +1817,6 @@ main(int argc, char **argv)
1817 OpenSSL_add_all_algorithms(); 1817 OpenSSL_add_all_algorithms();
1818 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); 1818 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
1819 1819
1820 init_rng();
1821 seed_rng(); 1820 seed_rng();
1822 1821
1823 /* we need this for the home * directory. */ 1822 /* we need this for the home * directory. */
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 25d7ac66f..eb282b948 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -620,7 +620,6 @@ main(int argc, char **argv)
620 extern char *optarg; 620 extern char *optarg;
621 621
622 __progname = ssh_get_progname(argv[0]); 622 __progname = ssh_get_progname(argv[0]);
623 init_rng();
624 seed_rng(); 623 seed_rng();
625 TAILQ_INIT(&tq); 624 TAILQ_INIT(&tq);
626 625
diff --git a/ssh-keysign.c b/ssh-keysign.c
index 4172491c2..1deb7e141 100644
--- a/ssh-keysign.c
+++ b/ssh-keysign.c
@@ -178,7 +178,6 @@ main(int argc, char **argv)
178 178
179 permanently_set_uid(pw); 179 permanently_set_uid(pw);
180 180
181 init_rng();
182 seed_rng(); 181 seed_rng();
183 arc4random_stir(); 182 arc4random_stir();
184 183
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c
index 8e3f57ace..cd33515f6 100644
--- a/ssh-pkcs11-helper.c
+++ b/ssh-pkcs11-helper.c
@@ -280,7 +280,6 @@ main(int argc, char **argv)
280 TAILQ_INIT(&pkcs11_keylist); 280 TAILQ_INIT(&pkcs11_keylist);
281 pkcs11_init(0); 281 pkcs11_init(0);
282 282
283 init_rng();
284 seed_rng(); 283 seed_rng();
285 __progname = ssh_get_progname(argv[0]); 284 __progname = ssh_get_progname(argv[0]);
286 285
diff --git a/ssh-rand-helper.8 b/ssh-rand-helper.8
deleted file mode 100644
index af5a72fcb..000000000
--- a/ssh-rand-helper.8
+++ /dev/null
@@ -1,94 +0,0 @@
1.\" $Id: ssh-rand-helper.8,v 1.3 2007/01/22 01:44:53 djm Exp $
2.\"
3.\" Copyright (c) 2002 Damien Miller. All rights reserved.
4.\"
5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions
7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution.
13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24.\"
25.Dd April 14, 2002
26.Dt SSH-RAND-HELPER 8
27.Os
28.Sh NAME
29.Nm ssh-rand-helper
30.Nd random number gatherer for OpenSSH
31.Sh SYNOPSIS
32.Nm ssh-rand-hlper
33.Op Fl vxXh
34.Op Fl b Ar bytes
35.Sh DESCRIPTION
36.Nm
37is a small helper program used by
38.Xr ssh 1 ,
39.Xr ssh-add 1 ,
40.Xr ssh-agent 1 ,
41.Xr ssh-keygen 1 ,
42.Xr ssh-keyscan 1
43and
44.Xr sshd 8
45to gather random numbers of cryptographic quality if the
46.Xr openssl 4
47library has not been configured to provide them itself.
48.Pp
49Normally
50.Nm
51will generate a strong random seed and provide it to the calling
52program via standard output. If standard output is a tty,
53.Nm
54will instead print the seed in hexidecimal format unless told otherwise.
55.Pp
56.Nm
57will by default gather random numbers from the system commands listed
58in
59.Pa /etc/ssh/ssh_prng_cmds .
60The output of each of the commands listed will be hashed and used to
61generate a random seed for the calling program.
62.Nm
63will also store seed files in
64.Pa ~/.ssh/prng_seed
65between executions.
66.Pp
67Alternately,
68.Nm
69may be configured at build time to collect random numbers from a
70EGD/PRNGd server via a unix domain or localhost tcp socket.
71.Pp
72This program is not intended to be run by the end-user, so the few
73commandline options are for debugging purposes only.
74.Bl -tag -width Ds
75.It Fl b Ar bytes
76Specify the number of random bytes to include in the output.
77.It Fl x
78Output a hexidecimal instead of a binary seed.
79.It Fl X
80Force output of a binary seed, even if standard output is a tty
81.It Fl v
82Turn on debugging message. Multiple
83.Fl v
84options will increase the debugging level.
85.It Fl h
86Display a summary of options.
87.El
88.Sh AUTHORS
89Damien Miller <djm@mindrot.org>
90.Sh SEE ALSO
91.Xr ssh 1 ,
92.Xr ssh-add 1 ,
93.Xr ssh-keygen 1 ,
94.Xr sshd 8
diff --git a/ssh-rand-helper.c b/ssh-rand-helper.c
deleted file mode 100644
index fa5070499..000000000
--- a/ssh-rand-helper.c
+++ /dev/null
@@ -1,932 +0,0 @@
1/*
2 * Copyright (c) 2001-2002 Damien Miller. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
26
27#include <sys/types.h>
28#include <sys/resource.h>
29#include <sys/stat.h>
30#include <sys/wait.h>
31#include <sys/socket.h>
32
33#include <stdarg.h>
34#include <stddef.h>
35#include <string.h>
36
37#include <netinet/in.h>
38#include <arpa/inet.h>
39
40#ifdef HAVE_SYS_UN_H
41# include <sys/un.h>
42#endif
43
44#include <errno.h>
45#include <fcntl.h>
46#include <pwd.h>
47#include <signal.h>
48#include <time.h>
49#include <unistd.h>
50
51#include <openssl/rand.h>
52#include <openssl/sha.h>
53#include <openssl/crypto.h>
54
55/* SunOS 4.4.4 needs this */
56#ifdef HAVE_FLOATINGPOINT_H
57# include <floatingpoint.h>
58#endif /* HAVE_FLOATINGPOINT_H */
59
60#include "misc.h"
61#include "xmalloc.h"
62#include "atomicio.h"
63#include "pathnames.h"
64#include "log.h"
65
66/* Number of bytes we write out */
67#define OUTPUT_SEED_SIZE 48
68
69/* Length of on-disk seedfiles */
70#define SEED_FILE_SIZE 1024
71
72/* Maximum number of command-line arguments to read from file */
73#define NUM_ARGS 10
74
75/* Minimum number of usable commands to be considered sufficient */
76#define MIN_ENTROPY_SOURCES 16
77
78/* Path to on-disk seed file (relative to user's home directory */
79#ifndef SSH_PRNG_SEED_FILE
80# define SSH_PRNG_SEED_FILE _PATH_SSH_USER_DIR"/prng_seed"
81#endif
82
83/* Path to PRNG commands list */
84#ifndef SSH_PRNG_COMMAND_FILE
85# define SSH_PRNG_COMMAND_FILE SSHDIR "/ssh_prng_cmds"
86#endif
87
88extern char *__progname;
89
90#define WHITESPACE " \t\n"
91
92#ifndef RUSAGE_SELF
93# define RUSAGE_SELF 0
94#endif
95#ifndef RUSAGE_CHILDREN
96# define RUSAGE_CHILDREN 0
97#endif
98
99#if !defined(PRNGD_SOCKET) && !defined(PRNGD_PORT)
100# define USE_SEED_FILES
101#endif
102
103typedef struct {
104 /* Proportion of data that is entropy */
105 double rate;
106 /* Counter goes positive if this command times out */
107 unsigned int badness;
108 /* Increases by factor of two each timeout */
109 unsigned int sticky_badness;
110 /* Path to executable */
111 char *path;
112 /* argv to pass to executable */
113 char *args[NUM_ARGS]; /* XXX: arbitrary limit */
114 /* full command string (debug) */
115 char *cmdstring;
116} entropy_cmd_t;
117
118/* slow command timeouts (all in milliseconds) */
119/* static int entropy_timeout_default = ENTROPY_TIMEOUT_MSEC; */
120static int entropy_timeout_current = ENTROPY_TIMEOUT_MSEC;
121
122/* this is initialised from a file, by prng_read_commands() */
123static entropy_cmd_t *entropy_cmds = NULL;
124
125/* Prototypes */
126double stir_from_system(void);
127double stir_from_programs(void);
128double stir_gettimeofday(double entropy_estimate);
129double stir_clock(double entropy_estimate);
130double stir_rusage(int who, double entropy_estimate);
131double hash_command_output(entropy_cmd_t *src, unsigned char *hash);
132int get_random_bytes_prngd(unsigned char *buf, int len,
133 unsigned short tcp_port, char *socket_path);
134
135/*
136 * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon
137 * listening either on 'tcp_port', or via Unix domain socket at *
138 * 'socket_path'.
139 * Either a non-zero tcp_port or a non-null socket_path must be
140 * supplied.
141 * Returns 0 on success, -1 on error
142 */
143int
144get_random_bytes_prngd(unsigned char *buf, int len,
145 unsigned short tcp_port, char *socket_path)
146{
147 int fd, addr_len, rval, errors;
148 u_char msg[2];
149 struct sockaddr_storage addr;
150 struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
151 struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr;
152 mysig_t old_sigpipe;
153
154 /* Sanity checks */
155 if (socket_path == NULL && tcp_port == 0)
156 fatal("You must specify a port or a socket");
157 if (socket_path != NULL &&
158 strlen(socket_path) >= sizeof(addr_un->sun_path))
159 fatal("Random pool path is too long");
160 if (len <= 0 || len > 255)
161 fatal("Too many bytes (%d) to read from PRNGD", len);
162
163 memset(&addr, '\0', sizeof(addr));
164
165 if (tcp_port != 0) {
166 addr_in->sin_family = AF_INET;
167 addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
168 addr_in->sin_port = htons(tcp_port);
169 addr_len = sizeof(*addr_in);
170 } else {
171 addr_un->sun_family = AF_UNIX;
172 strlcpy(addr_un->sun_path, socket_path,
173 sizeof(addr_un->sun_path));
174 addr_len = offsetof(struct sockaddr_un, sun_path) +
175 strlen(socket_path) + 1;
176 }
177
178 old_sigpipe = mysignal(SIGPIPE, SIG_IGN);
179
180 errors = 0;
181 rval = -1;
182reopen:
183 fd = socket(addr.ss_family, SOCK_STREAM, 0);
184 if (fd == -1) {
185 error("Couldn't create socket: %s", strerror(errno));
186 goto done;
187 }
188
189 if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) {
190 if (tcp_port != 0) {
191 error("Couldn't connect to PRNGD port %d: %s",
192 tcp_port, strerror(errno));
193 } else {
194 error("Couldn't connect to PRNGD socket \"%s\": %s",
195 addr_un->sun_path, strerror(errno));
196 }
197 goto done;
198 }
199
200 /* Send blocking read request to PRNGD */
201 msg[0] = 0x02;
202 msg[1] = len;
203
204 if (atomicio(vwrite, fd, msg, sizeof(msg)) != sizeof(msg)) {
205 if (errno == EPIPE && errors < 10) {
206 close(fd);
207 errors++;
208 goto reopen;
209 }
210 error("Couldn't write to PRNGD socket: %s",
211 strerror(errno));
212 goto done;
213 }
214
215 if (atomicio(read, fd, buf, len) != (size_t)len) {
216 if (errno == EPIPE && errors < 10) {
217 close(fd);
218 errors++;
219 goto reopen;
220 }
221 error("Couldn't read from PRNGD socket: %s",
222 strerror(errno));
223 goto done;
224 }
225
226 rval = 0;
227done:
228 mysignal(SIGPIPE, old_sigpipe);
229 if (fd != -1)
230 close(fd);
231 return rval;
232}
233
234static int
235seed_from_prngd(unsigned char *buf, size_t bytes)
236{
237#ifdef PRNGD_PORT
238 debug("trying egd/prngd port %d", PRNGD_PORT);
239 if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == 0)
240 return 0;
241#endif
242#ifdef PRNGD_SOCKET
243 debug("trying egd/prngd socket %s", PRNGD_SOCKET);
244 if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == 0)
245 return 0;
246#endif
247 return -1;
248}
249
250double
251stir_gettimeofday(double entropy_estimate)
252{
253 struct timeval tv;
254
255 if (gettimeofday(&tv, NULL) == -1)
256 fatal("Couldn't gettimeofday: %s", strerror(errno));
257
258 RAND_add(&tv, sizeof(tv), entropy_estimate);
259
260 return entropy_estimate;
261}
262
263double
264stir_clock(double entropy_estimate)
265{
266#ifdef HAVE_CLOCK
267 clock_t c;
268
269 c = clock();
270 RAND_add(&c, sizeof(c), entropy_estimate);
271
272 return entropy_estimate;
273#else /* _HAVE_CLOCK */
274 return 0;
275#endif /* _HAVE_CLOCK */
276}
277
278double
279stir_rusage(int who, double entropy_estimate)
280{
281#ifdef HAVE_GETRUSAGE
282 struct rusage ru;
283
284 if (getrusage(who, &ru) == -1)
285 return 0;
286
287 RAND_add(&ru, sizeof(ru), entropy_estimate);
288
289 return entropy_estimate;
290#else /* _HAVE_GETRUSAGE */
291 return 0;
292#endif /* _HAVE_GETRUSAGE */
293}
294
295static int
296timeval_diff(struct timeval *t1, struct timeval *t2)
297{
298 int secdiff, usecdiff;
299
300 secdiff = t2->tv_sec - t1->tv_sec;
301 usecdiff = (secdiff*1000000) + (t2->tv_usec - t1->tv_usec);
302 return (int)(usecdiff / 1000);
303}
304
305double
306hash_command_output(entropy_cmd_t *src, unsigned char *hash)
307{
308 char buf[8192];
309 fd_set rdset;
310 int bytes_read, cmd_eof, error_abort, msec_elapsed, p[2];
311 int status, total_bytes_read;
312 static int devnull = -1;
313 pid_t pid;
314 SHA_CTX sha;
315 struct timeval tv_start, tv_current;
316
317 debug3("Reading output from \'%s\'", src->cmdstring);
318
319 if (devnull == -1) {
320 devnull = open("/dev/null", O_RDWR);
321 if (devnull == -1)
322 fatal("Couldn't open /dev/null: %s",
323 strerror(errno));
324 }
325
326 if (pipe(p) == -1)
327 fatal("Couldn't open pipe: %s", strerror(errno));
328
329 (void)gettimeofday(&tv_start, NULL); /* record start time */
330
331 switch (pid = fork()) {
332 case -1: /* Error */
333 close(p[0]);
334 close(p[1]);
335 fatal("Couldn't fork: %s", strerror(errno));
336 /* NOTREACHED */
337 case 0: /* Child */
338 dup2(devnull, STDIN_FILENO);
339 dup2(p[1], STDOUT_FILENO);
340 dup2(p[1], STDERR_FILENO);
341 close(p[0]);
342 close(p[1]);
343 close(devnull);
344
345 execv(src->path, (char**)(src->args));
346
347 debug("(child) Couldn't exec '%s': %s",
348 src->cmdstring, strerror(errno));
349 _exit(-1);
350 default: /* Parent */
351 break;
352 }
353
354 RAND_add(&pid, sizeof(&pid), 0.0);
355
356 close(p[1]);
357
358 /* Hash output from child */
359 SHA1_Init(&sha);
360
361 cmd_eof = error_abort = msec_elapsed = total_bytes_read = 0;
362 while (!error_abort && !cmd_eof) {
363 int ret;
364 struct timeval tv;
365 int msec_remaining;
366
367 (void) gettimeofday(&tv_current, 0);
368 msec_elapsed = timeval_diff(&tv_start, &tv_current);
369 if (msec_elapsed >= entropy_timeout_current) {
370 error_abort=1;
371 continue;
372 }
373 msec_remaining = entropy_timeout_current - msec_elapsed;
374
375 FD_ZERO(&rdset);
376 FD_SET(p[0], &rdset);
377 tv.tv_sec = msec_remaining / 1000;
378 tv.tv_usec = (msec_remaining % 1000) * 1000;
379
380 ret = select(p[0] + 1, &rdset, NULL, NULL, &tv);
381
382 RAND_add(&tv, sizeof(tv), 0.0);
383
384 switch (ret) {
385 case 0:
386 /* timer expired */
387 error_abort = 1;
388 kill(pid, SIGINT);
389 break;
390 case 1:
391 /* command input */
392 do {
393 bytes_read = read(p[0], buf, sizeof(buf));
394 } while (bytes_read == -1 && errno == EINTR);
395 RAND_add(&bytes_read, sizeof(&bytes_read), 0.0);
396 if (bytes_read == -1) {
397 error_abort = 1;
398 break;
399 } else if (bytes_read) {
400 SHA1_Update(&sha, buf, bytes_read);
401 total_bytes_read += bytes_read;
402 } else {
403 cmd_eof = 1;
404 }
405 break;
406 case -1:
407 default:
408 /* error */
409 debug("Command '%s': select() failed: %s",
410 src->cmdstring, strerror(errno));
411 error_abort = 1;
412 break;
413 }
414 }
415
416 SHA1_Final(hash, &sha);
417
418 close(p[0]);
419
420 debug3("Time elapsed: %d msec", msec_elapsed);
421
422 if (waitpid(pid, &status, 0) == -1) {
423 error("Couldn't wait for child '%s' completion: %s",
424 src->cmdstring, strerror(errno));
425 return 0.0;
426 }
427
428 RAND_add(&status, sizeof(&status), 0.0);
429
430 if (error_abort) {
431 /*
432 * Closing p[0] on timeout causes the entropy command to
433 * SIGPIPE. Take whatever output we got, and mark this
434 * command as slow
435 */
436 debug2("Command '%s' timed out", src->cmdstring);
437 src->sticky_badness *= 2;
438 src->badness = src->sticky_badness;
439 return total_bytes_read;
440 }
441
442 if (WIFEXITED(status)) {
443 if (WEXITSTATUS(status) == 0) {
444 return total_bytes_read;
445 } else {
446 debug2("Command '%s' exit status was %d",
447 src->cmdstring, WEXITSTATUS(status));
448 src->badness = src->sticky_badness = 128;
449 return 0.0;
450 }
451 } else if (WIFSIGNALED(status)) {
452 debug2("Command '%s' returned on uncaught signal %d !",
453 src->cmdstring, status);
454 src->badness = src->sticky_badness = 128;
455 return 0.0;
456 } else
457 return 0.0;
458}
459
460double
461stir_from_system(void)
462{
463 double total_entropy_estimate;
464 long int i;
465
466 total_entropy_estimate = 0;
467
468 i = getpid();
469 RAND_add(&i, sizeof(i), 0.5);
470 total_entropy_estimate += 0.1;
471
472 i = getppid();
473 RAND_add(&i, sizeof(i), 0.5);
474 total_entropy_estimate += 0.1;
475
476 i = getuid();
477 RAND_add(&i, sizeof(i), 0.0);
478 i = getgid();
479 RAND_add(&i, sizeof(i), 0.0);
480
481 total_entropy_estimate += stir_gettimeofday(1.0);
482 total_entropy_estimate += stir_clock(0.5);
483 total_entropy_estimate += stir_rusage(RUSAGE_SELF, 2.0);
484
485 return total_entropy_estimate;
486}
487
488double
489stir_from_programs(void)
490{
491 int c;
492 double entropy, total_entropy;
493 unsigned char hash[SHA_DIGEST_LENGTH];
494
495 total_entropy = 0;
496 for(c = 0; entropy_cmds[c].path != NULL; c++) {
497 if (!entropy_cmds[c].badness) {
498 /* Hash output from command */
499 entropy = hash_command_output(&entropy_cmds[c],
500 hash);
501
502 /* Scale back estimate by command's rate */
503 entropy *= entropy_cmds[c].rate;
504
505 /* Upper bound of entropy is SHA_DIGEST_LENGTH */
506 if (entropy > SHA_DIGEST_LENGTH)
507 entropy = SHA_DIGEST_LENGTH;
508
509 /* Stir it in */
510 RAND_add(hash, sizeof(hash), entropy);
511
512 debug3("Got %0.2f bytes of entropy from '%s'",
513 entropy, entropy_cmds[c].cmdstring);
514
515 total_entropy += entropy;
516
517 /* Execution time should be a bit unpredictable */
518 total_entropy += stir_gettimeofday(0.05);
519 total_entropy += stir_clock(0.05);
520 total_entropy += stir_rusage(RUSAGE_SELF, 0.1);
521 total_entropy += stir_rusage(RUSAGE_CHILDREN, 0.1);
522 } else {
523 debug2("Command '%s' disabled (badness %d)",
524 entropy_cmds[c].cmdstring,
525 entropy_cmds[c].badness);
526
527 if (entropy_cmds[c].badness > 0)
528 entropy_cmds[c].badness--;
529 }
530 }
531
532 return total_entropy;
533}
534
535/*
536 * prng seedfile functions
537 */
538int
539prng_check_seedfile(char *filename)
540{
541 struct stat st;
542
543 /*
544 * XXX raceable: eg replace seed between this stat and subsequent
545 * open. Not such a problem because we don't really trust the
546 * seed file anyway.
547 * XXX: use secure path checking as elsewhere in OpenSSH
548 */
549 if (lstat(filename, &st) == -1) {
550 /* Give up on hard errors */
551 if (errno != ENOENT)
552 debug("WARNING: Couldn't stat random seed file "
553 "\"%.100s\": %s", filename, strerror(errno));
554 return 0;
555 }
556
557 /* regular file? */
558 if (!S_ISREG(st.st_mode))
559 fatal("PRNG seedfile %.100s is not a regular file",
560 filename);
561
562 /* mode 0600, owned by root or the current user? */
563 if (((st.st_mode & 0177) != 0) || !(st.st_uid == getuid())) {
564 debug("WARNING: PRNG seedfile %.100s must be mode 0600, "
565 "owned by uid %li", filename, (long int)getuid());
566 return 0;
567 }
568
569 return 1;
570}
571
572void
573prng_write_seedfile(void)
574{
575 int fd, save_errno;
576 unsigned char seed[SEED_FILE_SIZE];
577 char filename[MAXPATHLEN], tmpseed[MAXPATHLEN];
578 struct passwd *pw;
579 mode_t old_umask;
580
581 pw = getpwuid(getuid());
582 if (pw == NULL)
583 fatal("Couldn't get password entry for current user "
584 "(%li): %s", (long int)getuid(), strerror(errno));
585
586 /* Try to ensure that the parent directory is there */
587 snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir,
588 _PATH_SSH_USER_DIR);
589 if (mkdir(filename, 0700) < 0 && errno != EEXIST)
590 fatal("mkdir %.200s: %s", filename, strerror(errno));
591
592 snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir,
593 SSH_PRNG_SEED_FILE);
594
595 strlcpy(tmpseed, filename, sizeof(tmpseed));
596 if (strlcat(tmpseed, ".XXXXXXXXXX", sizeof(tmpseed)) >=
597 sizeof(tmpseed))
598 fatal("PRNG seed filename too long");
599
600 if (RAND_bytes(seed, sizeof(seed)) <= 0)
601 fatal("PRNG seed extraction failed");
602
603 /* Don't care if the seed doesn't exist */
604 prng_check_seedfile(filename);
605
606 old_umask = umask(0177);
607
608 if ((fd = mkstemp(tmpseed)) == -1) {
609 debug("WARNING: couldn't make temporary PRNG seedfile %.100s "
610 "(%.100s)", tmpseed, strerror(errno));
611 } else {
612 debug("writing PRNG seed to file %.100s", tmpseed);
613 if (atomicio(vwrite, fd, &seed, sizeof(seed)) < sizeof(seed)) {
614 save_errno = errno;
615 close(fd);
616 unlink(tmpseed);
617 fatal("problem writing PRNG seedfile %.100s "
618 "(%.100s)", filename, strerror(save_errno));
619 }
620 close(fd);
621 debug("moving temporary PRNG seed to file %.100s", filename);
622 if (rename(tmpseed, filename) == -1) {
623 save_errno = errno;
624 unlink(tmpseed);
625 fatal("problem renaming PRNG seedfile from %.100s "
626 "to %.100s (%.100s)", tmpseed, filename,
627 strerror(save_errno));
628 }
629 }
630 umask(old_umask);
631}
632
633void
634prng_read_seedfile(void)
635{
636 int fd;
637 char seed[SEED_FILE_SIZE], filename[MAXPATHLEN];
638 struct passwd *pw;
639
640 pw = getpwuid(getuid());
641 if (pw == NULL)
642 fatal("Couldn't get password entry for current user "
643 "(%li): %s", (long int)getuid(), strerror(errno));
644
645 snprintf(filename, sizeof(filename), "%.512s/%s", pw->pw_dir,
646 SSH_PRNG_SEED_FILE);
647
648 debug("loading PRNG seed from file %.100s", filename);
649
650 if (!prng_check_seedfile(filename)) {
651 verbose("Random seed file not found or invalid, ignoring.");
652 return;
653 }
654
655 /* open the file and read in the seed */
656 fd = open(filename, O_RDONLY);
657 if (fd == -1)
658 fatal("could not open PRNG seedfile %.100s (%.100s)",
659 filename, strerror(errno));
660
661 if (atomicio(read, fd, &seed, sizeof(seed)) < sizeof(seed)) {
662 verbose("invalid or short read from PRNG seedfile "
663 "%.100s - ignoring", filename);
664 memset(seed, '\0', sizeof(seed));
665 }
666 close(fd);
667
668 /* stir in the seed, with estimated entropy zero */
669 RAND_add(&seed, sizeof(seed), 0.0);
670}
671
672
673/*
674 * entropy command initialisation functions
675 */
676int
677prng_read_commands(char *cmdfilename)
678{
679 char cmd[SEED_FILE_SIZE], *cp, line[1024], path[SEED_FILE_SIZE];
680 double est;
681 entropy_cmd_t *entcmd;
682 FILE *f;
683 int cur_cmd, linenum, num_cmds, arg;
684
685 if ((f = fopen(cmdfilename, "r")) == NULL) {
686 fatal("couldn't read entropy commands file %.100s: %.100s",
687 cmdfilename, strerror(errno));
688 }
689
690 num_cmds = 64;
691 entcmd = xcalloc(num_cmds, sizeof(entropy_cmd_t));
692
693 /* Read in file */
694 cur_cmd = linenum = 0;
695 while (fgets(line, sizeof(line), f)) {
696 linenum++;
697
698 /* Skip leading whitespace, blank lines and comments */
699 cp = line + strspn(line, WHITESPACE);
700 if ((*cp == 0) || (*cp == '#'))
701 continue; /* done with this line */
702
703 /*
704 * The first non-whitespace char should be a double quote
705 * delimiting the commandline
706 */
707 if (*cp != '"') {
708 error("bad entropy command, %.100s line %d",
709 cmdfilename, linenum);
710 continue;
711 }
712
713 /*
714 * First token, command args (incl. argv[0]) in double
715 * quotes
716 */
717 cp = strtok(cp, "\"");
718 if (cp == NULL) {
719 error("missing or bad command string, %.100s "
720 "line %d -- ignored", cmdfilename, linenum);
721 continue;
722 }
723 strlcpy(cmd, cp, sizeof(cmd));
724
725 /* Second token, full command path */
726 if ((cp = strtok(NULL, WHITESPACE)) == NULL) {
727 error("missing command path, %.100s "
728 "line %d -- ignored", cmdfilename, linenum);
729 continue;
730 }
731
732 /* Did configure mark this as dead? */
733 if (strncmp("undef", cp, 5) == 0)
734 continue;
735
736 strlcpy(path, cp, sizeof(path));
737
738 /* Third token, entropy rate estimate for this command */
739 if ((cp = strtok(NULL, WHITESPACE)) == NULL) {
740 error("missing entropy estimate, %.100s "
741 "line %d -- ignored", cmdfilename, linenum);
742 continue;
743 }
744 est = strtod(cp, NULL);
745
746 /* end of line */
747 if ((cp = strtok(NULL, WHITESPACE)) != NULL) {
748 error("garbage at end of line %d in %.100s "
749 "-- ignored", linenum, cmdfilename);
750 continue;
751 }
752
753 /* save the command for debug messages */
754 entcmd[cur_cmd].cmdstring = xstrdup(cmd);
755
756 /* split the command args */
757 cp = strtok(cmd, WHITESPACE);
758 arg = 0;
759 do {
760 entcmd[cur_cmd].args[arg] = xstrdup(cp);
761 arg++;
762 } while(arg < NUM_ARGS && (cp = strtok(NULL, WHITESPACE)));
763
764 if (strtok(NULL, WHITESPACE))
765 error("ignored extra commands (max %d), %.100s "
766 "line %d", NUM_ARGS, cmdfilename, linenum);
767
768 /* Copy the command path and rate estimate */
769 entcmd[cur_cmd].path = xstrdup(path);
770 entcmd[cur_cmd].rate = est;
771
772 /* Initialise other values */
773 entcmd[cur_cmd].sticky_badness = 1;
774
775 cur_cmd++;
776
777 /*
778 * If we've filled the array, reallocate it twice the size
779 * Do this now because even if this we're on the last
780 * command we need another slot to mark the last entry
781 */
782 if (cur_cmd == num_cmds) {
783 num_cmds *= 2;
784 entcmd = xrealloc(entcmd, num_cmds,
785 sizeof(entropy_cmd_t));
786 }
787 }
788
789 /* zero the last entry */
790 memset(&entcmd[cur_cmd], '\0', sizeof(entropy_cmd_t));
791
792 /* trim to size */
793 entropy_cmds = xrealloc(entcmd, (cur_cmd + 1),
794 sizeof(entropy_cmd_t));
795
796 debug("Loaded %d entropy commands from %.100s", cur_cmd,
797 cmdfilename);
798
799 fclose(f);
800 return cur_cmd < MIN_ENTROPY_SOURCES ? -1 : 0;
801}
802
803void
804usage(void)
805{
806 fprintf(stderr, "Usage: %s [options]\n", __progname);
807 fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
808 fprintf(stderr, " Multiple -v increases verbosity.\n");
809 fprintf(stderr, " -x Force output in hexadecimal (for debugging)\n");
810 fprintf(stderr, " -X Force output in binary\n");
811 fprintf(stderr, " -b bytes Number of bytes to output (default %d)\n",
812 OUTPUT_SEED_SIZE);
813}
814
815int
816main(int argc, char **argv)
817{
818 unsigned char *buf;
819 int ret, ch, debug_level, output_hex, bytes;
820 extern char *optarg;
821 extern int optind;
822 LogLevel ll;
823
824 __progname = ssh_get_progname(argv[0]);
825 log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
826
827 ll = SYSLOG_LEVEL_INFO;
828 debug_level = output_hex = 0;
829 bytes = OUTPUT_SEED_SIZE;
830
831 /* Don't write binary data to a tty, unless we are forced to */
832 if (isatty(STDOUT_FILENO))
833 output_hex = 1;
834
835 while ((ch = getopt(argc, argv, "vxXhb:")) != -1) {
836 switch (ch) {
837 case 'v':
838 if (debug_level < 3)
839 ll = SYSLOG_LEVEL_DEBUG1 + debug_level++;
840 break;
841 case 'x':
842 output_hex = 1;
843 break;
844 case 'X':
845 output_hex = 0;
846 break;
847 case 'b':
848 if ((bytes = atoi(optarg)) <= 0)
849 fatal("Invalid number of output bytes");
850 break;
851 case 'h':
852 usage();
853 exit(0);
854 default:
855 error("Invalid commandline option");
856 usage();
857 exit(1);
858 }
859 }
860 log_init(argv[0], ll, SYSLOG_FACILITY_USER, 1);
861
862 if (argc != optind) {
863 error("Unexpected commandline arguments.");
864 usage();
865 exit(1);
866 }
867
868#ifdef USE_SEED_FILES
869 prng_read_seedfile();
870#endif
871
872 buf = xmalloc(bytes);
873
874 /*
875 * Seed the RNG from wherever we can
876 */
877
878 /* Take whatever is on the stack, but don't credit it */
879 RAND_add(buf, bytes, 0);
880
881 debug("Seeded RNG with %i bytes from system calls",
882 (int)stir_from_system());
883
884 /* try prngd, fall back to commands if prngd fails or not configured */
885 if (seed_from_prngd(buf, bytes) == 0) {
886 RAND_add(buf, bytes, bytes);
887 } else {
888 /* Read in collection commands */
889 if (prng_read_commands(SSH_PRNG_COMMAND_FILE) == -1)
890 fatal("PRNG initialisation failed -- exiting.");
891 debug("Seeded RNG with %i bytes from programs",
892 (int)stir_from_programs());
893 }
894
895#ifdef USE_SEED_FILES
896 prng_write_seedfile();
897#endif
898
899 /*
900 * Write the seed to stdout
901 */
902
903 if (!RAND_status())
904 fatal("Not enough entropy in RNG");
905
906 if (RAND_bytes(buf, bytes) <= 0)
907 fatal("Couldn't extract entropy from PRNG");
908
909 if (output_hex) {
910 for(ret = 0; ret < bytes; ret++)
911 printf("%02x", (unsigned char)(buf[ret]));
912 printf("\n");
913 } else
914 ret = atomicio(vwrite, STDOUT_FILENO, buf, bytes);
915
916 memset(buf, '\0', bytes);
917 xfree(buf);
918
919 return ret == bytes ? 0 : 1;
920}
921
922/*
923 * We may attempt to re-seed during mkstemp if we are using the one in the
924 * compat library (via mkstemp -> _gettemp -> arc4random -> seed_rng) so we
925 * need our own seed_rng(). We must also check that we have enough entropy.
926 */
927void
928seed_rng(void)
929{
930 if (!RAND_status())
931 fatal("Not enough entropy in RNG");
932}
diff --git a/ssh.c b/ssh.c
index d32ef78b0..b543c6117 100644
--- a/ssh.c
+++ b/ssh.c
@@ -234,7 +234,6 @@ main(int ac, char **av)
234 sanitise_stdfd(); 234 sanitise_stdfd();
235 235
236 __progname = ssh_get_progname(av[0]); 236 __progname = ssh_get_progname(av[0]);
237 init_rng();
238 237
239 /* 238 /*
240 * Discard other fds that are hanging around. These can cause problem 239 * Discard other fds that are hanging around. These can cause problem
diff --git a/ssh_prng_cmds.in b/ssh_prng_cmds.in
deleted file mode 100644
index 0d29d49f1..000000000
--- a/ssh_prng_cmds.in
+++ /dev/null
@@ -1,75 +0,0 @@
1# entropy gathering commands
2
3# Format is: "program-name args" path rate
4
5# The "rate" represents the number of bits of usuable entropy per
6# byte of command output. Be conservative.
7#
8# $Id: ssh_prng_cmds.in,v 1.9 2003/11/21 12:48:56 djm Exp $
9
10"ls -alni /var/log" @PROG_LS@ 0.02
11"ls -alni /var/adm" @PROG_LS@ 0.02
12"ls -alni /usr/adm" @PROG_LS@ 0.02
13"ls -alni /var/mail" @PROG_LS@ 0.02
14"ls -alni /usr/mail" @PROG_LS@ 0.02
15"ls -alni /var/adm/syslog" @PROG_LS@ 0.02
16"ls -alni /usr/adm/syslog" @PROG_LS@ 0.02
17"ls -alni /var/spool/mail" @PROG_LS@ 0.02
18"ls -alni /proc" @PROG_LS@ 0.02
19"ls -alni /tmp" @PROG_LS@ 0.02
20"ls -alni /var/tmp" @PROG_LS@ 0.02
21"ls -alni /usr/tmp" @PROG_LS@ 0.02
22"ls -alTi /var/log" @PROG_LS@ 0.02
23"ls -alTi /var/adm" @PROG_LS@ 0.02
24"ls -alTi /var/mail" @PROG_LS@ 0.02
25"ls -alTi /var/adm/syslog" @PROG_LS@ 0.02
26"ls -alTi /var/spool/mail" @PROG_LS@ 0.02
27"ls -alTi /proc" @PROG_LS@ 0.02
28"ls -alTi /tmp" @PROG_LS@ 0.02
29"ls -alTi /var/tmp" @PROG_LS@ 0.02
30"ls -alTi /usr/tmp" @PROG_LS@ 0.02
31
32"netstat -an" @PROG_NETSTAT@ 0.05
33"netstat -in" @PROG_NETSTAT@ 0.05
34"netstat -rn" @PROG_NETSTAT@ 0.02
35"netstat -pn" @PROG_NETSTAT@ 0.02
36"netstat -ia" @PROG_NETSTAT@ 0.05
37"netstat -s" @PROG_NETSTAT@ 0.02
38"netstat -is" @PROG_NETSTAT@ 0.07
39
40"arp -n -a" @PROG_ARP@ 0.02
41
42"ifconfig -a" @PROG_IFCONFIG@ 0.02
43
44"ps laxww" @PROG_PS@ 0.03
45"ps -al" @PROG_PS@ 0.03
46"ps -efl" @PROG_PS@ 0.03
47"jstat" @PROG_JSTAT@ 0.07
48
49"w" @PROG_W@ 0.05
50
51"who -i" @PROG_WHO@ 0.01
52
53"last" @PROG_LAST@ 0.01
54
55"lastlog" @PROG_LASTLOG@ 0.01
56
57"df" @PROG_DF@ 0.01
58"df -i" @PROG_DF@ 0.01
59
60"sar -d" @PROG_SAR@ 0.04
61
62"vmstat" @PROG_VMSTAT@ 0.01
63"uptime" @PROG_UPTIME@ 0.01
64
65"ipcs -a" @PROG_IPCS@ 0.01
66
67"tail -200 /var/log/messages" @PROG_TAIL@ 0.01
68"tail -200 /var/log/syslog" @PROG_TAIL@ 0.01
69"tail -200 /var/adm/messages" @PROG_TAIL@ 0.01
70"tail -200 /var/adm/syslog" @PROG_TAIL@ 0.01
71"tail -200 /var/adm/syslog/syslog.log" @PROG_TAIL@ 0.01
72"tail -200 /var/log/maillog" @PROG_TAIL@ 0.01
73"tail -200 /var/adm/maillog" @PROG_TAIL@ 0.01
74"tail -200 /var/adm/syslog/mail.log" @PROG_TAIL@ 0.01
75
diff --git a/sshd.c b/sshd.c
index cb45cecbd..8f65858c9 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1306,7 +1306,6 @@ main(int ac, char **av)
1306 (void)set_auth_parameters(ac, av); 1306 (void)set_auth_parameters(ac, av);
1307#endif 1307#endif
1308 __progname = ssh_get_progname(av[0]); 1308 __progname = ssh_get_progname(av[0]);
1309 init_rng();
1310 1309
1311 /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ 1310 /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
1312 saved_argc = ac; 1311 saved_argc = ac;