- Created contrib/ subdirectory. Included helpers from Phil Hands'
   Debian package, README file and chroot patch from Ricardo Cerqueira
   <rmcc@clix.pt>
 - Moved gnome-ssh-askpass.c to contrib directory and reomved config
   option.
 - Slight cleanup to doc files
diff --git a/ChangeLog b/ChangeLog
index 7d28776..ddb4cba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,12 @@
    problems with gcc/Solaris.
  - Don't free argument to putenv() after use (in setenv() replacement). 
    Report from Seigo Tanimura <tanimura@r.dl.itc.u-tokyo.ac.jp>
+ - Created contrib/ subdirectory. Included helpers from Phil Hands' 
+   Debian package, README file and chroot patch from Ricardo Cerqueira
+   <rmcc@clix.pt>
+ - Moved gnome-ssh-askpass.c to contrib directory and reomved config 
+   option.
+ - Slight cleanup to doc files
 
 20000314
  - Include macro for IN6_IS_ADDR_V4MAPPED. Report from 
diff --git a/INSTALL b/INSTALL
index 4c1c0f8..d7d6d4e 100644
--- a/INSTALL
+++ b/INSTALL
@@ -15,12 +15,6 @@
 PAM:
 http://www.kernel.org/pub/linux/libs/pam/
 
-Dante:
-http://www.inet.no/dante
-
-OpenSSH can also use the Dante SOCKS libraries, version 1.1.1pre1 or higher,
-if you have them installed on your system. 
-
 If you wish to build the GNOME passphrase requester, you will need the GNOME
 libraries and headers.
 
@@ -145,10 +139,6 @@
 
 --with-xauth=PATH specifies the location of the xauth binary
 
---with-dante[=DIR] will enable Dante SOCKS library support. If the Dante
-libsocks library isn't installed in a library searched by the compiler,
-add the directory name as the option.
-
 --with-ipv4-default instructs OpenSSH to use IPv4 by default for new
 connections. Normally OpenSSH will try attempt to lookup both IPv6 and
 IPv4 addresses. On Linux/glibc-2.1.2 this causes long delays in name
diff --git a/Makefile.in b/Makefile.in
index b406d5f..a55af98 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -21,7 +21,6 @@
 CC=@CC@
 PATHS=-DETCDIR=\"$(sysconfdir)\" -DSSH_PROGRAM=\"$(SSH_PROGRAM)\" -DSSH_ASKPASS_DEFAULT=\"$(ASKPASS_PROGRAM)\"
 CFLAGS=@CFLAGS@ $(PATHS) @DEFS@
-EXTRA_TARGETS=@GNOME_ASKPASS@
 LIBS=@LIBS@
 AR=@AR@
 RANLIB=@RANLIB@
@@ -29,9 +28,6 @@
 PERL=@PERL@
 LDFLAGS=-L. @LDFLAGS@
 
-GNOME_CFLAGS=`gnome-config --cflags gnome gnomeui`
-GNOME_LIBS=`gnome-config --libs gnome gnomeui`
-
 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-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 fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.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 
@@ -76,9 +72,6 @@
 ssh-keygen: libssh.a ssh-keygen.o log-client.o
 	$(CC) -o $@ ssh-keygen.o log-client.o $(LDFLAGS) -lssh $(LIBS) 
 
-gnome-ssh-askpass: gnome-ssh-askpass.c
-	$(CC) $(CFLAGS) $(GNOME_CFLAGS) -o $@ gnome-ssh-askpass.c $(GNOME_LIBS)
-
 $(MANPAGES) $(CONFIGFILES)::
 	$(FIXPATHSCMD) $(srcdir)/$@
 
@@ -124,12 +117,6 @@
 	-rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
 	ln -s ssh.1 $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
 
-	if [ ! -z "@GNOME_ASKPASS@" ] ; then \
-		$(INSTALL) -d $(DESTDIR)$(libexecdir) ; \
-		$(INSTALL) -d $(DESTDIR)$(libexecdir)/ssh ; \
-		$(INSTALL) -s @GNOME_ASKPASS@ $(DESTDIR)${ASKPASS_LOCATION} ; \
-	fi
-
 	if [ ! -f $(DESTDIR)$(sysconfdir)/ssh_config -a ! -f $(DESTDIR)$(sysconfdir)/sshd_config ]; then \
 		$(INSTALL) -d $(DESTDIR)$(sysconfdir); \
 		$(INSTALL) -m 644 ssh_config.out $(DESTDIR)$(sysconfdir)/ssh_config; \
diff --git a/configure.in b/configure.in
index c643d9e..7f7326f 100644
--- a/configure.in
+++ b/configure.in
@@ -577,25 +577,6 @@
 
 # Options from here on. Some of these are preset by platform above
 
-# Check whether user wants GNOME ssh-askpass
-AC_MSG_CHECKING([whether to build GNOME ssh-askpass])
-AC_ARG_WITH(gnome-askpass,
-	[  --with-gnome-askpass    Build the GNOME passphrase requester (default=no)],
-	[
-		if test "x$withval" = "xno" ; then
-			GNOME_ASKPASS="";
-		else
-			GNOME_ASKPASS="gnome-ssh-askpass";
-		fi
-	])
-AC_SUBST(GNOME_ASKPASS)
-
-if test -z "$GNOME_ASKPASS" ; then
-	AC_MSG_RESULT(no)
-else
-	AC_MSG_RESULT(yes)
-fi
-
 # Check for user-specified random device, otherwise check /dev/urandom
 AC_ARG_WITH(random,
 	[  --with-random=FILE      read randomness from FILE (default=/dev/urandom)],
diff --git a/contrib/README b/contrib/README
new file mode 100644
index 0000000..fda244f
--- /dev/null
+++ b/contrib/README
@@ -0,0 +1,49 @@
+Other patches and addons for OpenSSH. Please send submissions to 
+djm@ibs.com.au
+
+In this directory
+-----------------
+
+chroot.diff:
+
+Ricardo Cerqueira's <rmcc@clix.pt> patch to enable chrooting using the
+wu-ftpd style magic home directories (containing '/./'). More details in
+the head of the patch itself.
+
+make-ssh-known-hosts:
+
+Tero Kivinen's <Tero.Kivinen@hut.fi> PERL script to generate
+ssh_known_hosts files by trawling tjhrough the DNS. More details in the
+manpage.
+
+ssh-copy-id:
+
+Phil Hands' <phil@hands.com> shell script to automate the process of adding
+your public key to a remote machine's ~/.ssh/authorized_keys file.
+
+gnome-ssh-askpass:
+
+A GNOME passphrase requester of my own creation. Compilation instructions
+are in the top of the file.
+
+Externally maintained
+---------------------
+
+liblogin:
+
+liblogin is Andre Lucas' cross platform login library. It handles all the 
+yucky details of wtmp, utmp and lastlog (which every OS vendor has
+seen fit to implement differently) in one clean library.
+
+OpenSSH will require liblogin in the near future, but for now it is 
+recommended for users with login logging problems or curiosity.
+
+http://dspace.dial.pipex.com/andre.lucas/liblogin.html
+
+X11 SSH Askpass:
+
+Jim Knoble <jmknoble@pobox.com> has written an excellent X11
+passphrase requester. This is highly recommended:
+
+http://www.ntrnet.net/~jmknoble/software/x11-ssh-askpass/index.html
+
diff --git a/contrib/chroot.diff b/contrib/chroot.diff
new file mode 100644
index 0000000..850bd8f
--- /dev/null
+++ b/contrib/chroot.diff
@@ -0,0 +1,134 @@
+From: Ricardo Cerqueira <rmcc@clix.pt>
+
+A patch to cause sshd to chroot when it encounters the magic token
+'/./' in a users home directory. The directory portion before the
+token is the directory to chroot() to, the portion after the
+token is the user's home directory relative to the new root.
+
+
+
+diff -ruN openssh-1.2.3pre2-orig/acconfig.h openssh-1.2.3pre2/acconfig.h
+--- openssh-1.2.3pre2-orig/acconfig.h	Sat Mar 11 20:45:40 2000
++++ openssh-1.2.3pre2/acconfig.h	Wed Mar 15 11:44:33 2000
+@@ -159,6 +159,9 @@
+ /* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
+ #undef IPV4_IN_IPV6
+ 
++/* Define if you want to enable chrooted users */
++#undef CHROOT
++
+ @BOTTOM@
+ 
+ /* ******************* Shouldn't need to edit below this line ************** */
+diff -ruN openssh-1.2.3pre2-orig/config.h.in openssh-1.2.3pre2/config.h.in
+--- openssh-1.2.3pre2-orig/config.h.in	Wed Mar 15 11:51:02 2000
++++ openssh-1.2.3pre2/config.h.in	Wed Mar 15 11:46:33 2000
+@@ -140,6 +140,9 @@
+ /* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
+ #undef IPV4_IN_IPV6
+ 
++/* Define if you want to enable chrooted users */
++#undef CHROOT
++
+ /* The number of bytes in a char.  */
+ #undef SIZEOF_CHAR
+ 
+diff -ruN openssh-1.2.3pre2-orig/configure openssh-1.2.3pre2/configure
+--- openssh-1.2.3pre2-orig/configure	Wed Mar 15 11:51:03 2000
++++ openssh-1.2.3pre2/configure	Wed Mar 15 11:46:34 2000
+@@ -52,6 +52,8 @@
+ ac_help="$ac_help
+   --with-4in6             Check for and convert IPv4 in IPv6 mapped addresses"
+ ac_help="$ac_help
++  --with-chroot           Enable chroot using /./ directory token"
++ac_help="$ac_help
+   --with-pid-dir=PATH     Specify location of ssh.pid file"
+ 
+ # Initialize some variables set by options.
+@@ -3605,6 +3607,22 @@
+ 
+ 		else
+ 			echo "$ac_t""no (default)" 1>&6
++		fi
++	
++
++fi
++
++
++# Whether to enable the magic chroot token
++# Check whether --with-chroot or --without-chroot was given.
++if test "${with_chroot+set}" = set; then
++  withval="$with_chroot"
++  
++		if test "x$withval" != "xno" ; then	
++			cat >> confdefs.h <<\EOF
++#define CHROOT 1
++EOF
++
+ 		fi
+ 	
+ 
+diff -ruN openssh-1.2.3pre2-orig/configure.in openssh-1.2.3pre2/configure.in
+--- openssh-1.2.3pre2-orig/configure.in	Sat Mar 11 20:45:41 2000
++++ openssh-1.2.3pre2/configure.in	Wed Mar 15 11:46:04 2000
+@@ -810,6 +810,16 @@
+ 	]
+ )
+ 
++# Whether to enable the magic chroot token
++AC_ARG_WITH(chroot,
++	[  --with-chroot           Enable chroot using /./ directory token],
++	[
++		if test "x$withval" != "xno" ; then	
++			AC_DEFINE(CHROOT)
++		fi
++	]
++)
++
+ # Where to place sshd.pid
+ piddir=/var/run
+ AC_ARG_WITH(pid-dir,
+diff -ruN openssh-1.2.3pre2-orig/sshd.c openssh-1.2.3pre2/sshd.c
+--- openssh-1.2.3pre2-orig/sshd.c	Sat Mar 11 11:58:29 2000
++++ openssh-1.2.3pre2/sshd.c	Wed Mar 15 11:43:38 2000
+@@ -2365,6 +2365,10 @@
+ 	extern char **environ;
+ 	struct stat st;
+ 	char *argv[10];
++#ifdef CHROOT /* patch by rmcc */
++        char *user_dir;
++        char *new_root;
++#endif /* CHROOT */
+ 
+ #ifndef USE_PAM /* pam_nologin handles this */
+ 	/* Check /etc/nologin. */
+@@ -2422,6 +2426,29 @@
+ 		krb_afslog(0, 0);
+ 	}
+ #endif /* AFS */
++
++#ifdef CHROOT /* patch by rmcc */
++
++        user_dir = xstrdup(pw->pw_dir);
++        new_root = user_dir;                                  
++
++        while((new_root = strchr(new_root, '.')) != NULL){
++          new_root--;
++          if(strncmp(new_root, "/./", 3) == 0){
++            *new_root = 0;
++            new_root += 2;
++            if(chroot(user_dir) != 0){
++              printf("Couldn't chroot!\n");
++              exit(1);
++            }
++            pw->pw_dir = new_root;
++            break;
++          }
++          new_root +=2;
++        }
++
++
++#endif /* CHROOT */
+ 
+ 	/* Initialize the environment. */
+ 	envsize = 100;
diff --git a/gnome-ssh-askpass.c b/contrib/gnome-ssh-askpass.c
similarity index 95%
rename from gnome-ssh-askpass.c
rename to contrib/gnome-ssh-askpass.c
index 97e9cc3..fd537e6 100644
--- a/gnome-ssh-askpass.c
+++ b/contrib/gnome-ssh-askpass.c
@@ -1,4 +1,13 @@
 /*
+   Compile with:
+
+   cc `gnome-config --cflags gnome gnomeui` \
+     gnome-ssh-askpass.c -o gnome-ssh-askpass \
+     `gnome-config --libs gnome gnomeui`
+
+*/
+
+/*
 **
 ** GNOME ssh passphrase requestor
 **
diff --git a/contrib/make-ssh-known-hosts.1 b/contrib/make-ssh-known-hosts.1
new file mode 100644
index 0000000..cf0d52f
--- /dev/null
+++ b/contrib/make-ssh-known-hosts.1
@@ -0,0 +1,432 @@
+.\" -*- nroff -*-
+.\" ----------------------------------------------------------------------
+.\" make-ssh-known-hosts.1 -- Make ssh-known-hosts file
+.\" Copyright (c) 1995 Tero Kivinen
+.\" All Rights Reserved.
+.\"
+.\" Make-ssh-known-hosts is distributed in the hope that it will be
+.\" useful, but WITHOUT ANY WARRANTY.  No author or distributor accepts
+.\" responsibility to anyone for the consequences of using it or for
+.\" whether it serves any particular purpose or works at all, unless he
+.\" says so in writing.  Refer to the General Public License for full
+.\" details.
+.\"
+.\" Everyone is granted permission to copy, modify and redistribute
+.\" make-ssh-known-hosts, but only under the conditions described in
+.\" the General Public License.  A copy of this license is supposed to
+.\" have been given to you along with make-ssh-known-hosts so you can
+.\" know your rights and responsibilities.  It should be in a file named
+.\" COPYING.  Among other things, the copyright notice and this notice
+.\" must be preserved on all copies.
+.\" ----------------------------------------------------------------------
+.\"       Program: make-ssh-known-hosts.1
+.\"	  $Source: /var/cvs/openssh/contrib/Attic/make-ssh-known-hosts.1,v $
+.\"	  Author : $Author: damien $
+.\"
+.\"	  (C) Tero Kivinen 1995 <Tero.Kivinen@hut.fi>
+.\"
+.\"	  Creation          : 03:51 Jun 28 1995 kivinen
+.\"	  Last Modification : 03:44 Jun 28 1995 kivinen
+.\"	  Last check in     : $Date: 2000/03/15 01:13:03 $
+.\"	  Revision number   : $Revision: 1.1 $
+.\"	  State             : $State: Exp $
+.\"	  Version	    : 1.1
+.\"
+.\"	  Description       : Manual page for make-ssh-known-hosts.pl
+.\"
+.\"	  $Log: make-ssh-known-hosts.1,v $
+.\"	  Revision 1.1  2000/03/15 01:13:03  damien
+.\"	   - Created contrib/ subdirectory. Included helpers from Phil Hands'
+.\"	     Debian package, README file and chroot patch from Ricardo Cerqueira
+.\"	     <rmcc@clix.pt>
+.\"	   - Moved gnome-ssh-askpass.c to contrib directory and reomved config
+.\"	     option.
+.\"	   - Slight cleanup to doc files
+.\"	
+.\"	  Revision 1.4  1998/07/08 00:40:14  kivinen
+.\"	  	Changed to do similar commercial #ifdef processing than other
+.\"	  	files.
+.\"
+.\"	  Revision 1.3  1998/06/11 00:07:21  kivinen
+.\"	  	Fixed comment characters.
+.\"
+.\" Revision 1.2  1997/04/27  21:48:28  kivinen
+.\" 	Added F-SECURE stuff.
+.\"
+.\"	  Revision 1.1.1.1  1996/02/18 21:38:13  ylo
+.\"	  	Imported ssh-1.2.13.
+.\"
+.\" Revision 1.5  1995/10/02  01:23:23  ylo
+.\" 	Make substitutions by configure.
+.\"
+.\" Revision 1.4  1995/08/31  09:21:35  ylo
+.\" 	Minor cleanup.
+.\"
+.\" Revision 1.3  1995/08/29  22:37:10  ylo
+.\" 	Minor cleanup.
+.\"
+.\" Revision 1.2  1995/07/15  13:26:11  ylo
+.\" 	Changes from kivinen.
+.\"
+.\" Revision 1.1.1.1  1995/07/12  22:41:05  ylo
+.\" Imported ssh-1.0.0.
+.\"
+.\"
+.\"
+.\" If you have any useful modifications or extensions please send them to
+.\" Tero.Kivinen@hut.fi
+.\"
+.\"
+.\"
+.\"
+.\"
+.\" #ifndef F_SECURE_COMMERCIAL
+.TH MAKE-SSH-KNOWN-HOSTS 1 "November 8, 1995" "SSH TOOLS" "SSH TOOLS"
+.\" #endif F_SECURE_COMMERCIAL
+.SH NAME
+make-ssh-known-hosts \- make ssh_known_hosts file from DNS data
+.SH SYNOPSIS
+.na
+.TP
+.B make-ssh-known-hosts
+.RB "[\|" "\-\-initialdns "\c
+.I initial_dns\c
+\|]
+.br
+.RB "[\|" "\-\-server "\c
+.I domain_name_server\c
+\|]
+.br
+.RB "[\|" "\-\-subdomains "\c
+.I comma_separated_list_of_subdomains\c
+\|]
+.br
+.RB "[\|" "\-\-debug "\c
+.I debug_level\c
+\|]
+.br
+.RB "[\|" "\-\-timeout "\c
+.I ssh_exec_timeout\c
+\|]
+.br
+.RB "[\|" "\-\-pingtimeout "\c
+.I ping_timeout\c
+\|]
+.br
+.RB "[\|" "\-\-passwordtimeout "\c
+.I timeout_when_asking_password\c
+\|]
+.br
+.RB "[\|" "\-\-notrustdaemon" "\|]"
+.br
+.RB "[\|" "\-\-norecursive" "\|]"
+.br
+.RB "[\|" "\-\-domainnamesplit" "\|]"
+.br
+.RB "[\|" "\-\-silent" "\|]"
+.br
+.RB "[\|" "\-\-keyscan" "\|]"
+.br
+.RB "[\|" "\-\-nslookup "\c
+.I path_to_nslookup_program\c
+\|]
+.br
+.RB "[\|" "\-\-ssh "\c
+.I path_to_ssh_program\c
+\|]
+.br
+.IR "domain_name " "[\|" "take_regexp " "[\|" "remove_regexp"\|]\|]"
+
+.SH DESCRIPTION
+.LP
+.B make-ssh-known-hosts
+is a perl5 script that helps create the
+.I /etc/ssh_known_hosts
+file, which is used by
+.B ssh
+to contain the host keys of all publicly known hosts.  
+.B Ssh
+does not normally permit login using rhosts or /etc/hosts.equiv
+authentication unless the server knows the client's host key.  In
+addition, the host keys are used to prevent man-in-the-middle attacks.
+.LP
+In addition to
+.IR /etc/ssh_known_hosts ",
+.B ssh
+also uses the
+.I $HOME/.ssh/known_hosts
+file.  This file, however, is intended to contain only those hosts
+that the particular user needs but are not in the global file.  It is
+intended that the
+.I /etc/ssh_known_hosts
+file be maintained by the system administration, and periodically
+updated to contain the host keys for any new hosts.
+.LP
+The
+.B make-ssh-known-hosts
+program finds all the hosts in a domain by making a DNS query to the
+master domain name server of the domain. The master domain name server
+is located by searching for the SOA record of the domain from the initial
+domain name server (which can be specified with the
+.B \-\-initialdns
+option). The master domain name server can also be given directly with
+the
+.B \-\-server
+option.
+.LP
+After getting the hostname list
+.B make-ssh-known-hosts
+tries to get the public key from every host in the domain. It first
+tries to connect ssh port to check check if the host is alive, and if
+so, it tries to run the command
+.B cat /etc/ssh_host_key.pub
+on the remote machine using
+.BR ssh ".
+If the command succeeds, it knows the remote machine has
+.B ssh
+installed properly, and it then extracts the public key from the
+output, and prints the
+.B /etc/ssh_known_hosts
+entry for it to 
+.BR STDOUT ". Because
+.B make-ssh-known-hosts
+is usually run before
+remote machines have /etc/ssh_known_hosts file you may have to use
+RSA-authentication to allow access to hosts. 
+.LP
+If the command fails for some reason, it checks if the
+.B ssh
+client still got the public key from the remote host in the initial dialog,
+and if so, it will print a proper entry, and if
+.B \-\-notrustdaemon
+option is given comment it out.
+.LP
+.I Domain_name
+is the domain name for which the file is to be generated. By default 
+.B make-ssh-known-hosts
+extracts also all subdomains of domain. Many sites will want to
+include several domains in their
+.I /etc/ssh_known_hosts
+file.  The entries for each domain should be extracted separately by
+running
+.B make-ssh-known-hosts
+once for each domain.  The results should then be combined to create
+the final file.
+.LP
+.I Take_regexp
+is a perl regular expression that matches the hosts to be taken from the
+domain. The data matched contains all the DNS records in the form "\|\c
+.B fieldname=value\c
+\|". The fields are separated with newline, and the perl match is made in
+multiline mode and it is case insensetive. The multiline mode means
+that you can use a regexp like "\|\c
+.B ^wks=.*telnet.*$\c
+\|" to match all hosts that have WKS (well known services) field that
+contains value "telnet".
+.LP
+.I Remove_regexp
+is similar but those hosts that match the regexp are not added (it can
+be used for example to filter out PCs and Macs using the hinfo field: "\|\c
+.B ^hinfo=.*(mac|pc)\c
+\|").
+
+.SH OPTIONS
+.TP
+.BI "\-\-initialdns " "initial_dns"\c
+.TP
+.BI "\-i " "initial_dns"\c
+\&Set the initial domain name server used to query the SOA record of the
+domain.
+
+.TP
+.BI "\-\-server " "domain_name_server"\c
+.TP
+.BI "\-se " "domain_name_server"\c
+\&Set the master domain name server of the domain. This host is used
+to query the DNS list of the domain.
+
+.TP
+.BI "\-\-subdomains " "subdomainlist"\c
+.TP
+.BI "\-su " "subdomainlist"\c
+\&Comma separated list of subdomains that are added to hostnames. For
+example, if subdomainlist is "\|\c
+.I ,foo, foo.bar, foo.bar.zappa, foo.bar.zappa.hut.fi\c
+\|" then when host foobar is added to
+.B /etc/ssh_known_hosts
+file it has aliases "\|\c
+.I foobar, foobar.foo, foobar.foo.bar, foobar.foo.bar.zappa, foobar.foo.bar.zappa.hut.fi\c
+\|". The default action is to take all subparts of the host but the
+second last on a host by host basis.  (The last element is usually the
+country code, and something like 
+.I foobar.foo.bar.zappa.hut 
+would not make sense.)
+
+.TP
+.BI "\-\-debug " "debug_level"\c
+.TP
+.BI "\-de " "debug_level"\c
+\&Set the debug level. Default is 5, bigger values give more output.
+Using a big value (like 999) will print lots of debugging output.
+
+.TP
+.BI "\-\-timeout " "ssh_exec_timeout"\c
+.TP
+.BI "\-ti " "ssh_exec_timeout"\c
+\&Timeout when executing
+.B ssh
+command.  The default is 60 seconds.
+
+.TP
+.BI "\-\-pingtimeout " "ping_timeout"\c
+.TP
+.BI "\-pi " "ping_timeout"\c
+\&Timeout when trying to ping the ssh port.  The default is 3 seconds.
+
+.TP
+.BI "\-\-passwordtimeout " "timeout_when_asking_password"\c
+.TP
+.BI "\-pa " "timeout_when_asking_password"\c
+\&Timeout when asking password for ssh command. Default is that no
+passwords are queried. Use value 0 to have no timeout for password queries.
+
+.TP
+.BI "\-\-notrustdaemon"\c
+.TP
+.BI "\-notr"\c
+\&If the
+.B ssh
+command fails, use the public key stored in the local known hosts file
+and trust it is the correct key for the host. If this option is not
+given such entries are commented out in the generated
+.B /etc/ssh_known_hosts
+file.
+
+.TP
+.BI "\-\-norecursive"\c
+.TP
+.BI "\-nor"\c
+\&Tell
+.B make-ssh-known-hosts
+that it should only extract keys for the given domain, and not to be
+recursive. 
+
+.TP
+.BI "\-\-domainnamesplit"\c
+.TP
+.BI "\-do"\c
+\&Split the domainname to get the list of subdomains. Use this option
+if you don't want hostname to splitted to pieces automatically.
+Default splitting is done host by host basis. If the domain is
+zappa.hut.fi, and the host name is foo.bar then default action adds
+entries "\|\c
+.I foo, foo.bar, foo.bar.zappa, foo.bar.zappa.hut.fi\c
+\|" and this options adds entries "\|\c
+.I foo.bar, foo.bar.zappa, foo.bar.zappa.hut.fi\c
+\|").
+
+.TP
+.BI "\-\-silent"\c
+.TP
+.BI "\-si"\c
+\&Be silent.
+
+.TP
+.BI "\-\-keyscan"\c
+.TP
+.BI "\-k"\c
+\&Output list of all hosts in format "ipaddr1,ipaddr2,...ipaddrn
+hostname.domain.co,hostname,ipaddr1,ipaddr2,all_other_hostname_entries".
+The output of this can be feeded to ssh-keyscan to fetch keys.
+
+.TP
+.BI "\-\-nslookup " "path_to_nslookup_program"\c
+.TP
+.BI "\-n " "path_to_nslookup_program"\c
+\&Path to the
+.B nslookup
+program. 
+
+.TP
+.BI "\-\-ssh " "path_to_ssh_program"\c
+.TP
+.BI "\-ss " "path_to_ssh_program"\c
+\&Path to the
+.B ssh
+program, including all options.
+
+.SH EXAMPLES
+.LP
+The following command:
+.IP
+.B example# make-ssh-known-hosts cs.hut.fi > \c
+.B /etc/ssh_known_hosts
+.LP
+finds all public keys of the hosts in
+.B cs.hut.fi
+domain and put them to
+.B /etc/ssh_known_hosts
+file splitting domain names on a per host basis.
+.LP
+The command
+.IP
+.B example% make-ssh-known-hosts hut.fi '^wks=.*ssh' > \c
+.B hut-hosts
+.LP
+finds all hosts in
+.B hut.fi
+domain, and its subdomains having own name server (cs.hut.fi,
+tf.hut.fi, tky.hut.fi) that have ssh service and puts their public key
+to hut-hosts file. This would require that the domain name server of
+hut.fi would define all hosts running ssh to have entry ssh in their
+WKS record. Because nobody yet adds ssh to WKS, it would be better to
+use command
+.IP
+.B example% make-ssh-known-hosts hut.fi '^wks=.*telnet' > \c
+.B hut-hosts
+.LP
+that would take those host having telnet service. This uses default
+subdomain list.
+
+.LP
+The command:
+.IP
+.B example% make-ssh-known-hosts hut.fi 'dipoli.hut.fi' '^hinfo=.*(mac|pc)' > \c
+.B dipoli-hosts
+.LP
+finds all hosts in hut.fi domain that are in dipoli.hut.fi subdomain
+(note dipoli.hut.fi does not have own name server so its entries are
+in hut.fi-server) and that are not Mac or PC.
+
+.SH FILES
+.ta 3i
+/etc/ssh_known_hosts	Global host public key list
+
+.SH "SEE ALSO"
+.BR ssh (1),
+.BR sshd (8),
+.BR ssh-keygen (1),
+.BR ping (8),
+.BR nslookup (8),
+.BR perl (1),
+.BR perlre (1)
+
+.SH AUTHOR
+Tero Kivinen <kivinen@hut.fi>
+
+.SH COPYING
+.LP
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+.LP
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+.LP
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the the author instead of in the original
+English.
diff --git a/contrib/make-ssh-known-hosts.pl b/contrib/make-ssh-known-hosts.pl
new file mode 100644
index 0000000..49c9f61
--- /dev/null
+++ b/contrib/make-ssh-known-hosts.pl
@@ -0,0 +1,737 @@
+#!/usr/bin/perl -w
+# -*- perl -*-
+######################################################################
+# make-ssh-known-hosts.pl -- Make ssh-known-hosts file
+# Copyright (c) 1995 Tero Kivinen
+# All Rights Reserved.
+#
+# Make-ssh-known-hosts is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY.  No author or distributor accepts
+# responsibility to anyone for the consequences of using it or for
+# whether it serves any particular purpose or works at all, unless he
+# says so in writing.  Refer to the GNU General Public License for full
+# details.
+#
+# Everyone is granted permission to copy, modify and redistribute
+# make-ssh-known-hosts, but only under the conditions described in
+# the GNU General Public License.  A copy of this license is supposed to
+# have been given to you along with make-ssh-known-hosts so you can
+# know your rights and responsibilities.  It should be in a file named
+# gnu-COPYING-GPL.  Among other things, the copyright notice and this notice
+# must be preserved on all copies.
+######################################################################
+#         Program: make-ssh-known-hosts.pl
+#	  $Source: /var/cvs/openssh/contrib/Attic/make-ssh-known-hosts.pl,v $
+#	  Author : $Author: damien $
+#
+#	  (C) Tero Kivinen 1995 <Tero.Kivinen@hut.fi>
+#
+#	  Creation          : 19:52 Jun 27 1995 kivinen
+#	  Last Modification : 00:07 Jul  8 1998 kivinen
+#	  Last check in     : $Date: 2000/03/15 01:13:03 $
+#	  Revision number   : $Revision: 1.1 $
+#	  State             : $State: Exp $
+#	  Version	    : 1.343
+#	  Edit time	    : 242 min
+#
+#	  Description       : Make ssh-known-host file from dns data.
+#
+#	  $Log: make-ssh-known-hosts.pl,v $
+#	  Revision 1.1  2000/03/15 01:13:03  damien
+#	   - Created contrib/ subdirectory. Included helpers from Phil Hands'
+#	     Debian package, README file and chroot patch from Ricardo Cerqueira
+#	     <rmcc@clix.pt>
+#	   - Moved gnome-ssh-askpass.c to contrib directory and reomved config
+#	     option.
+#	   - Slight cleanup to doc files
+#	
+#	  Revision 1.6  1998/07/08 00:44:23  kivinen
+#	  	Fixed to understand bind 8 nslookup output.
+#
+# Revision 1.5  1998/04/30  01:53:33  kivinen
+# 	Moved kill before close and added sending SIGINT first and
+# 	then 1 second sleep before sending SIGKILL.
+#
+#	  Revision 1.4  1998/04/17 00:39:19  kivinen
+#	  	Changed to close ssh program filedescriptor before killing it.
+#	  	Removed ^ from the password matching prompt.
+#
+#	  Revision 1.3  1997/04/17 04:21:27  kivinen
+#	  	Changed to use 3des by default.
+#
+#	  Revision 1.2  1997/03/26 07:14:01  kivinen
+#	  	Added EWOULDBLOCK.
+#
+#	  Revision 1.1.1.1  1996/02/18 21:38:10  ylo
+#	  	Imported ssh-1.2.13.
+#
+# Revision 1.4  1995/10/02  01:23:45  ylo
+# 	Ping packet size fixes from Kivinen.
+#
+# Revision 1.3  1995/08/29  22:37:39  ylo
+# 	Now uses GlobalKnownHostsFile and UserKnownHostsFile.
+#
+# Revision 1.2  1995/07/15  13:26:37  ylo
+# 	Changes from kivinen.
+#
+# Revision 1.1.1.1  1995/07/12  22:41:05  ylo
+# Imported ssh-1.0.0.
+#
+#
+#
+# If you have any useful modifications or extensions please send them to
+# Tero.Kivinen@hut.fi
+#
+######################################################################
+# initialization
+
+require 5.000;
+use Getopt::Long;
+use FileHandle;
+use POSIX;
+use Socket;
+use Fcntl;
+
+$version = ' $Id: make-ssh-known-hosts.pl,v 1.1 2000/03/15 01:13:03 damien Exp $ ';
+
+$command_line = "$0 ";
+foreach $a (@ARGV) {
+    $command_line .= $a . " ";
+}
+STDERR->autoflush(1);
+
+######################################################################
+# default values for options
+
+$debug = 5;
+$defserver = '';
+$bell='\a';
+$public_key = '/etc/ssh_host_key.pub';
+$private_ssh_known_hosts = "/tmp/ssh_known_hosts$$";
+$timeout = 60;
+$ping_timeout = 3;
+$passwordtimeout = undef;
+$trustdaemon = 1;
+$domainnamesplit = 0;
+$recursive = 1;
+
+######################################################################
+# Programs and their options
+
+$nslookup = "nslookup";
+
+$ssh="ssh -a -c 3des -x -o 'ConnectionAttempts 1' -o 'FallBackToRsh no' -o 'GlobalKnownHostsFile /dev/null' -o 'KeepAlive yes' -o 'StrictHostKeyChecking no' -o 'UserKnownHostsFile $private_ssh_known_hosts'";
+$sshdisablepasswordoption="-o 'BatchMode yes' -o 'PasswordAuthentication no'";
+
+######################################################################
+# Cleanup and initialization
+
+unlink($private_ssh_known_hosts);
+$sockaddr = 'S n a4 x8';
+($junk, $junk, $sshport) = getservbyname("ssh", "tcp");
+if (!defined($sshport)) {
+    $sshport = 22;
+}
+($tcpprotoname, $junk, $tcpproto) = getprotobyname('tcp');
+defined($tcpprotoname) || die "getprotobyname : $!";
+
+######################################################################
+# Parse options
+
+GetOptions("initialdns=s", "server=s", "subdomains=s",
+	   "debug=i", "timeout=i", "passwordtimeout=i",
+	   "trustdaemon!", "domainnamesplit", "silent",
+	   "nslookup=s", "pingtimeout=i", "recursive!",
+	   "keyscan", 
+	   "ssh=s")
+    || die "Getopt : $!";
+
+if (defined($opt_initialdns)) { $defserver = $opt_initialdns; }
+
+if (defined($opt_server)) { $server = $opt_server; }
+
+if (defined($opt_subdomains)) { @subdomains = split(/,/, $opt_subdomains); }
+
+if (defined($opt_debug)) { $debug = $opt_debug; }
+
+if (defined($opt_timeout)) { $timeout = $opt_timeout; }
+
+if (defined($opt_pingtimeout)) { $ping_timeout = $opt_pingtimeout; }
+
+if (defined($opt_passwordtimeout)) {
+    $passwordtimeout = $opt_passwordtimeout;
+    $sshdisablepasswordoption = '';
+}
+
+if (defined($opt_trustdaemon)) { $trustdaemon = $opt_trustdaemon; }
+
+if (defined($opt_recursive)) { $recursive = $opt_recursive; }
+
+if (defined($opt_domainnamesplit)) { $domainnamesplit = $opt_domainnamesplit; }
+
+if (defined($opt_silent)) { $bell = ''; }
+
+if (defined($opt_nslookup)) { $nslookup = $opt_nslookup; }
+
+if (defined($opt_ssh)) { $ssh = $opt_ssh; } else {
+    $ssh = "$ssh $sshdisablepasswordoption";
+}
+
+if ($#ARGV == 0) {
+    $domain = "\L$ARGV[0]\E";
+    $grep_yes = '.*';
+    $grep_no = '^$';
+} elsif ($#ARGV == 1) {
+    $domain = "\L$ARGV[0]\E";
+    $grep_yes = $ARGV[1];
+    $grep_no = '^$';
+} elsif ($#ARGV == 2) {
+    $domain = "\L$ARGV[0]\E";
+    $grep_yes = $ARGV[1];
+    $grep_no = $ARGV[2];
+} else {
+    print(STDERR "$0 [--initialdns initial_dns_server] [--server dns_server] [--subdomains sub.sub.domain,sub.sub,sub,] [--debug debug_level] [--timeout ssh_exec_timeout_in_secs] [--pingtimeout ping_timeout_in_secs] [--passwordtimeout timeout_for_password_in_secs] [--notrustdaemon] [--norecursive] [--domainnamesplit] [--silent] [--keyscan] [--nslookup path_to_nslookup] [--ssh path_to_ssh] full.domain [ host_info_take_regexp [ host_info_remove_regex ]]\n");
+    exit(1);
+}
+
+######################################################################
+# Check that ssh program exists
+
+if (system("$ssh > /dev/null 2>&1 ") != 256) {
+    print(STDERR "Error: Could not run ssh program ($ssh): $!\nError: Try giving the path to it with --ssh option\n");
+    exit(1);
+}
+
+######################################################################
+# Generate subdomains list
+
+if (!$domainnamesplit) {
+    debug(6, "Auto splitting host entries");
+} elsif (!defined(@subdomains)) {
+    debug(6, "Generating subdomain list");
+    
+    # split domain to pieces
+    @domain_pieces = split(/\./, $domain);
+    
+    # add empty domain part
+    push(@subdomains, '');
+    
+    # add rest parts, except the one before full domain name
+    $entry='';
+    for(; $#domain_pieces > 1; ) {
+	$entry .= "." . shift(@domain_pieces);
+	push(@subdomains, $entry);
+    }
+    
+    # add full domain name
+    push(@subdomains, ".$domain");
+    debug(5, "Subdomain list: " . join(',', @subdomains));
+} else {
+    debug(5, "Using given subdomain list:" . join(',', @subdomains));
+}
+
+######################################################################
+# finding SOA entry for domain
+
+@other_servers = ();
+if (!defined($server)) {
+    debug(6, "Finding DNS database SOA entry");
+
+    ($server, @other_servers) = find_soa($domain, $defserver);
+    
+    if (!defined($server)) {
+	print(STDERR "Error: Could not find DNS SOA entry from default dns server\nError: Try giving the initial nameserver with --initialdns option\n");
+	exit(1);
+    } else {
+	debug(5, "DNS server found : $server");
+    }
+} else {
+    debug(5, "Using given DNS server : $server");
+}
+
+######################################################################
+# Print header
+    
+($name, $junk, $junk, $junk, $junk, $junk, $gecos) = getpwuid($<);
+$gecos =~ s/,.*$//g;
+
+if (!defined($opt_keyscan)) {
+    print(STDOUT "# This file is generated with make-ssh-known-hosts.pl\n");
+    print(STDOUT "#$version\n");
+    print(STDOUT "# with command line :\n");
+    print(STDOUT "# $command_line\n");
+    print(STDOUT "#\n");
+    print(STDOUT "# The script was run by $gecos ($name) at " . localtime() . "\n");
+    print(STDOUT "# using perl ($^X) version $].\n");
+}
+
+######################################################################
+# Get DNS database list from server
+
+do {    
+    $domains_done{$domain} = 1;
+    delete $domains_waiting{$domain};
+
+    $hostcnt = 0;
+    $cnamecnt = 0;
+    $lines = 0;
+    $soa = 0;
+    undef %host;
+    undef %cname;
+    undef %hostdata;
+    
+  dnsagain:
+    debug(1, "Getting DNS database for $domain from server $server");
+    open(DNS, "echo ls -d $domain | nslookup - $server 2>&1 |") ||
+	die "Error: Could not start nslookup to make dns list : $!\nError: Try giving --nslookup option and telling the path to nslookup program\n";
+    
+    while(<DNS>) {
+	$lines++;
+	chomp;
+	undef $hostname if/^\s*$/;
+	if (/^\s{0,1}([a-zA-Z0-9-]\S*)/) {
+            $hostname = "\L$1\E";
+	}
+	next unless defined $hostname;
+	if (/^.*\s(SOA)\s+(.*)\s*$/ || $hostname eq "SOA") {
+	    undef $soa if(/^.*\s(SOA)\s+(.*)\s*$/);
+	    $data = $_ if ($hostname eq "SOA");
+	    $data = $2 unless $hostname eq "SOA";
+	    $data =~ s/\s*;.*$//;
+	    $data =~ s/^\s+//;
+	    if( defined $soa ) {
+		$soa .= " \L$data\E";
+	    } else {
+		$soa = "\L$data\E";
+	    }
+	    $hostname = "SOA";
+        } elsif (/^.*\s(A|CNAME|NS)\s+(.*)\s*$/) {
+            $host = $hostname;
+	    $field = "\L$1\E";
+	    $data = "\L$2\E";
+	    debug(70, "Line = /$host/$field/$data/");
+	    if ($host !~ /\.$/) {
+		$host .= ".$domain";
+	    } else {
+		$host =~ s/\.$//g;
+	    }
+	    if ($field eq "a") {
+		if ($host =~ /$domain$/) {
+		    if (defined($host{$host})) {
+			$host{$host} .= ",$data";
+		    } else {
+			$host{$host} = "$data";
+			$hostcnt++;
+		    }
+		    debug(30, "$host A == $host{$host}");
+		}
+	    } elsif ($field eq "cname") {
+		if ($data !~ /\.$/ && ! /^\s/ ) {
+    		    $data .= ".$domain";
+	        } else {
+		    $data =~ s/\.$//g;
+	        }
+		if ($host =~ /$domain$/) {
+		    if (defined($cname{$data})) {
+			$cname{$data} .= ",$host";
+		    } else {
+			$cname{$data} = "$host";
+			$cnamecnt++;
+		    }
+		    debug(30, "$host CNAME $data");
+		    $junk = $data;
+		    $data = $host;
+		    $host = $junk;
+		}
+	    } elsif ($field eq "ns") {
+		if (!defined($domains_done{$host})) {
+		    if (!defined($domains_waiting{$host})) {
+			debug(10, "Adding subdomain $host to domains list, with NS $data");
+			$domains_waiting{$host} = $data;
+			push(@domains_waiting, $host);
+		    } else {
+			debug(10, "Adding NS $data for domain $host");
+			$domains_waiting{$host} .= ",$data";
+		    }
+		}
+	    }
+	    if (!defined($hostdata{$host})) {
+		$hostdata{$host} = "$host\n$field=$data\n";
+	    } else {
+		$hostdata{$host} .= "$field=$data\n";
+	    }
+	}
+    }
+    close(DNS);
+    if ($hostcnt == 0 && $cnamecnt == 0) {
+	if ($#other_servers != -1) {
+	    $server = shift(@other_servers);
+	    goto dnsagain;
+	}
+    }
+    debug(1, "Found $hostcnt hosts, $cnamecnt CNAMEs (total $lines lines)");
+    if (!defined($opt_keyscan)) {
+	print(STDOUT "#\n");
+	print(STDOUT "# Domain = $domain, server = $server\n");
+	print(STDOUT "# Found $hostcnt hosts, $cnamecnt CNAMEs (total $lines lines)\n");
+	print(STDOUT "# SOA = $soa\n");
+	print(STDOUT "#\n");
+    }
+
+######################################################################
+# Loop through hosts and try to connect to hosts
+
+    foreach $i (sort (keys %host)) {
+	debug(50, "Host = $i, Hostdata = $hostdata{$i}");
+	if ($hostdata{$i} =~ /$grep_yes/im &&
+	    $hostdata{$i} !~ /$grep_no/im &&
+	    $i !~ /^localhost\./ &&
+	    $host{$i} !~ /^127.0.0.1$|^127.0.0.1,|,127.0.0.1$|,127.0.0.1,/) {
+	    debug(2, "Trying host $i");
+	    
+	    @hostnames = ();
+	    if (defined($cname{$i})) {
+		expand($i, \@hostnames, \@subdomains);
+		foreach $j (split(/,/, $cname{$i})) {
+		    expand($j, \@hostnames, \@subdomains);
+		}
+	    } else {
+		expand($i, \@hostnames, \@subdomains);
+	    }
+	    foreach $j (split(/,/, $host{$i})) {
+		push(@hostnames, $j);
+	    }
+	    $hostnames = join(',', (@hostnames));
+	    
+	    if (defined($opt_keyscan)) {
+		printf(STDOUT "$host{$i}\t$hostnames\n");
+	    } elsif (try_ping($i, $host{$i})) {
+		$trusted = 1;
+		$err = 'Timeout expired';
+		$ssh_key = try_ssh("$i");
+		if (!defined($ssh_key)) {
+		    $ssh_key = find_host_from_known_hosts($i);
+		    $trusted = 0;
+		}
+		if (defined($ssh_key)) {
+		    if ($trusted) {
+			debug(2, "Ssh to $i succeded");
+		    } else {
+			debug(2, "Ssh to $i failed, using local known_hosts entry");
+		    }
+		    debug(4, "adding entries : $hostnames");
+		    $ssh_key =~ s/root@//i;
+		    if (!$trusted && !$trustdaemon) {
+			print(STDOUT "# $hostnames $ssh_key\n");
+		    } else {
+			print(STDOUT "$hostnames $ssh_key\n");
+		    }
+		} else {
+		    debug(2, "ssh failed : $err");
+		}
+	    } else {
+		debug(2, "ping failed");
+	    }
+	} else {
+	    debug(10, "Skipped host $i");
+	}
+    }
+  again:
+    $domain = shift(@domains_waiting);
+    if (defined($domain)) {
+	$server = $domains_waiting{$domain};
+	@other_servers = split(',', $server);
+	$server = shift(@other_servers);
+	($server, @other_servers) = find_soa($domain, $server);
+	if(!defined($server)) {
+	    debug(1, "Skipping domain $domain because no DNS SOA entry found");
+	    $domains_done{$domain} = 1;
+	    delete $domains_waiting{$domain};
+	    goto again;
+	}
+    }
+} while ($recursive && defined($domain));
+
+unlink($private_ssh_known_hosts);
+exit (0);
+
+######################################################################
+# try_ping -- try to ping to host and return 1 if success
+# $success = try_ping($host, $list_ip_addrs);
+
+sub try_ping {
+    my($host, $ipaddrs) = @_;
+    my(@ipaddrs, $ipaddr, $serv, $ip);
+    my($rin, $rout, $win, $wout, $nfound, $tmout, $buf, $len, $ret, $err);
+
+    $buf = '';
+    debug(51,"Trying to ping host $host");
+    @ipaddrs = split(/,/, $ipaddrs);
+
+    while ($ipaddr = shift(@ipaddrs)) {
+	
+	debug(55,"Trying ipaddr $ipaddr");
+	
+	#initialize socket
+	socket(PING, PF_INET, SOCK_STREAM, $tcpproto) ||
+	    die "socket failed : $!";
+	setsockopt(PING, SOL_SOCKET, SO_REUSEADDR, 1) ||
+	    die "setsockopt failed : $!";
+	PING->autoflush(1);
+	fcntl(PING, F_SETFL, fcntl(PING, F_GETFL, 0) | POSIX::O_NONBLOCK) ||
+	    die "fcntl failed : $!";
+	
+        $ip = pack('C4', split(/\./, $ipaddr, 4));
+	$serv = pack($sockaddr, AF_INET, $sshport, $ip);
+	
+      again:
+	# try connect
+	$ret = connect(PING, $serv);
+	$err = $!;
+	if (!$ret) {
+	    debug(60, "Connect failed : $err");
+	    if ($err == EINTR) {
+		goto again;
+	    }
+	    # socket not yet connected, wait for result, it will
+	    # wake up for writing when done
+	    $tmout = $ping_timeout;
+	    
+ 	    $rin = '';
+	    $win = '';
+	    vec($rin, fileno(PING), 1) = 1;
+	    vec($win, fileno(PING), 1) = 1;
+	    debug(60, "Waiting in select, rin = " . unpack('H*', $rin) .
+		  ", win = " . unpack('H*', $win));
+	    ($nfound) = select($rout = $rin, $wout = $win, undef, $tmout);
+	    $err = $!;
+	    debug(80, "Select returned $nfound, rout = " . unpack('H*', $rout) .
+		  ", wout = " . unpack('H*', $wout));
+	    if ($nfound != 0) {
+		# connect done, read the status with sysread
+		$ret = sysread(PING, $buf, 1);
+		$err = $!;
+		if (defined($ret) || $err == EAGAIN || $err == EWOULDBLOCK) {
+		    debug(60, "Select ok, read ok ($err), returning ok");
+		    # connection done, return ok
+		    shutdown(PING, 2);
+		    close(PING);
+		    return 1;
+		} else {
+		    # connection failed, try next ipaddr
+		    debug(60, "Select ok, read failed : $err, trying next");
+		    close(PING);
+		}
+	    } else {
+		# timeout exceeded, try next ipaddr
+		debug(60, "Select failed : $err, trying next");
+		close(PING);
+	    }
+	} else {
+	    # connect succeeded, return ok.
+	    debug(60, "Connect ok, returning ok");
+	    shutdown(PING, 2);
+	    close(PING);
+	    return 1;
+	}
+    }
+    debug(60, "Returning fail");
+    return 0;
+}
+
+######################################################################
+# try_ssh -- try ssh connection to host and return ssh_key if success
+# if failure return undef, and set $err string to contain error message.
+# $ssh_key = try_ssh($host);
+
+sub try_ssh {
+    my($host) = @_;
+    my($buf, $ret, $pos, $pid, $rin, $nfound, $tmout);
+
+    $pid = open(SSH, "$ssh $host cat $public_key 2>&1 |");
+    $err = undef;
+
+    if ($pid == 0) {
+	$err = "could not open ssh connection to host";
+	return undef;
+    }
+    $ret = 1;
+    $pos = 0;
+    $buf = '';
+    $tmout = $timeout;
+    debug(10, "Starting ssh select loop");
+  loop:
+    while (1) {
+	
+	$rin = '';
+	vec($rin, fileno(SSH), 1) = 1;
+	($nfound, $tmout) = select($rin, undef, undef, $tmout);
+	
+	# Timeout
+	if ($nfound <= 0) {
+	    debug(20, "Ssh select timed out");
+	    kill(2, $pid); sleep(1); kill(9, $pid);
+	    close(SSH);
+	    $err = "Timeout expired";
+	    return undef;
+	}
+	
+	$ret = sysread(SSH, $buf, 256, $pos);
+	# EOF or error
+	if ($ret <= 0) {
+	    # Yes, close the pipe and return
+	    close(SSH);
+	    debug(20, "Ssh select closed status = $?");
+	    $err = "No reply from ssh";
+	    return undef;
+	}
+	$pos += $ret;
+	while ($buf =~ /^(.*)\n\r?([\000-\377]*)$/) {
+	    $_ = $1;
+	    $buf = $2;
+	    $pos = length($buf);
+	    debug(20, "Ssh select loop, line = \"$_\"");
+	    if (/^connection.*refused/i) {
+		$err = "connection refused";
+	    } elsif (/^permission/i) {
+		$err = "permission denied";
+	    } elsif (/$public_key.*no\s+file/i) {
+		$err = "$public_key file not found";
+	    } elsif (/$public_key.*permission\s+denied/i) {
+		$err = "$public_key file permission denied";
+	    } elsif (/^\d+\s+\d+\s+\d/) {
+		kill(2, $pid); sleep(1); kill(9, $pid);
+		close(SSH);
+		return $_;
+	    }
+	    if (defined($err)) {
+		kill(2, $pid); sleep(1); kill(9, $pid);
+		close(SSH);
+		return undef;
+	    }
+	}
+	if ($buf =~ /password: $/i) {
+	    if (defined($passwordtimeout)) {
+		$tmout = $passwordtimeout;
+		print(STDERR "$bell\n\rPassword: ");
+		if ($tmout == 0) {
+		    $tmout = undef;
+		}
+	    } else {
+		$tmout = 0;
+	    }
+	    $buf = '';
+	    $pos = 0;
+	}
+    }
+}
+
+######################################################################
+# find_hosts_from_known_hosts -- find host key from private known_hosts file
+# $ssh_key = find_host_from_known_hosts($host);
+
+sub find_host_from_known_hosts {
+    my($host) = @_;
+    open(KNOWNHOSTS, "<$private_ssh_known_hosts") || return undef;
+    while(<KNOWNHOSTS>) {
+	@_ = split(/\s+/, $_);
+	if ($_[0] =~ /^$host$|^$host,|,$host$/) {
+	    shift(@_);
+	    close(KNOWNHOSTS);
+	    return join(' ', @_);
+	}
+    }
+    close(KNOWNHOSTS);
+    return undef;
+}
+
+######################################################################
+# expand -- insert expanded hostnames to hostnames table
+# expand($hostname, \@hostnames, \@subdomains);
+
+sub expand {
+    my($host, $hostnames, $subdomains) = @_;
+    my($newhost, $sub, $entry);
+
+    if (!$domainnamesplit) {
+	my(@domain_pieces);
+	
+	# split domain to pieces
+	@domain_pieces = split(/\./, $host);
+    
+	# add rest parts, except the one before full domain name
+	$entry = shift(@domain_pieces);
+	
+	debug(20, "Adding autosplit entry $entry");
+	push(@$hostnames, $entry);
+	
+	for(; $#domain_pieces > 1; ) {
+	    $entry .= "." . shift(@domain_pieces);
+	    debug(20, "Adding autosplit entry $entry");
+	    push(@$hostnames, $entry);
+	}
+	# add full domain name
+	debug(20, "Adding autosplit entry $host");
+	push(@$hostnames, $host);
+    } else {
+	if ($host =~ /^(.*)$domain$/i) {
+	    $newhost = $1;
+	    $newhost =~ s/\.$//g;
+	    foreach $sub (@$subdomains) {
+		$entry = $newhost . $sub;
+		$entry =~ s/^\.//g;
+		if ($entry ne '') {
+		    debug(20, "Adding entry $entry");
+		    push(@$hostnames, $entry);
+		}
+	    }
+	}
+    }
+}
+
+######################################################################
+# Print debug text
+# debug(text_debug_level, string)
+
+sub debug {
+    my($level, $str) = @_;
+    if ($debug > $level) {
+	print(STDERR "$0:debug[$level]: $str\n");
+    }
+}
+
+######################################################################
+# find_soa -- find soa entry for domain
+# ($soa_origin, @other_servers) = find_soa($domain, $initial_server)
+
+sub find_soa {
+    my($domain, $initial_server) = @_;
+    my($field, $data, $server, @other_servers);
+
+    open(DNS, "$nslookup -type=soa $domain $initial_server 2>&1 |") ||
+	die "Error: Could not start nslookup to find SOA entry for $domain : $!\nError: Try giving the path to it with --nslookup option\n";
+    
+    while (<DNS>) {
+	if (/^[^=]*origin\s*=\s*(.*)/) {
+	    $server = $1;
+	    debug(10, "Found origin : $1");
+	} elsif (/^[^=]*nameserver\s*=\s*(.*)\s*$/) {
+	    push(@other_servers, $1);
+	    debug(10, "Found nameserver : $1");
+	}
+    }
+    close(DNS);
+    return($server, @other_servers);
+}
+
+######################################################################
+# make_perl_happy -- use some symbols, so perl doesn't complain so much
+# make_perl_happy();
+
+sub make_perl_happy {
+    if (0) {
+	print $opt_silent;
+    }
+}
+
+1;
diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id
new file mode 100644
index 0000000..0ab37ca
--- /dev/null
+++ b/contrib/ssh-copy-id
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# Shell script to install your identity.pub on a remote machine
+# Takes the remote machine name as an argument.
+# Obviously, the remote machine must accept password authentication,
+# or one of the other keys in your ssh-agent, for this to work.
+
+ID_FILE="${HOME}/.ssh/identity.pub"
+
+if [ "-i" = "$1" ]; then
+  shift
+  # check if we have 2 parameters left, if so the first is the new ID file
+  if [ -n "$2" ]; then
+    if expr "$1" : ".*\.pub" ; then
+      ID_FILE="$1"
+    else
+      ID_FILE="$1.pub"
+    fi
+    shift         # and this should leave $1 as the target name
+  fi
+else
+  if [ x$SSH_AUTH_SOCK != x ] ; then
+    GET_ID="$GET_ID ssh-add -L"
+  fi
+fi
+
+if [ -z "`eval $GET_ID`" -a -r "${ID_FILE}" ] ; then
+  GET_ID="cat ${ID_FILE}"
+fi
+
+if [ -z "`eval $GET_ID`" ]; then
+  echo "$0: ERROR: No identities found"
+  exit 1
+fi
+
+{ eval "$GET_ID" ; } | ssh $1 "test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys ; chmod g-w . .ssh .ssh/authorized_keys"
+
+cat <<EOF
+Now try logging into the machine, with "ssh '$1'", and check in:
+
+  .ssh/authorized_keys
+
+to make sure we haven't added extra keys that you weren't expecting.
+
+EOF
diff --git a/contrib/ssh-copy-id.1 b/contrib/ssh-copy-id.1
new file mode 100644
index 0000000..df4f88d
--- /dev/null
+++ b/contrib/ssh-copy-id.1
@@ -0,0 +1,67 @@
+.ig \"  -*- nroff -*-
+Copyright (c) 1999 Philip Hands Computing <http://www.hands.com/>
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.TH SSH-COPY-ID 1 "14 November 1999" "OpenSSH"
+.SH NAME
+ssh-copy-id \- install your identity.pub in a remote machine's authorized_keys
+.SH SYNOPSIS
+.B ssh-copy-id [-i [identity_file]]
+.I "[user@]machine"
+.br
+.SH DESCRIPTION
+.BR ssh-copy-id
+is a script that uses ssh to log into a remote machine (presumably
+using a login password, so password authentication should be enabled,
+unless you've done some clever use of multiple identities)
+.PP
+It also changes the permissions of the remote user's home,
+.BR ~/.ssh ,
+and
+.B ~/.ssh/authorized_keys
+to remove group writability (which would otherwise prevent you from logging in, if the remote
+.B sshd
+has
+.B StrictModes
+set in its configuration).
+.PP
+If the
+.B -i
+option is given then the identity file (defaults to
+.BR ~/.ssh/identity.pub )
+is used, regardless of whether there are any keys in your
+.BR ssh-agent .
+Otherwise, if this:
+.PP
+.B "      ssh-add -L"
+.PP
+provides any output, it uses that in preference to the identity file.
+.PP
+If the
+.B -i
+option is used, or the
+.B ssh-add
+produced no output, then it uses the contents of the identity
+file.  Once it has one or more fingerprints (by whatever means) it
+uses ssh to append them to
+.B ~/.ssh/authorised_keys
+on the remote machine (creating the file, and directory, if necessary)
+
+.SH "SEE ALSO"
+.BR ssh (1),
+.BR ssh-agent (1),
+.BR sshd (8)