summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/ssh/COPYING.Ylonen220
-rw-r--r--usr.bin/ssh/ChangeLog578
-rw-r--r--usr.bin/ssh/INSTALL409
-rw-r--r--usr.bin/ssh/Makefile344
-rw-r--r--usr.bin/ssh/Makefile.in344
-rw-r--r--usr.bin/ssh/OVERVIEW226
-rw-r--r--usr.bin/ssh/README563
-rw-r--r--usr.bin/ssh/README.AFS-KERBEROS44
-rw-r--r--usr.bin/ssh/RFC2187
-rw-r--r--usr.bin/ssh/RFC.nroff1780
-rw-r--r--usr.bin/ssh/acconfig.h186
-rw-r--r--usr.bin/ssh/auth-krb4.c218
-rw-r--r--usr.bin/ssh/auth-passwd.c343
-rw-r--r--usr.bin/ssh/auth-rhosts.c332
-rw-r--r--usr.bin/ssh/authfd.c669
-rw-r--r--usr.bin/ssh/authfd.h109
-rw-r--r--usr.bin/ssh/authfile.c315
-rw-r--r--usr.bin/ssh/bf_enc.c241
-rw-r--r--usr.bin/ssh/bf_locl.h242
-rw-r--r--usr.bin/ssh/bf_pi.h325
-rw-r--r--usr.bin/ssh/bf_skey.c119
-rw-r--r--usr.bin/ssh/blowfish.h116
-rw-r--r--usr.bin/ssh/bufaux.c170
-rw-r--r--usr.bin/ssh/bufaux.h51
-rw-r--r--usr.bin/ssh/buffer.c150
-rw-r--r--usr.bin/ssh/buffer.h66
-rw-r--r--usr.bin/ssh/canohost.c237
-rw-r--r--usr.bin/ssh/channels.c1559
-rw-r--r--usr.bin/ssh/check-fds.c43
-rw-r--r--usr.bin/ssh/cipher.c418
-rw-r--r--usr.bin/ssh/cipher.h109
-rw-r--r--usr.bin/ssh/clientloop.c973
-rw-r--r--usr.bin/ssh/compress.c160
-rw-r--r--usr.bin/ssh/compress.h46
-rw-r--r--usr.bin/ssh/config.cache102
-rw-r--r--usr.bin/ssh/config.guess1012
-rw-r--r--usr.bin/ssh/config.h443
-rw-r--r--usr.bin/ssh/config.h.in442
-rw-r--r--usr.bin/ssh/config.log420
-rw-r--r--usr.bin/ssh/config.sample62
-rw-r--r--usr.bin/ssh/config.status536
-rw-r--r--usr.bin/ssh/config.sub1238
-rw-r--r--usr.bin/ssh/configure5293
-rw-r--r--usr.bin/ssh/configure.in815
-rw-r--r--usr.bin/ssh/crc32.c120
-rw-r--r--usr.bin/ssh/crc32.h25
-rw-r--r--usr.bin/ssh/fdlim.h69
-rw-r--r--usr.bin/ssh/gen_minfd.c123
-rw-r--r--usr.bin/ssh/getput.h64
-rw-r--r--usr.bin/ssh/host_config.sample29
-rw-r--r--usr.bin/ssh/hostfile.c275
-rw-r--r--usr.bin/ssh/includes.h263
-rw-r--r--usr.bin/ssh/install-sh238
-rw-r--r--usr.bin/ssh/log-client.c137
-rw-r--r--usr.bin/ssh/log-server.c242
-rw-r--r--usr.bin/ssh/login.c399
-rw-r--r--usr.bin/ssh/match.c78
-rw-r--r--usr.bin/ssh/minfd.c96
-rw-r--r--usr.bin/ssh/mpaux.c93
-rw-r--r--usr.bin/ssh/mpaux.h42
-rw-r--r--usr.bin/ssh/packet.c732
-rw-r--r--usr.bin/ssh/packet.h167
-rw-r--r--usr.bin/ssh/pty.c313
-rw-r--r--usr.bin/ssh/pty.h40
-rw-r--r--usr.bin/ssh/radix.c259
-rw-r--r--usr.bin/ssh/random.c370
-rw-r--r--usr.bin/ssh/randoms.c365
-rw-r--r--usr.bin/ssh/randoms.h77
-rw-r--r--usr.bin/ssh/rc4.c72
-rw-r--r--usr.bin/ssh/rc4.h34
-rw-r--r--usr.bin/ssh/readconf.c670
-rw-r--r--usr.bin/ssh/readconf.h116
-rw-r--r--usr.bin/ssh/readpass.c171
-rw-r--r--usr.bin/ssh/remove.c6
-rw-r--r--usr.bin/ssh/rfc-pg.c49
-rw-r--r--usr.bin/ssh/scp.1127
-rw-r--r--usr.bin/ssh/scp.c1071
-rw-r--r--usr.bin/ssh/servconf.c499
-rw-r--r--usr.bin/ssh/servconf.h77
-rw-r--r--usr.bin/ssh/server_config.sample38
-rw-r--r--usr.bin/ssh/serverloop.c628
-rw-r--r--usr.bin/ssh/ssh-add.198
-rw-r--r--usr.bin/ssh/ssh-add.c247
-rw-r--r--usr.bin/ssh/ssh-agent.1113
-rw-r--r--usr.bin/ssh/ssh-agent.c629
-rw-r--r--usr.bin/ssh/ssh-askpass.wish48
-rw-r--r--usr.bin/ssh/ssh-keygen.1143
-rw-r--r--usr.bin/ssh/ssh-keygen.c552
-rw-r--r--usr.bin/ssh/ssh.11003
-rw-r--r--usr.bin/ssh/ssh.1.in1003
-rw-r--r--usr.bin/ssh/ssh.c813
-rw-r--r--usr.bin/ssh/ssh.h596
-rw-r--r--usr.bin/ssh/ssh_md5.c237
-rw-r--r--usr.bin/ssh/ssh_md5.h27
-rw-r--r--usr.bin/ssh/sshconnect.c1434
-rw-r--r--usr.bin/ssh/sshd.8734
-rw-r--r--usr.bin/ssh/sshd.8.in734
-rw-r--r--usr.bin/ssh/sshd.c2373
-rw-r--r--usr.bin/ssh/tildexpand.c71
-rw-r--r--usr.bin/ssh/ttymodes.c499
-rw-r--r--usr.bin/ssh/ttymodes.h138
-rw-r--r--usr.bin/ssh/uidswap.c126
-rw-r--r--usr.bin/ssh/uidswap.h30
-rw-r--r--usr.bin/ssh/version.h1
-rw-r--r--usr.bin/ssh/xmalloc.c60
-rw-r--r--usr.bin/ssh/xmalloc.h34
106 files changed, 44172 insertions, 0 deletions
diff --git a/usr.bin/ssh/COPYING.Ylonen b/usr.bin/ssh/COPYING.Ylonen
new file mode 100644
index 00000000000..73d3ecaa7b1
--- /dev/null
+++ b/usr.bin/ssh/COPYING.Ylonen
@@ -0,0 +1,220 @@
+This file is part of the ssh software, Copyright (c) 1995 Tatu Ylonen, Finland
+
+
+COPYING POLICY AND OTHER LEGAL ISSUES
+
+As far as I am concerned, the code I have written for this software
+can be used freely for any purpose. Any derived versions of this
+software must be clearly marked as such, and if the derived work is
+incompatible with the protocol description in the RFC file, it must be
+called by a name other than "ssh" or "Secure Shell".
+
+However, I am not implying to give any licenses to any patents or
+copyrights held by third parties, and the software includes parts that
+are not under my direct control. As far as I know, all included
+source code is used in accordance with the relevant license agreements
+and can be used freely for any purpose (the GNU license being the most
+restrictive); see below for details.
+
+[ IDEA is now *only* included if configured with --with-rsa. ]
+The RSA algorithm and even the concept of public key encryption are
+claimed to patented in the United States. These patents may interfere
+with your right to use this software. It is possible to compile the
+software using the RSAREF2 library by giving --with-rsaref on the
+configure command line. This may or may not make it legal to use this
+software for non-commercial purposes in the United States (I have sent
+a query about this to RSADSI (on July 10, 1995), but have not received
+an answer yet). The RSAREF2 distribution is not included in this
+distribution, but can be obtained from almost any ftp site worldwide
+containing cryptographic materials. Using RSAREF is not recommended
+outside the United States. See "http://www.cs.hut.fi/crypto" if you
+have trouble finding the RSAREF library.
+
+[ IDEA is now *only* included if configured with --with-idea. ]
+The IDEA algorithm is claimed to be patented in the United States and
+several other countries. I have been told by Ascom-Tech (the patent
+holder) that IDEA can be used freely for non-commercial use. A copy
+of their letter is at the end. The software can be compiled without
+IDEA by specifying the --without-idea option on the configure command
+line.
+
+[ All these files are now external to the distribution. ]
+The DES implementation in this distribution is derived from the libdes
+library by Eric Young <eay@mincom.oz.au>. It can be used under the
+Gnu General Public License (libdes-COPYING) or the Artistic License
+(libdes-ARTISTIC), at your option. See libdes-README for more
+information. Eric Young has kindly given permission to distribute the
+derived version under these terms. The file crypt.c is fcrypt.c from
+SSLeay-0.4.3a by Eric Young; he permits free use.
+
+[ GMP is no longer part of the distribution. ]
+The GNU Multiple Precision Library, included in this release and
+linked into the executable, is distributed under the GNU General
+Public License. A copy can be found in gmp-1.3.2/COPYING.
+
+[ Zlib is no longer part of the distribution. ]
+The zlib compression library is copyright Jean-loup Gailly and Mark
+Adler. Anyone is permitted to use the library for any purpose. A
+copy of the license conditions can be found in zlib095/README.
+
+[ This script is no longer part of the distribution. ]
+The make-ssh-known-hosts script was contributed by Tero Kivinen
+<kivinen@niksula.hut.fi> and is distributed under the GNU General
+Public License. A copy can be found in gnu-COPYING-GPL.
+
+Some files, such as memmove.c and random.c, are owned by the Regents
+of the University of California, and can be freely used and
+distributed. License terms are included in the affected files. The
+file scp.c is derived from code owned by the Regents of the University
+of California, and can be used freely.
+
+[ TSS has been removed from the distribution. ]
+The TSS encryption algorithm implementation in tss.c is copyright Timo
+Rinne <tri@iki.fi> and Cirion Oy. It is used with permission, and
+permission has been given for anyone to use it for any purpose as part
+of ssh.
+
+The MD5 implementation in md5.c was taken from PGP and is due to Colin
+Plumb. Comments in the file indicate that it is in the public domain.
+
+The 32-bit CRC implementation in crc32.c is due to Gary S. Brown.
+Comments in the file indicate it may be used for any purpose without
+restrictions.
+
+
+In some countries, particularly France, Russia, Iraq, and Pakistan, it
+may be illegal to use any encryption at all without a special permit,
+and the rumor is that you cannot get a permit for any strong
+encryption.
+
+If you are in the United States, you should be aware that while this
+software was written outside the United States using information
+publicly available everywhere, the United States Government may
+consider it a criminal offence to export this software from the United
+States once it has been imported. I have been told that "the federal
+mandatory sentencing guidelines for this offence are 41 to 51 months
+in federal prison". The rumor is that the government considers
+putting the software available on an ftp site the same as exporting
+it. Contact the Office of Defence Trade Controls if you need more
+information. Also, please write to your congress and senate
+representatives to get these silly and unconstitutional restrictions
+dropped.
+
+Note that any information and cryptographic algorithms used in this
+software are publicly available on the Internet and at any major
+bookstore, scientific library, and patent office worldwide. More
+information can be found e.g. at "http://www.cs.hut.fi/crypto".
+
+The legal status of this program is some combination of all these
+permissions and restrictions. Use only at your own responsibility.
+You will be responsible for any legal consequences yourself; I am not
+making any claims whether possessing or using this is legal or not in
+your country, and I am not taking any responsibility on your behalf.
+
+
+ NO WARRANTY
+
+BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+---------------------------------------------------------------------------
+Below is a copy of a message I received from Ascom, the holder of the IDEA
+patent.
+
+Date: Tue, 15 Aug 95 09:09:59 CET
+From: IDEA@ascom.ch (Licensing Systec)
+Encoding: 3001 Text
+To: ylo@cs.hut.fi
+Subject: Phone Call 15.8.95
+
+ Dear Mr. Ylonen
+
+ Thank you for your inquiry about the IDEA encryption algorithm.
+ Please excuse the delay in answering your fax sent 26.6.95.
+ Here is the information you requested :
+
+ Non commercial use of IDEA is free. The following examples (regarding
+ PGP) should clarify what we mean by commercial and non-commercial use
+
+ Here are some examples of commercial use of PGP:
+
+ 1. When PGP is used for signing and/or encrypting e-mail messages
+ exchanged between two corporations.
+
+ 2. When a consultant uses PGP for his communications with his client
+ corporations.
+
+ 3. When a bank makes PGP available to its clients for telebanking and
+ charges them money for it (directly or indirectly).
+
+ 4. When you use the software you receive from a company for commercial
+ purposes (telebanking included).
+
+
+ Some examples of non commercial use:
+
+ 1. When an individual uses PGP for his private communications.
+
+ 2. When an individual obtains PGP on the Internet and uses it for
+ telebanking (assuming this is approved by the bank).
+
+ 3. When you use the software you receive from a company for private
+ purposes (telebanking excluded).
+
+
+ You may use IDEA freely within your software for non commercial use.
+ If you include IDEA in your software, it must include the following
+ copy right statement :
+
+ 1. Copyright and Licensing Statement
+ IDEA(tm) is a trademark of Ascom Systec AG. There is no license fee
+ required for non-commercial use. Commercial users of IDEA may
+ obtain licensing information from Ascom Systec AG.
+ e-mail: IDEA@ascom.ch
+ fax: ++41 64 56 59 54
+
+
+ For selling the software commercially a product license is required:
+
+ The PRODUCT LICENSE gives a software developer the right to implement
+ IDEA in a software product and to sell this product worldwide. With
+ the PRODUCT LICENSE we supply a source listing in C and a software
+ manual. We charge an initial fee per company and a percentage of sales
+ of the software product or products (typically between .5 and 4 per
+ cent of the sales price, depending on the price and the importance of
+ IDEA for the product).
+
+
+ For further information please do not hesitate to contact us.
+
+ Best regards,
+
+ Roland Weinhart
+
+
+ Ascom Systec Ltd
+ IDEA Licensing @@@@@ @@@@@ @@@@@ @@@@@ @@@@@@@
+ Gewerbepark @ @ @ @ @ @ @ @
+ CH-5506 Maegenwil @@@@@ @@@@@ @ @ @ @ @ @
+ Switzerland @ @ @ @ @ @ @ @ @
+ Phone ++41 64 56 59 54 @@@@@ @@@@@ @@@@@ @@@@@ @ @ @
+ Fax ++41 64 56 59 98
+
+
diff --git a/usr.bin/ssh/ChangeLog b/usr.bin/ssh/ChangeLog
new file mode 100644
index 00000000000..08d90f78d31
--- /dev/null
+++ b/usr.bin/ssh/ChangeLog
@@ -0,0 +1,578 @@
+Fri Nov 17 16:19:20 1995 Tatu Ylonen <ylo@trance.olari.clinet.fi>
+
+ * Released 1.2.12.
+
+ * channels.c: Commented out debugging messages about output draining.
+
+ * Added file OVERVIEW to give some idea about the structure of the
+ ssh software.
+
+Thu Nov 16 16:40:17 1995 Tatu Ylonen <ylo@trance.olari.clinet.fi>
+
+ * canohost.c (get_remote_hostname): Don't ever return NULL (causes
+ segmentation violation).
+
+ * sshconnect.c: Host ip address printed incorrectly with -v.
+
+ * Implemented SSH_TTY environment variable.
+
+Wed Nov 15 01:47:40 1995 Tatu Ylonen <ylo@trance.olari.clinet.fi>
+
+ * Implemented server and client option KeepAlive to specify
+ whether to set SO_KEEPALIVE. Both default to "yes"; to disable
+ keepalives, set the value to "no" in both the server and the
+ client configuration files. Updated manual pages.
+
+ * sshd.c: Fixed Solaris utmp problem: wrong pid stored in utmp
+ (patch from Petri Virkkula <argon@bat.cs.hut.fi>).
+
+ * login.c (record_logout): Fixed removing user from utmp on BSD
+ (with HAVE_LIBUTIL_LOGIN).
+
+ * Added cleanup functions to be called from fatal(). Arranged for
+ utmp to be cleaned if sshd terminates by calling fatal (e.g.,
+ after dropping connection). Eliminated separate client-side
+ fatal() functions and moved fatal() to log-client.c. Made all
+ cleanups, including channel_stop_listening() and packet_close()
+ be called using this mechanism.
+
+Thu Nov 9 09:58:05 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * sshd.c: Permit immediate login with empty password only if
+ password authentication is allowed.
+
+Wed Nov 8 00:43:55 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * Eliminated unix-domain X11 forwarding. Inet-domain forwarding is
+ now the only supported form. Renamed server option
+ X11InetForwarding to X11Forwarding, and eliminated
+ X11UnixForwarding. Updated documentation. Updated RFC (marked
+ the SSH_CMSG_X11_REQUEST_FORWARDING message (code 26) as
+ obsolete, and removed all references to it). Increased protocol
+ version number to 1.3.
+
+ * scp.c (main): Added -B (BatchMode). Updated manual page.
+
+ * Cleaned up and updated all manual pages.
+
+ * clientloop.c: Added new escape sequences ~# (lists forwarded
+ connections), ~& (background ssh when waiting for forwarded
+ connections to terminate), ~? (list available escapes).
+ Polished the output of the connection listing. Updated
+ documentation.
+
+ * uidswap.c: If _POSIX_SAVED_IDS is defined, don't change the real
+ uid. Assume that _POSIX_SAVED_IDS also applies to seteuid.
+ This may solve problems with tcp_wrappers (libwrap) showing
+ connections as coming from root.
+
+Tue Nov 7 20:28:57 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * Added RandomSeed server configuration option. The argument
+ specifies the location of the random seed file. Updated
+ documentation.
+
+ * Locate perl5 in configure. Generate make-ssh-known-hosts (with
+ the correct path for perl5) in Makefile.in, and install it with
+ the other programs. Updated manual page.
+
+ * sshd.c (main): Added a call to umask to set the umask to a
+ reasonable value.
+
+ * compress.c (buffer_compress): Fixed to follow the zlib
+ documentation (which is slightly confusing).
+
+ * INSTALL: Added information about Linux libc.so.4 problem.
+
+Mon Nov 6 15:42:36 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * (Actually autoconf fix) Installed patch to AC_ARG_PROGRAM.
+
+ * sshd.c, sshd.8.in: Renamed $HOME/.environment ->
+ $HOME/.ssh/environment.
+
+ * configure.in: Disable shadow password checking on convex.
+ Convex has /etc/shadow, but sets pw_passwd automatically if
+ running as root.
+
+ * Eliminated HAVE_ETC_MASTER_PASSWD (NetBSD, FreeBSD); the
+ pw_passwd field is automatically filled if running as root.
+ Put explicit code in configure.in to prevent shadow password
+ checking on FreeBSD and NetBSD.
+
+ * serverloop.c (signchld_handler): Don't print error if wait
+ returns -1.
+
+ * Makefile.in (install): Fixed modes of data files.
+
+ * Makefile.in (install): Make links for slogin.1.
+
+ * make-ssh-known-hosts: Merged a patch from melo@ci.uminho.pt to
+ fix the ping command.
+
+Fri Nov 3 16:25:28 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * ssh.1.in: Added more information about X11 forwarding.
+
+Thu Nov 2 18:42:13 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * Changes to use O_NONBLOCK_BROKEN consistently.
+
+ * pty.c (pty_make_controlling_tty): Use setpgid instead of
+ setsid() on Ultrix.
+
+ * includes.h: Removed redundant #undefs for Ultrix and Sony News;
+ these are already handled in configure.in.
+
+Tue Oct 31 13:31:28 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * configure.in: Define SSH_WTMP to /var/adm/wtmp is wtmp not found.
+
+ * configure.in: Disable vhangup on Ultrix. I am told this fixes
+ the server problems.
+
+Sat Oct 28 14:22:05 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * sshconnect.c: Fixed a bug in connecting to a multi-homed host.
+ Restructured the connecting code to never try to use the same
+ socket a second time after a failed connection.
+
+ * Makefile.in: Added explicit -m option to install, and umask 022
+ when creating directories and the host key.
+
+Fri Oct 27 01:05:10 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * Makefile.in: Added cleaning of $(ZLIBDIR) to clean and distclean.
+
+ * login.c (get_last_login_time): Fixed a typo (define -> defined).
+
+Thu Oct 26 01:28:07 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * configure.in: Moved testing for ANSI C compiler after the host
+ specific code (problems on HPUX).
+
+ * Minor fixes to /etc/default/login stuff from Bryan O'Sullivan.
+
+ * Fixed .SH NAME sections in manual pages.
+
+ * compress.c: Trying to fix a mysterious bug in the compression
+ glue.
+
+ * ssh-1.2.11.
+
+ * scp.c: disable agent forwarding when running ssh from scp.
+
+ * Added compression of plaintext packets using the gzip library
+ (zlib). Client configuration options Compression and
+ CompressionLevel (1-9 as in gzip). New ssh and scp option -C
+ (to enable compression). Updated RFC.
+
+Wed Oct 25 05:11:55 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * Implemented ProxyCommand stuff based on patches from Bryan
+ O'Sullivan <bos@serpentine.com>.
+
+ * Merged BSD login/logout/lastlog patches from Mark Treacy
+ <mark@labtam.oz.au>.
+
+ * sshd.c: Added chdir("/").
+
+Tue Oct 24 00:29:01 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * Merged RSA environment= patches from Felix Leitner
+ <leitner@prz.tu-berlin.de> with some changes.
+
+ * sshd.c: Made the packet code use two separate descriptors for
+ the connection (one for input, the other for output). This will
+ make future extensions easier (e.g., non-socket transports, etc.).
+ sshd -i now uses both stdin and stdout separately.
+
+Mon Oct 23 21:29:28 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * sshd.c: Merged execle -> execve patches from Mark Martinec
+ <Mark.Martinec@nsc.ijs.si>. This may help with execle bugs on
+ Convex (environment not getting passed properly). This might
+ also solve similar problems on Sonys; please test!
+
+ * Removed all compatibility code for protocol version 1.0.
+ THIS MEANS THAT WE ARE NO LONGER COMPATIBLE WITH SSH VERSIONS
+ PRIOR TO 1.1.0.
+
+ * randoms.c (random_acquire_light_environmental_noise): If
+ /dev/random is available, read up to 32 bytes (256 bits) from
+ there in non-blocking mode, and mix the new random bytes into
+ the pool.
+
+ * Added client configuration option StrictHostKeyChecking
+ (disabled by default). If this is enabled, the client will not
+ automatically add new host keys to $HOME/.ssh/known_hosts;
+ instead the connection will be refused if the host key is not
+ known. Similarly, if the host key has changed, the connection
+ will be refused instead if just issuing a warning. This
+ provides additional security against man-in-the-middle/trojan
+ horse attacks (especially in scripts where there is no-one to
+ see the warnings), but may be quite inconvenient in everyday
+ interactive use unless /etc/ssh_known_hosts is very complete,
+ because new host keys must now be added manually.
+
+ * sshconnect.c (ssh_connect): Use the user's uid when creating the
+ socket and connecting it. I am hoping that this might help with
+ tcp_wrappers showing the remote user as root.
+
+ * ssh.c: Try inet-domain X11 forwarding regardless of whether we
+ can get local authorization information. If we don't, we just
+ come up with fake information; the forwarding code will anyway
+ generate its own fake information and validate that the client
+ knows that information. It will then substitute our fake
+ information for that, but that info should get ignored by the
+ server if it doesn't support it.
+
+ * Added option BatchMode to disable password/passphrase querying
+ in scripts.
+
+ * auth-rh-rsa.c: Changed to use uid-swapping when reading
+ .ssh/known_hosts.
+
+ * sshd.8.in (command): Improved documentation of file permissions
+ on the manual pages.
+
+Thu Oct 19 21:05:51 1995 Tatu Ylonen <ylo@soikko.cs.hut.fi>
+
+ * ssh-add.c (add_file): Fixed a bug causing ssh to sometimes refer
+ to freed memory (comment -> saved_comment).
+
+ * log-server.c: Added a prefix to debug/warning/error/fatal
+ messages describing message types. Syslog does not include that
+ information automatically.
+
+Sun Oct 8 01:56:01 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Merged /etc/default/login and MAIL environment variable changes
+ from Bryan O'Sullivan <bos@serpentine.com>.
+ - mail spool file location
+ - process /etc/default/login
+ - add HAVE_ETC_DEFAULT_LOGIN
+ - new function child_get_env and read_etc_default_login (sshd.c)
+
+ * ssh-add.c (add_file): Fixed asking for passphrase.
+
+ * Makefile.in: Fixed installing configure-generated man pages when
+ compiling in a separate object directory.
+
+ * sshd.c (main): Moved RSA key generation until after allocating
+ the port number. (Actually, the code got duplicated because we
+ never listen when run from inetd.)
+
+ * ssh.c: Fixed a problem that caused scp to hang when called with
+ stdin closed.
+
+Sat Oct 7 03:08:06 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Added server config option StrictModes. It specifies whether to
+ check ownership and modes of home directory and .rhosts files.
+
+ * ssh.c: If ssh is renamed/linked to a host name, connect to that
+ host.
+
+ * serverloop.c, clientloop.c: Ignore EAGAIN reported on read from
+ connection. Solaris has a kernel bug which causes select() to
+ sometimes wake up even though there is no data available.
+
+ * Display all open connections when printing the "Waiting for
+ forwarded connections to terminate" message.
+
+ * sshd.c, readconf.c: Added X11InetForwarding and
+ X11UnixForwarding server config options.
+
+Thu Oct 5 17:41:16 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Some more SCO fixes.
+
+Tue Oct 3 01:04:34 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Fixes and cleanups in README, INSTALL, COPYING.
+
+Mon Oct 2 03:36:08 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * ssh-add.c (add_file): Fixed a bug in ssh-add (xfree: NULL ...).
+
+ * Removed .BR from ".SH NAME" in man pages.
+
+Sun Oct 1 04:16:07 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * ssh-1.2.10.
+
+ * configure.in: When checking that the compiler works, check that
+ it understands ANSI C prototypes.
+
+ * Made uidswap error message a debug() to avoid confusing errors
+ on AIX (AIX geteuid is brain-damaged and fails even for root).
+
+ * Fixed an error in sshd.8 (FacistLogging -> FascistLogging).
+
+ * Fixed distribution in Makefile.in (missing manual page .in files).
+
+Sat Sep 30 17:38:46 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * auth-rhosts.c: Fixed serious security problem in
+ /etc/hosts.equiv authentication.
+
+Fri Sep 29 00:41:02 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Include machine/endian.h on Paragon.
+
+ * ssh-add.c (add_file): Made ssh-add keep asking for the
+ passphrase until the user just types return or cancels.
+ Make the dialog display the comment of the key.
+
+ * Read use shosts.equiv in addition to /etc/hosts.equiv.
+
+ * sshd.8 is now sshd.8.in and is processed by configure to
+ substitute the proper paths for various files. Ditto for ssh.1.
+ Ditto for make-ssh-known-hosts.1.
+
+ * configure.in: Moved /etc/sshd_pid to PIDDIR/sshd.pid. PIDDIR
+ will be /var/run if it exists, and ETCDIR otherwise.
+
+Thu Sep 28 21:52:42 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * On Ultrix, check if sys/syslog.h needs to be included in
+ addition to syslog.h.
+
+ * make-ssh-known-hosts.pl: Merged Kivinen's fixes for HPUX.
+
+ * configure.in: Put -lwrap, -lsocks, etc. at the head of LIBS.
+
+ * Fixed case-insensitivity in auth-rhosts.c.
+
+ * Added missing socketpair.c to EXTRA_SRCS (needed on SCO), plus
+ other SCO fixes.
+
+ * Makefile.in: Fixed missing install_prefixes.
+
+Wed Sep 27 03:57:00 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * ssh-1.2.9.
+
+ * Added SOCKS support.
+
+ * Fixed default setting of IgnoreRhosts option.
+
+ * Pass the magic cookie to xauth in stdin instead of command line;
+ the command line is visible in ps.
+
+ * Added processing $HOME/.ssh/rc and /etc/sshrc.
+
+ * Added a section to sshd.8 on what happens at login time.
+
+Tue Sep 26 01:27:40 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Don't define speed_t on SunOS 4.1.1; it conflicts with system
+ headers.
+
+ * Added support for .hushlogin.
+
+ * Added --with-etcdir.
+
+ * Read $HOME/.environment after /etc/environment.
+
+Mon Sep 25 03:26:06 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Merged patches for SCO Unix (from Michael Henits).
+
+Sun Sep 24 22:28:02 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Added ssh option ConnectionAttempts.
+
+Sat Sep 23 12:30:15 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * sshd.c: Don't print last login time and /etc/motd if a command
+ has been specified (with ssh -t host command).
+
+ * Added support for passing the screen number in X11 forwarding.
+ It is implemented as a compatible protocol extension, signalled
+ by SSH_PROTOFLAG_SCREEN_NUMBER by the child.
+
+ * clientloop.c: Fixed bugs in the order in which things were
+ processed. This may solve problems with some data not getting
+ sent to the server as soon as possible (probably solves the TCP
+ forwarding delayed close problem). Also, it looked like window
+ changes might not get transmitted as early as possible in some
+ cases.
+
+ * clientloop.c: Changed to detect window size change that
+ happened while ssh was suspended.
+
+ * ssh.c: Moved the do_session function (client main loop) to
+ clientloop.c. Divided it into smaller functions. General cleanup.
+
+ * ssh-1.2.8
+
+Fri Sep 22 22:07:46 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * sshconnect.c (ssh_login): Made ssh_login take the options
+ structure as argument, instead of the individual arguments.
+
+ * auth-rhosts.c (check_rhosts_file): Added support for netgroups.
+
+ * auth-rhosts.c (check_rhosts_file): Added support for negated
+ entries.
+
+Thu Sep 21 00:07:56 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * auth-rhosts.c: Restructured rhosts authentication code.
+ Hosts.equiv now has same format as .rhosts: user names are allowed.
+
+ * Added support for the Intel Paragon.
+
+ * sshd.c: Don't use X11 forwarding with spoofing if no xauth
+ program. Changed configure.in to not define XAUTH_PATH if
+ there is no xauth program.
+
+ * ssh-1.2.7
+
+ * sshd.c: Rewrote the code to build the environment. Now also reads
+ /etc/environment.
+
+ * sshd.c: Fixed problems in libwrap code. --with-libwrap now
+ takes optional library name/path.
+
+ * ssh-1.2.6
+
+ * Define USE_PIPES by default.
+
+ * Added support for Univel Unixware and MachTen.
+
+ * Added IgnoreRhosts server option.
+
+ * Added USE_STRLEN_FOR_AF_UNIX; it is needed at least on MachTen.
+
+Wed Sep 20 02:41:02 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * sshd.c (do_child): don't call packet_close when /etc/nologin,
+ because packet_close does shutdown, and the message does not get
+ sent.
+
+ * pty.c (pty_allocate): Push ttcompat streams module.
+
+ * randoms.c (random_acquire_light_environmental_noise): Don't use
+ the second argument to gettimeofday as it is not supported on
+ all systems.
+
+ * login.c (record_login): Added NULL second argument to gettimeofday.
+
+Tue Sep 19 13:25:48 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * fixed pclose wait() in sshd key regeneration (now only collects
+ easily available noise).
+
+ * configure.in: test for bsdi before bsd*.
+
+ * ssh.c: Don't print "Connection closed" if -q.
+
+Wed Sep 13 04:19:52 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Released ssh-1.2.5.
+
+ * Hopefully fixed "Waiting for forwarded connections to terminate"
+ message.
+
+ * randoms.c, md5.c: Large modifications to make these work on Cray
+ (which has no 32 bit integer type).
+
+ * Fixed a problem with forwarded connection closes not being
+ reported immediately.
+
+ * ssh.c: fixed rhosts authentication (broken by uid-swapping).
+
+ * scp.c: Don't use -l if server user not specified (it made
+ setting User in the configuration file not work).
+
+ * configure.in: don't use -pipe on BSDI.
+
+ * randoms.c: Major modifications to make it work without 32 bit
+ integers (e.g. Cray).
+
+ * md5.c: Major modifications to make it work without 32 bit
+ integers (e.g. Cray).
+
+ * Eliminated HPSUX_BROKEN_PTYS. The code is now enabled by
+ default on all systems.
+
+Mon Sep 11 00:53:12 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * sshd.c: don't include sshd pathname in log messages.
+
+ * Added libwrap stuff (includes support for identd).
+
+ * Added OSF/1 C2 extended security stuff.
+
+ * Fixed interactions between getuid() and uid-swap stuff.
+
+Sun Sep 10 00:29:27 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * serverloop.c: Don't send stdout data to client until after a few
+ milliseconds if there is very little data. This is because some
+ systems give data from pty one character at a time, which would
+ multiply data size by about 16.
+
+ * serverloop.c: Moved server do_session to a separate file and
+ renamed it server_loop. Split it into several functions and
+ partially rewrote it. Fixed "cat /etc/termcap | ssh foo cat" hangup.
+
+ * Screwed up something while checking stuff in under cvs. No harm,
+ but bogus log entries...
+
+Sat Sep 9 02:24:51 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * minfd.c (_get_permanent_fd): Use SHELL environment variable.
+
+ * channels.c (x11_create_display_inet): Created
+ HPSUX_NONSTANDARD_X11_KLUDGE; it causes DISPLAY to contain the
+ IP address of the host instead of the name, because HPSUX uses
+ some magic shared memory communication for local connections.
+
+ * Changed SIGHUP processing in server; it should now work multiple
+ times.
+
+ * Added length limits in many debug/log/error/fatal calls just in
+ case.
+
+ * login.c (get_last_login_time): Fixed location of lastlog.
+
+ * Rewrote all uid-swapping code. New files uidswap.h, uidswap.c.
+
+ * Fixed several security problems involving chmod and chgrp (race
+ conditions). Added warnings about dubious modes for /tmp/.X11-unix.
+
+Fri Sep 8 20:03:36 1995 Tatu Ylonen <ylo@shadows.cs.hut.fi>
+
+ * Changed readconf.c to never display anything from the config
+ file. This should now be prevented otherwise, but let's play safe.
+
+ * log-server.c: Use %.500s in syslog() just to be sure (they
+ should already be shorter than 1024 though).
+
+ * sshd.c: Moved setuid in child a little earlier (just to be
+ conservative, there was no security problem that I could detect).
+
+ * README, INSTALL: Added info about mailing list and WWW page.
+
+ * sshd.c: Added code to use SIGCHLD and wait zombies immediately.
+
+ * Merged patch to set ut_addr in utmp.
+
+ * Created ChangeLog and added it to Makefile.in.
+
+ * Use read_passphrase instead of getpass().
+
+ * Added SSH_FALLBACK_CIPHER. Fixed a bug in default cipher
+ selection (IDEA used to be selected even if not supported by the
+ server).
+
+ * Use no encryption for key files if empty passphrase.
+
+ * Added section about --without-idea in INSTALL.
+
+ * Version 1.2.0 was released a couple of days ago.
+
diff --git a/usr.bin/ssh/INSTALL b/usr.bin/ssh/INSTALL
new file mode 100644
index 00000000000..76cf2ee8902
--- /dev/null
+++ b/usr.bin/ssh/INSTALL
@@ -0,0 +1,409 @@
+This is a hacked-up version of ssh-1.2.12.
+
+The GMP and DES sources are now external to the distribution. To build
+this software it is necessary to first have GMP and a DES
+implementation installed somewhere. Some systems comes with GMP and
+DES preinstalled. If your system doesn't; pick up the GMP sources from
+your favorite GNU ftp site (ftp://prep.ai.mit.edu/pub/gnu/). There is
+a free DES implementation made by Eric Young that can be found under
+the name libdes-x.x.x.tar.gz, for example at
+ftp://ftp.psy.uq.oz.au/pub/Crypto/DES/.
+
+The distribution optionally supports Kerberos version 4 authentication
+and AFS. If you want to build with Kerberos support and your system
+comes with Kerberos preinstalled add the switch --with-krb4=/usr to
+configure. Otherwise, first build and install Kerberos and then use
+--with-krb4=/usr/whatever-directory. If you don't want Kerberos
+support use --without-krb4 (the default). Kerberos can be found at
+ftp://ftp.pdc.kth.se/pub/krb/src/.
+
+Compression support is now optional. If you don't have zlib installed
+configure using --without-zlib or first install zlib. We have
+succesfully used zlib-1.0.4.tar.gz
+
+For more detailed installation instructions read the rest of this file
+and README.AFS-KERBEROS.
+
+----------------------------------------------------------------------------
+This file describes how to install the Secure Shell (ssh). Secure Shell is
+a replacement for rlogin and rsh. It seamlessly encrypts all communications,
+provides improved security, and has useful new features.
+
+
+INSTALLATION
+
+For most machines and configurations, the following is all you need.
+
+ ./configure
+ make
+ make install
+
+Then check (and edit if needed) the following files:
+ /etc/sshd_config (server configuration file)
+ /etc/ssh_config (client configuration file - defaults for users)
+
+You may also want to create the /etc/ssh_known_hosts for your site and update
+it periodically. See the manual page for make-ssh-known-hosts on how to
+do this easily. The file format is documented on the sshd manual page.
+
+The source is written in ANSI C, and requires an ANSI C compiler or GCC.
+A copy of GCC is available on all major FTP sites (e.g., in
+ftp:/prep.ai.mit.edu/pub/gnu).
+
+
+CONFIGURATION OPTIONS
+
+The package comes with an Autoconf-generated configure script. The
+script accepts several options
+ All standard options, including:
+ --prefix=PREFIX where to install files (default: subdirs of /usr/local)
+ --exec_prefix=PREFIX where to install executables (default: same as prefix)
+ --srcdir=DIR find sources in DIR (default: where configure is)
+ Specific options:
+ --with-rsh=PATH Use rsh specified by PATH when needed
+ --with-etcdir=PATH Store system files in the given dir (default: /etc)
+ --with-path=PATH Default path to pass to user shell.
+ --with-rsaref Use rsaref2 from rsaref2 subdirectory (see below).
+ --with-libwrap[=PATH] Use libwrap (tcp_wrappers) and identd (see below).
+ --with-socks[=PATH] Include SOCKS (firewall traversal) support.
+ --without-idea Don't include IDEA (see below).
+ --with-securid[=PATH] Support for the SecurID card (see README.SECURID).
+ --enable-warnings Adds -Wall to CFLAGS if using gcc.
+
+You may also want to configure the following variables:
+ CC=compiler specify name of the C compiler (default: gcc or cc)
+ CFLAGS=flags specify flags to C compiler (default: -O -g or just -O)
+ LDFLAGS=flags specify flags to linker (default: none)
+
+Alternate values can be given to configure in the environment, e.g.:
+ CC=xcc CFLAGS="-O2" LDFLAGS="-L/lib/zzz" ./configure
+(Note that if you have already configured, and later decide to give
+some values on the command line, you may need to say "make distclean"
+before reconfiguring.)
+
+
+CONFIGURATION FILES
+
+The server has a configuration file /etc/sshd_config, which specifies the
+permitted authentication methods, hosts, port number, etc. The defaults are
+acceptable for most sites, but you may want to check this file. Its format
+is documented on the sshd manual page.
+
+The client reads a configuration file /etc/ssh_config, which gives
+site-wide defaults for various options. Options in this file can be
+overridden by per-user configuration files. The file is documented on
+the ssh manual page.
+
+
+MAKEFILE
+
+The Makefile is generated from Makefile.in by running configure. It supports
+the following targets:
+ all: compile everything
+ install: install in $exec_prefix/bin and $prefix/man/man1.
+ uninstall: remove installed files
+ clean: remove object files and executables
+ distclean: remove anything not in the distribution
+
+
+PORTABILITY
+
+This software has been used at least in the following environments.
+
+ 386BSD 0.1; i386
+ AIX 3.2.5, 4.1; RS6000, PowerPC
+ BSD 4.4; several platforms
+ BSD/OS 1.1, 2.0.1; i486
+ BSD/386 1.1; i386
+ ConvexOS 10.1; Convex
+ DGUX 5.4R2.10; DGUX
+ FreeBSD 1.x, 2.x; Pentium
+ HPUX 9.0x, 10.0; HPPA
+ IRIX 5.2, 5.3; SGI Indy
+ IRIX 6.0.1; Mips-R8000
+ Linux 1.2.8 Slackware 2.1.0; i486
+ Mach3; Mips
+ Mach3/Lites; i386
+ Machten 2.2
+ NetBSD 1.0A; Pentium, Sparc
+ OSF/1 3.0, 3.2, 3.2a; Alpha
+ Sequent Dynix/ptx 3.2.0 V2.1.0; i386
+ SCO Unix; i386 (client only)
+ SINIX 5.42; Mips R4000
+ Solaris 2.3, 2.4; Sparc
+ Sony NEWS-OS 3.3 (BSD 4.3); m68k
+ SunOS 4.1.2, 4.1.3, 4.1.4; Sparc
+ SysV 4.x; several platforms
+ Ultrix x.x; Mips
+ Unicos 8.0.3; Cray C90
+
+Please report back any other environments where you have used ssh,
+and send back any patches you had to do so that they can be integrated
+to the distribution. The proper address is ossh-bugs@sics.se.
+Always remember to mention the ssh version number and machine type in
+your bug reports. Please include also the output of the -v option
+from the client side, and the output of the -d option from the server,
+if applicable.
+
+Not all compilers work in all environments. If you have problems, try
+compiling with gcc-2.7. *** SPARC NOTE: gcc-2.7.0 appears to generate
+bad code on Sparc (Solaris 2.3) when compiling without -O. Try
+gcc-2.6.3 or compile with -O. ***
+
+Solaris 2.4 note: you need to install "kernel jumbo patch number
+101945-32" (dated August 31, 1995) for ssh to work. The symptom is
+that ssh dies with a "Resource temporarily unavailable" error.
+
+Linux note: Some linux systems have a bug which causes an error about
+libc.so.4 when compiling ssh. This can be solved by any of the
+following ways:
+ - Do "ln -s libc.sa /usr/lib/libg.sa" as root.
+ - Install gcc-2.7.0.
+ - Configure ssh with "CFLAGS=-O ./configure" (i.e., without debug info).
+More information on this problem is available in
+ftp://ftp.netcom.com/pub/ze/zenon/linux.
+
+BSDI BSD/OS note: Apparently the gcc that comes with BSD/OS is
+broken. Use "CC=cc ./configure" or "setenv CC cc; ./configure" when
+configuring to force it to use cc instead of gcc.
+
+ConvexOS note: Convex "make" is broken. Install GNU make first if you
+have trouble compiling ssh.
+
+
+COMPILING WITH RSAREF2
+
+If you are using ssh in the United States, you may want to use the
+RSAREF2 library from RSADSI. This may make it legal to use ssh
+without a separate license for non-commercial purposes. RSAREF2 is
+not included in the distribution; however, it is available on any
+major ftp site around the world (e.g.,
+ftp://ftp.funet.fi/pub/crypt/cryptography/asymmetric/rsa/rsaref2.tar.gz).
+The RSAREF2 distribution should be unpacked into "rsaref2"
+subdirectory in the ssh distribution directory (a symbolic link to
+rsaref2 is not sufficient). Configure should be given the
+--with-rsaref option. (Note that there is no need to *compile*
+rsaref2 manually; the ssh Makefile will compile those files it needs.)
+
+Using RSAREF outside the United States is not recommended and only
+causes legal complications.
+
+RSAREF2 does not work for large key sizes (> 1024). This may be the
+problem if you get "RSAPrivateDecrypt failed".
+
+On alpha, one should edit rsaref2/source/global.h, and make UINT4
+"unsigned int" instead of "unsigned long int".
+
+
+LIBWRAP AND IDENTD
+
+Ssh does not normally use identd or tcp-wrappers. However, it can be
+compiled to use these by adding --with-libwrap on the command line.
+This requires that the tcp_wrappers libwrap.a library and the
+associated tcpd.h have been installed somewhere where the compiler can
+find them. With libwrap support, ssh will process the
+/etc/hosts.allow and /etc/hosts.deny files, and use identd if required
+by them. The name of the user on the client side (as returned by
+identd) will be logged if requested by the configuration files. See
+tcp_wrappers documentation for more information.
+
+
+COMPILING WITHOUT IDEA
+
+The IDEA cipher can be freely used for non-commercial use. However,
+commercial use may require a license in a number of countries.
+
+Ssh can be compiled without IDEA by using the --without-idea configure
+option. This disables IDEA, and causes 3DES to be used for encrypting
+key/identity files and as the default session cipher. (The default
+session cipher can be changed by editing SSH_FALLBACK_CIPHER in
+ssh.h.)
+
+If one disables IDEA after having used it for some time, it is
+possible that there are key files around that were encrypted with IDEA.
+
+Key files can be converted to use 3DES by creating a special version
+of ssh-keygen that includes IDEA (was compiled without
+--without-idea), but that generates key files encrypted with 3DES
+(edit SSH_AUTHFILE_CIPHER to be SSH_CIPHER_3DES even when WITHOUT_IDEA
+is not defined). Any operation with re-encrypts the key file can be
+used, such as changing the comment or changing the passphrase.
+
+
+STARTING THE SERVER
+
+The server should be started at boot from /etc/rc or equivalent. It
+need not be given any arguments; however, an optional "-b bits" flag
+may be used to specify RSA key size (default is 768). Key sizes less
+than 512 can be broken; larger key sizes generally mean more security
+but require more time to generate and use. 1024 bits is secure for
+any practical time with current technology.
+
+The server is not started using inetd, because it needs to generate
+the RSA key before serving the connection, and this can take about a
+minute on slower machines. On a fast machine, and small (breakable)
+key size (< 512 bits) it may be feasible to start the server from
+inetd on every connection. The server must be given "-i" flag if
+started from inetd.
+
+
+REPLACING RLOGIN AND RSH
+
+This software has been designed so that it can be installed with the
+names rlogin, rsh, and rcp, and it will use the Secure Shell
+protocol whenever the remote machine supports it, and will
+automatically execute rlogin/rsh (after displaying a warning that
+there is no encryption) if the remote host does not support Secure
+Shell.
+
+Rlogin/rsh replacement is done as follows:
+ ./configure --with-rsh=RSH-PATH --program-transform-name='s/^s/r/'
+ make install
+
+where RSH-PATH is the complete pathname of the real rsh program. (You
+may want to copy the old rsh program to a suitable location).
+
+This will create links for rlogin, rsh, and rcp. If you are
+installing them in the same directory where rlogin etc. normally are
+(e.g., /usr/bin), you must first move the original programs to some
+other directory (e.g., /usr/lib/rsh).
+
+When doing this, you should also build a file containing the host keys of all
+machines in your organization, and copy this file to /etc/ssh_known_hosts
+on every machine. This will make .rhosts and /etc/hosts.equiv authentication
+work for users without any changes to the user configuration, but will be
+much more secure than conventional .rhosts and /etc/hosts.equiv authentication.
+This will also protect the users against router attacks where someone (perhaps
+remotely) reconfigures the routers to direct connections to a certain host
+to a different machine, which can then grab any passwords which the user
+types thinking he/she is connected to the real machine.
+
+
+CLIENT SUID ROOT, SERVER RUN AS ROOT
+
+This package installs two programs that need special privileges. Ssh
+is the client program, and it is by default installed as suid root,
+because it needs to create a privileged port in order to use .rhosts
+files for authentication. If it is not installed as suid root, it will
+still be usable, but .rhosts authentication will not be available. Also, the
+private host key file is readable by root only.
+
+Sshd is the daemon that listens for connections. It should preferably
+be run as root, because it is by normally listening on a privileged
+port, and it needs to be able to do setuid(), update utmp, chown ptys
+etc. when a user logs in. If it is not run as root, explicit "-p
+port" option must be given to specify an alternate port (same port
+must also be specified for clients), "-h host_key_file_path" must be
+given to specify an alternate host key file, and it cannot be used to
+log in as any other user than the user running it (because it cannot
+call setuid()). Also, if your system uses shadow passwords, password
+authentication will not work when running as someone else than root.
+
+Both the server and the client have been carefully screened for
+possible security problems, and are believed to be secure. However,
+there can be no guarantee. If you find any problems, please report
+them immediately.
+
+
+COMMON PROBLEMS
+
+This section lists some common installation problems.
+
+Shadow passwords
+
+ There are many different shadow password schemes. Ssh currently recognizes
+ and supports many of them; however, there are probably still many that
+ it does not understand. This may not be visible at compile time.
+ If your system uses shadow passwords, and password authentication does not
+ work even if sshd is running as root, this is probably your problem.
+ Please contact the author if this happens. Code to recognize (configure.in)
+ and use (auth-passwd.c) the shadow password mechanism on new systems
+ is highly welcome.
+
+login.c does not compile, or logging of logins does not work properly
+
+ Mechanisms for updating wtmp, utmp, lastlog, and similar mechanisms
+ are not standardized. Ssh substitutes many of the functions of the
+ conventional login program. These functions are implemented in login.c.
+ You may need to modify this file to make it work on exotic systems.
+ Please send any modifications and bug fixes back to the author for inclusion
+ in the distribution. If you just want to try ssh, and cannot get this file
+ to compile, if is safe to define all of the functions as empty; however,
+ in that case logins will not be logged.
+
+Sshd does not start or dies immediately
+
+ The easiest thing to do is to give the -d option to sshd. It will
+ then send debugging output to stderr (and syslog). The -d option
+ also has other side effects, e.g. the daemon will not fork and will
+ only serve a single connection before exiting. However, it is very
+ useful for debugging problems.
+
+ Sshd sends debugging output to the system log. Check your system
+ log (and syslogd configuration) to see why it dies. One possible
+ reason is that your system does not have a proper host key in
+ /etc/ssh_host_key. You can either generate a key with ssh-keygen
+ (it is automatically generated by "make install"), or specify an
+ alternative key with the -h option to the server. Another reason
+ could be that the port which the server tries to listen is already
+ reserved by some other program.
+
+Rhosts authentication does not work
+
+ By default, the server does not accept normal .rhosts or /etc/hosts.equiv
+ authentication, because they are fundamentally insecure and can be spoofed
+ by anyone with access to the local network. Rhosts authentication can be
+ enabled at compile time by giving the --with-rhosts option to configure.
+
+ The preferred alternative is to collect the public host keys of the entire
+ site to a file, and copy this to /etc/ssh_known_hosts on every machine in
+ the organization running sshd. This will prevent all IP spoofing attacks
+ and provides improved security (provided rshd, rlogind, and rexecd are
+ disabled).
+
+Opening connections is too slow
+
+ On very slow machines, encrypting and decrypting the session key may
+ be too slow. For example, on a heavily loaded sun3 it took
+ several minutes to log in with the default key sizes. When we changed it
+ to use shorter host key (512 bits) and server key (384 bits),
+ login time dropped to about a second. A symptom of this problem is
+ that "ssh -v hostname" waits for a long time after printing "Sent
+ encrypted session key".
+
+ Shorter host keys can be generated with "ssh-keygen -b 512", giving
+ /etc/ssh_host_key as the file in which to save the key (with empty
+ passphrase). The server key size can be specified with the -b
+ option on sshd command line (typically, in /etc/rc.local). The
+ server must be restarted for changes to take effect.
+
+The program complains "Could not set controlling tty" or something similar
+
+ There are many different styles of pseudo ttys. Ssh currently
+ supports about five different styles (plus variations of them). It
+ is quite possible that there are more variations, some of which are
+ not supported by existing code. Fixing the problem may require
+ adding new code in pty.c and configure.in. You are encouraged to
+ write the needed code and send a patch to the author, or at least
+ report the problem.
+
+General problem solving
+
+ The client has -v option, which sends verbose output to stdout. It
+ is very helpful in solving problems.
+
+ The server has -d option, which causes it to send verbose debugging
+ output to system log and stderr. This option also causes the server
+ to only serve a single connection and not fork, which helps debugging.
+
+
+REPORTING PROBLEMS AND OTHER CONTACTS
+
+Please report any bugs, problems, and enhancements to
+ossh-bugs@sics.se.
+
+There is a mailing list for ossh. It is ossh@sics.se. If you would
+like to join, send a message to majordomo@sics.se with "subscribe
+ossh" in body.
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland.
diff --git a/usr.bin/ssh/Makefile b/usr.bin/ssh/Makefile
new file mode 100644
index 00000000000..15edbc03b8f
--- /dev/null
+++ b/usr.bin/ssh/Makefile
@@ -0,0 +1,344 @@
+# Generated automatically from Makefile.in by configure.
+#
+# Makefile.in
+#
+# Author: Tatu Ylonen <ylo@cs.hut.fi>
+#
+# Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+# All rights reserved
+#
+# Created: Wed Mar 22 17:37:49 1995 ylo
+#
+# $Id: Makefile,v 1.1 1999/09/26 20:53:32 deraadt Exp $
+#
+
+srcdir = .
+
+
+install_prefix =
+prefix = /usr/local
+exec_prefix = ${prefix}
+bindir = $(exec_prefix)/bin
+sbindir = $(exec_prefix)/sbin
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man8dir = $(mandir)/man8
+etcdir = /etc
+piddir = /var/run
+
+CC = gcc -pipe
+CFLAGS = -g -O2
+LDFLAGS =
+DEFS = -DHAVE_CONFIG_H
+LIBS = -lkrb -lz -lcrypto -ldes -lgmp -lutil
+LIBOBJS =
+CONFOBJS = bf_skey.o bf_enc.o compress.o
+
+MAKEDEP = makedepend
+LN_S = ln -s
+RANLIB = ranlib
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+WISH = /usr/local/bin/wish
+
+GMPLIBS = -lgmp
+GMPINCS =
+
+KRB4_AUTH =
+KRB4_ROOT =
+KRB4_INCS =
+KRB4_LIBS =
+RADIX =
+
+RSAREFDEP =
+
+transform = s,x,x,
+
+HOST_KEY_FILE = $(etcdir)/ssh_host_key
+HOST_CONFIG_FILE = $(etcdir)/ssh_config
+SERVER_CONFIG_FILE = $(etcdir)/sshd_config
+
+SHELL = /bin/sh
+
+#ZLIBLIBS = -L$(ZLIBDIR) -lz
+#ZINCS =
+
+RSAREFDIR = rsaref2
+RSAREFSRCDIR = $(RSAREFDIR)/source
+
+CIPHER_OBJS = cipher.o $(CONFOBJS)
+COMMON_OBJS = $(LIBOBJS) \
+ rsa.o randoms.o ssh_md5.o buffer.o packet.o \
+ xmalloc.o ttymodes.o channels.o bufaux.o authfd.o authfile.o crc32.o \
+ rsaglue.o match.o mpaux.o minfd.o $(CIPHER_OBJS)
+SSHD_OBJS = sshd.o $(KRB4_AUTH) auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o \
+ log-server.o login.o hostfile.o canohost.o servconf.o tildexpand.o \
+ uidswap.o serverloop.o $(RADIX) $(COMMON_OBJS)
+SSH_OBJS = ssh.o sshconnect.o log-client.o readconf.o hostfile.o readpass.o \
+ tildexpand.o uidswap.o clientloop.o canohost.o $(RADIX) $(COMMON_OBJS)
+KEYGEN_OBJS = ssh-keygen.o log-client.o readpass.o rsa.o randoms.o ssh_md5.o \
+ buffer.o xmalloc.o authfile.o $(CIPHER_OBJS) mpaux.o \
+ bufaux.o $(LIBOBJS)
+AGENT_OBJS = ssh-agent.o log-client.o rsa.o randoms.o ssh_md5.o buffer.o \
+ xmalloc.o bufaux.o authfd.o authfile.o rsaglue.o $(CIPHER_OBJS) \
+ mpaux.o minfd.o $(LIBOBJS)
+ADD_OBJS = ssh-add.o log-client.o readpass.o rsa.o randoms.o ssh_md5.o buffer.o \
+ xmalloc.o bufaux.o authfd.o authfile.o $(CIPHER_OBJS) \
+ mpaux.o minfd.o $(LIBOBJS)
+SCP_OBJS = scp.o xmalloc.o
+GEN_MINFD_OBJS = gen_minfd.o $(LIBOBJS)
+
+USER_SHELLS = sh jsh ksh csh tcsh bash zsh ash
+
+SRCS = $(SSHD_OBJS:.o=.c) $(SSH_OBJS:.o=.c) $(KEYGEN_OBJS:.o=.c) \
+ $(AGENT_OBJS:.o=.c) $(ADD_OBJS:.o=.c) \
+ $(SCP_OBJS:.o=.c) \
+ $(GEN_MINFD_OBJS:.o=.c)
+EXTRA_SRCS = memmove.c strerror.c remove.c random.c putenv.c osfc2.c \
+ socketpair.c
+MAN1PAGES = ssh-keygen.1 ssh-agent.1 ssh-add.1 scp.1
+MAN1GENERATED = ssh.1
+MAN1SOURCES = ssh.1.in ssh-keygen.1 ssh-agent.1 ssh-add.1 scp.1
+MAN8GENERATED = sshd.8
+MAN8SOURCES = sshd.8.in
+
+DISTFILES = COPYING.Ylonen README.AFS-KERBEROS README README.SECURID \
+ INSTALL TODO OVERVIEW \
+ configure configure.in config.guess config.sub Makefile.in \
+ ssh-askpass.wish host_config.sample config.sample \
+ acconfig.h config.h.in server_config.sample \
+ $(MAN1SOURCES) $(MAN8SOURCES) *.c *.h install-sh \
+ RFC.nroff RFC \
+ ChangeLog
+
+DISTNAME = `sed 's/.*"\(.*\)".*/\1/' version.h`
+
+NORMAL_PROGRAMS = ssh-keygen ssh-askpass ssh-agent ssh-add scp
+
+SBIN_PROGRAMS = sshd
+PROGRAMS = ssh $(SBIN_PROGRAMS) $(NORMAL_PROGRAMS)
+SSH_PROGRAM = $(bindir)/ssh
+
+all: $(PROGRAMS)
+
+RFC: RFC.nroff rfc-pg
+ tbl RFC.nroff | nroff -ms | sed 's/FORMFEED\[Page/ [Page/' | ./rfc-pg -n5 >RFC
+
+rfc-pg: rfc-pg.c
+ $(CC) -o rfc-pg rfc-pg.c
+
+.c.o:
+ $(CC) -c -I. $(KRB4_INCS) $(GMPINCS) $(ZINCS) $(DEFS) -DHOST_KEY_FILE=\"$(HOST_KEY_FILE)\" -DHOST_CONFIG_FILE=\"$(HOST_CONFIG_FILE)\" -DSERVER_CONFIG_FILE=\"$(SERVER_CONFIG_FILE)\" -DSSH_PROGRAM=\"$(SSH_PROGRAM)\" -DETCDIR=\"$(etcdir)\" -DPIDDIR=\"$(piddir)\" $(CFLAGS) $<
+
+sshd: $(SSHD_OBJS) $(RSAREFDEP)
+ -rm -f sshd
+ $(CC) $(LDFLAGS) -o sshd $(SSHD_OBJS) $(GMPLIBS) $(ZLIBLIBS) $(KRB4_LIBS) $(LIBS)
+
+ssh: $(SSH_OBJS) $(RSAREFDEP)
+ -rm -f ssh
+ $(CC) $(LDFLAGS) -o ssh $(SSH_OBJS) $(GMPLIBS) $(ZLIBLIBS) $(KRB4_LIBS) $(LIBS)
+
+ssh-keygen: $(KEYGEN_OBJS) $(RSAREFDEP)
+ -rm -f ssh-keygen
+ $(CC) $(LDFLAGS) -o ssh-keygen $(KEYGEN_OBJS) $(GMPLIBS) $(KRB4_LIBS) $(LIBS)
+
+ssh-agent: $(AGENT_OBJS) $(RSAREFDEP)
+ -rm -f ssh-agent
+ $(CC) $(LDFLAGS) -o ssh-agent $(AGENT_OBJS) $(GMPLIBS) $(KRB4_LIBS) $(LIBS)
+
+ssh-add: $(ADD_OBJS) $(RSAREFDEP)
+ -rm -f ssh-add
+ $(CC) $(LDFLAGS) -o ssh-add $(ADD_OBJS) $(GMPLIBS) $(KRB4_LIBS) $(LIBS)
+
+scp: $(SCP_OBJS) $(LIBOBJS)
+ -rm -f scp
+ $(CC) $(LDFLAGS) -o scp $(SCP_OBJS) $(LIBOBJS) $(KRB4_LIBS) $(LIBS)
+
+ssh-askpass: ssh-askpass.wish
+ -rm -f ssh-askpass
+ echo "#! $(WISH) -f" >ssh-askpass
+ cat $(srcdir)/ssh-askpass.wish >>ssh-askpass
+ chmod +x ssh-askpass
+
+gen_minfd: $(GEN_MINFD_OBJS)
+ $(CC) $(LDFLAGS) -o gen_minfd $(GEN_MINFD_OBJS) $(LIBS)
+
+minfd.o: minfd.h
+minfd.h: gen_minfd
+ rm -f minfd.h minfd.h~
+ ./gen_minfd $(USER_SHELLS) > minfd.h~
+ mv -f minfd.h~ minfd.h
+
+$(RSAREFSRCDIR)/librsaref.a:
+ -if test '!' -d $(RSAREFDIR); then \
+ (cd $(srcdir); tar cf - $(RSAREFSRCDIR)) | tar xf -; fi
+ cd $(RSAREFSRCDIR); $(MAKE) -f ../../Makefile librsaref.a
+
+RSAREFSRCS = desc.c digit.c md2c.c md5c.c nn.c prime.c r_dh.c r_encode.c \
+ r_enhanc.c r_keygen.c r_random.c r_stdlib.c rsa.c
+
+# Note: this target is used in a recursive make, with VPATH pointing to source
+librsaref.a:
+ for i in $(RSAREFSRCS); do $(CC) $(CFLAGS) -c $$i; done
+ $(AR) rc librsaref.a $(RSAREFSRCS:.c=.o)
+ $(RANLIB) librsaref.a
+
+# Creates /etc/ssh_host_key
+generate-host-key:
+ -@if test -f $(install_prefix)$(HOST_KEY_FILE); \
+ then echo "You already have a host key in $(install_prefix)$(HOST_KEY_FILE)."; \
+ else \
+ umask 022; echo "Generating 1024 bit host key."; \
+ ./ssh-keygen -b 1024 -f $(install_prefix)$(HOST_KEY_FILE) -N ''; \
+ fi
+
+# Creates install directories
+make-dirs:
+ -umask 022; if test '!' -d $(install_prefix)$(prefix); then \
+ mkdir $(install_prefix)$(prefix); fi; \
+ if test '!' -d $(install_prefix)$(exec_prefix); then \
+ mkdir $(install_prefix)$(exec_prefix); fi; \
+ if test '!' -d $(install_prefix)$(etcdir); then \
+ mkdir $(install_prefix)$(etcdir); fi; \
+ if test '!' -d $(install_prefix)$(bindir); then \
+ mkdir $(install_prefix)$(bindir); fi; \
+ if test '!' -d $(install_prefix)$(sbindir); then \
+ mkdir $(install_prefix)$(sbindir); fi; \
+ if test '!' -d $(install_prefix)$(mandir); then \
+ mkdir $(install_prefix)$(mandir); fi; \
+ if test '!' -d $(install_prefix)$(man1dir); then \
+ mkdir $(install_prefix)$(man1dir); fi; \
+ if test '!' -d $(install_prefix)$(man8dir); then \
+ mkdir $(install_prefix)$(man8dir); fi
+
+# Ssh is much to large and hairy to be installed suid root by
+# default. Disabled for now/bg. If you really need rhosts
+# authentication do a manual chmod u+s $(install_prefix)$(bindir)/ssh.
+#
+# Ssh is preferably installed suid root. It can also be used non-root,
+# but then it cannot connect from a privileged socket, and rhosts
+# authentication will be disabled.
+#
+# Sshd is not suid root, but should preferably be run as root
+# (otherwise it can only log in as the user it runs as, and must be
+# bound to a non-privileged port). Also, password authentication may
+# not be available if non-root and using shadow passwords.
+install: $(PROGRAMS) make-dirs generate-host-key
+ $(INSTALL_PROGRAM) -o root -m 0755 ssh $(install_prefix)$(bindir)/ssh
+ -if test "`echo ssh | sed '$(transform)'`" '!=' ssh; then \
+ rm -f $(install_prefix)$(bindir)/`echo ssh | sed '$(transform)'`; \
+ $(LN_S) ssh \
+ $(install_prefix)$(bindir)/`echo ssh | sed '$(transform)'`; fi
+ rm -f $(install_prefix)$(bindir)/slogin
+ $(LN_S) ssh $(install_prefix)$(bindir)/slogin
+ -if test "`echo slogin | sed '$(transform)'`" '!=' slogin; then \
+ rm -f $(install_prefix)$(bindir)/`echo slogin | sed '$(transform)'`;\
+ $(LN_S) ssh \
+ $(install_prefix)$(bindir)/`echo slogin | sed '$(transform)'`; fi
+ -for p in $(NORMAL_PROGRAMS); do \
+ $(INSTALL_PROGRAM) -m 0755 $$p $(install_prefix)$(bindir)/$$p; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(bindir)/`echo $$p | sed '$(transform)'`; \
+ $(LN_S) $$p \
+ $(install_prefix)$(bindir)/`echo $$p | sed '$(transform)'`; fi; \
+ done
+# Remove $(etcdir)/sshd_pid as it is now $(bindir)/sshd.pid
+ -rm -f $(install_prefix)$(etcdir)/sshd_pid
+# Remove $(bindir)/sshd to avoid confusion since it is now in $(sbindir)
+ -rm -f $(install_prefix)$(bindir)/sshd
+ -rm -f $(install_prefix)$(bindir)/`echo sshd | sed '$(transform)'`
+ -for p in $(SBIN_PROGRAMS); do \
+ $(INSTALL_PROGRAM) -m 0755 $$p $(install_prefix)$(sbindir)/$$p; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(sbindir)/`echo $$p | sed '$(transform)'`;\
+ $(LN_S) $$p \
+ $(install_prefix)$(sbindir)/`echo $$p | sed '$(transform)'`; fi;\
+ done
+ -for p in $(MAN1PAGES); do \
+ $(INSTALL_DATA) -m 0644 $(srcdir)/$$p $(install_prefix)$(man1dir)/$$p ; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`;\
+ $(LN_S) $$p \
+ $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`; \
+ fi; \
+ done
+ rm -f $(install_prefix)$(man1dir)/slogin.1
+ $(LN_S) ssh.1 $(install_prefix)$(man1dir)/slogin.1
+ if test "`echo slogin.1 | sed '$(transform)'`" '!=' slogin.1; then \
+ rm -f $(install_prefix)$(man1dir)/`echo slogin.1 | sed '$(transform)'`;\
+ $(LN_S) ssh.1 \
+ $(install_prefix)$(man1dir)/`echo slogin.1 | sed '$(transform)'`; \
+ fi
+ -for p in $(MAN1GENERATED); do \
+ $(INSTALL_DATA) -m 0644 $$p $(install_prefix)$(man1dir)/$$p ; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`;\
+ $(LN_S) $$p \
+ $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`; \
+ fi; \
+ done
+ -for p in $(MAN8GENERATED); do \
+ $(INSTALL_DATA) -m 0644 $$p $(install_prefix)$(man8dir)/$$p; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(man8dir)/`echo $$p | sed '$(transform)'`;\
+ $(LN_S) $$p \
+ $(install_prefix)$(man8dir)/`echo $$p | sed '$(transform)'`; fi;\
+ done
+ -if test '!' -f $(install_prefix)$(HOST_CONFIG_FILE); then \
+ $(INSTALL_DATA) -m 0644 $(srcdir)/host_config.sample \
+ $(install_prefix)$(HOST_CONFIG_FILE); fi
+ -if test '!' -f $(install_prefix)$(SERVER_CONFIG_FILE); then \
+ cat $(srcdir)/server_config.sample | \
+ sed "s#_ETCDIR_#$(etcdir)#g" >/tmp/ssh_inst.$$; \
+ $(INSTALL_DATA) -m 0644 /tmp/ssh_inst.$$ \
+ $(install_prefix)$(SERVER_CONFIG_FILE); \
+ rm -f /tmp/ssh_inst.$$; fi
+
+uninstall:
+ for p in ssh $(NORMAL_PROGRAMS); do \
+ rm -f $(install_prefix)$(bindir)/$$p; \
+ rm -f $(install_prefix)$(bindir)/`echo $$p | sed '$(transform)'`; \
+ done
+ for p in $(SBIN_PROGRAMS); do \
+ rm -f $(install_prefix)$(sbindir)/$$p; \
+ rm -f $(install_prefix)$(sbindir)/`echo $$p | sed '$(transform)'`; \
+ done
+ rm -f $(install_prefix)$(bindir)/slogin
+ rm -f $(install_prefix)$(bindir)/`echo slogin | sed '$(transform)'`
+ for p in $(MAN1PAGES) $(MAN1GENERATED); do \
+ rm -f $(install_prefix)$(man1dir)/$$p; \
+ rm -f $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`; \
+ done
+ for p in $(MAN8GENERATED); do \
+ rm -f $(install_prefix)$(man8dir)/$$p; \
+ rm -f $(install_prefix)$(man8dir)/`echo $$p | sed '$(transform)'`; \
+ done
+
+clean:
+ -rm -f *.o minfd.h gmon.out core $(PROGRAMS) gen_minfd rfc-pg
+# cd $(RSAREFSRCDIR); rm -f *.o *.a
+
+distclean: clean
+ -rm -f Makefile config.status config.cache config.log config.h
+ -rm -f ssh.1 sshd.8
+
+dist:
+ -rm -rf $(DISTNAME)
+ -mkdir $(DISTNAME)
+ cp $(DISTFILES) $(DISTNAME)
+ -rm -f $(DISTNAME)/config.h
+# tar cf - $(RSAREFDIR) | (cd $(DISTNAME); tar xf -)
+# cd $(DISTNAME)/$(RSAREFSRCDIR); rm -f *.o *.a
+ tar cf $(DISTNAME).tar $(DISTNAME)
+ -rm -f $(DISTNAME).tar.gz
+ gzip $(DISTNAME).tar
+ rm -rf $(DISTNAME)
+ @echo Distribution left in $(DISTNAME).tar.gz
+# @echo Incrementing version number...
+# @old_version=`sed 's/.*\.\([0-9][0-9]*\)"$$/\1/' version.h`; \
+# new_version=`expr $$old_version + 1`; \
+# (echo "s/\.$$old_version\"/.$$new_version\"/g"; echo w; echo q) | ed version.h >/dev/null
+
+depend:
+ $(MAKEDEP) -I$(srcdir) -I. $(GMPINCS) $(ZINCS) $(DEFS) $(SRCS)
diff --git a/usr.bin/ssh/Makefile.in b/usr.bin/ssh/Makefile.in
new file mode 100644
index 00000000000..2f22ce010a3
--- /dev/null
+++ b/usr.bin/ssh/Makefile.in
@@ -0,0 +1,344 @@
+#
+# Makefile.in
+#
+# Author: Tatu Ylonen <ylo@cs.hut.fi>
+#
+# Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+# All rights reserved
+#
+# Created: Wed Mar 22 17:37:49 1995 ylo
+#
+# $Id: Makefile.in,v 1.1 1999/09/26 20:53:32 deraadt Exp $
+#
+
+srcdir = @srcdir@
+
+VPATH = $(srcdir)
+
+install_prefix =
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = $(exec_prefix)/bin
+sbindir = $(exec_prefix)/sbin
+mandir = $(prefix)/man
+man1dir = $(mandir)/man1
+man8dir = $(mandir)/man8
+etcdir = @ETCDIR@
+piddir = @PIDDIR@
+
+CC = @CC@
+CFLAGS = @CFLAGS@
+LDFLAGS = @LDFLAGS@
+DEFS = @DEFS@
+LIBS = @LIBS@
+LIBOBJS = @LIBOBJS@
+CONFOBJS = @CONFOBJS@
+
+MAKEDEP = @MAKEDEP@
+LN_S = @LN_S@
+RANLIB = @RANLIB@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+WISH = @WISH@
+
+GMPLIBS = @GMPLIBS@
+GMPINCS = @GMPINCS@
+
+KRB4_AUTH = @KRB4_AUTH@
+KRB4_ROOT = @KRB4_ROOT@
+KRB4_INCS = @KRB4_INCS@
+KRB4_LIBS = @KRB4_LIBS@
+RADIX = @RADIX@
+
+RSAREFDEP = @RSAREFDEP@
+
+transform = @program_transform_name@
+
+HOST_KEY_FILE = $(etcdir)/ssh_host_key
+HOST_CONFIG_FILE = $(etcdir)/ssh_config
+SERVER_CONFIG_FILE = $(etcdir)/sshd_config
+
+SHELL = /bin/sh
+
+#ZLIBLIBS = -L$(ZLIBDIR) -lz
+#ZINCS =
+
+RSAREFDIR = rsaref2
+RSAREFSRCDIR = $(RSAREFDIR)/source
+
+CIPHER_OBJS = cipher.o $(CONFOBJS)
+COMMON_OBJS = $(LIBOBJS) \
+ rsa.o randoms.o ssh_md5.o buffer.o packet.o \
+ xmalloc.o ttymodes.o channels.o bufaux.o authfd.o authfile.o crc32.o \
+ rsaglue.o match.o mpaux.o minfd.o $(CIPHER_OBJS)
+SSHD_OBJS = sshd.o $(KRB4_AUTH) auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o \
+ log-server.o login.o hostfile.o canohost.o servconf.o tildexpand.o \
+ uidswap.o serverloop.o $(RADIX) $(COMMON_OBJS)
+SSH_OBJS = ssh.o sshconnect.o log-client.o readconf.o hostfile.o readpass.o \
+ tildexpand.o uidswap.o clientloop.o canohost.o $(RADIX) $(COMMON_OBJS)
+KEYGEN_OBJS = ssh-keygen.o log-client.o readpass.o rsa.o randoms.o ssh_md5.o \
+ buffer.o xmalloc.o authfile.o $(CIPHER_OBJS) mpaux.o \
+ bufaux.o $(LIBOBJS)
+AGENT_OBJS = ssh-agent.o log-client.o rsa.o randoms.o ssh_md5.o buffer.o \
+ xmalloc.o bufaux.o authfd.o authfile.o rsaglue.o $(CIPHER_OBJS) \
+ mpaux.o minfd.o $(LIBOBJS)
+ADD_OBJS = ssh-add.o log-client.o readpass.o rsa.o randoms.o ssh_md5.o buffer.o \
+ xmalloc.o bufaux.o authfd.o authfile.o $(CIPHER_OBJS) \
+ mpaux.o minfd.o $(LIBOBJS)
+SCP_OBJS = scp.o xmalloc.o
+GEN_MINFD_OBJS = gen_minfd.o $(LIBOBJS)
+
+USER_SHELLS = sh jsh ksh csh tcsh bash zsh ash
+
+SRCS = $(SSHD_OBJS:.o=.c) $(SSH_OBJS:.o=.c) $(KEYGEN_OBJS:.o=.c) \
+ $(AGENT_OBJS:.o=.c) $(ADD_OBJS:.o=.c) \
+ $(SCP_OBJS:.o=.c) \
+ $(GEN_MINFD_OBJS:.o=.c)
+EXTRA_SRCS = memmove.c strerror.c remove.c random.c putenv.c osfc2.c \
+ socketpair.c
+MAN1PAGES = ssh-keygen.1 ssh-agent.1 ssh-add.1 scp.1
+MAN1GENERATED = ssh.1
+MAN1SOURCES = ssh.1.in ssh-keygen.1 ssh-agent.1 ssh-add.1 scp.1
+MAN8GENERATED = sshd.8
+MAN8SOURCES = sshd.8.in
+
+DISTFILES = COPYING.Ylonen README.AFS-KERBEROS README README.SECURID \
+ INSTALL TODO OVERVIEW \
+ configure configure.in config.guess config.sub Makefile.in \
+ ssh-askpass.wish host_config.sample config.sample \
+ acconfig.h config.h.in server_config.sample \
+ $(MAN1SOURCES) $(MAN8SOURCES) *.c *.h install-sh \
+ RFC.nroff RFC \
+ ChangeLog
+
+DISTNAME = `sed 's/.*"\(.*\)".*/\1/' version.h`
+
+NORMAL_PROGRAMS = ssh-keygen ssh-askpass ssh-agent ssh-add scp
+
+SBIN_PROGRAMS = sshd
+PROGRAMS = ssh $(SBIN_PROGRAMS) $(NORMAL_PROGRAMS)
+SSH_PROGRAM = $(bindir)/ssh
+
+all: $(PROGRAMS)
+
+RFC: RFC.nroff rfc-pg
+ tbl RFC.nroff | nroff -ms | sed 's/FORMFEED\[Page/ [Page/' | ./rfc-pg -n5 >RFC
+
+rfc-pg: rfc-pg.c
+ $(CC) -o rfc-pg rfc-pg.c
+
+.c.o:
+ $(CC) -c -I. $(KRB4_INCS) $(GMPINCS) $(ZINCS) $(DEFS) -DHOST_KEY_FILE=\"$(HOST_KEY_FILE)\" -DHOST_CONFIG_FILE=\"$(HOST_CONFIG_FILE)\" -DSERVER_CONFIG_FILE=\"$(SERVER_CONFIG_FILE)\" -DSSH_PROGRAM=\"$(SSH_PROGRAM)\" -DETCDIR=\"$(etcdir)\" -DPIDDIR=\"$(piddir)\" $(CFLAGS) $<
+
+sshd: $(SSHD_OBJS) $(RSAREFDEP)
+ -rm -f sshd
+ $(CC) $(LDFLAGS) -o sshd $(SSHD_OBJS) $(GMPLIBS) $(ZLIBLIBS) $(KRB4_LIBS) $(LIBS)
+
+ssh: $(SSH_OBJS) $(RSAREFDEP)
+ -rm -f ssh
+ $(CC) $(LDFLAGS) -o ssh $(SSH_OBJS) $(GMPLIBS) $(ZLIBLIBS) $(KRB4_LIBS) $(LIBS)
+
+ssh-keygen: $(KEYGEN_OBJS) $(RSAREFDEP)
+ -rm -f ssh-keygen
+ $(CC) $(LDFLAGS) -o ssh-keygen $(KEYGEN_OBJS) $(GMPLIBS) $(KRB4_LIBS) $(LIBS)
+
+ssh-agent: $(AGENT_OBJS) $(RSAREFDEP)
+ -rm -f ssh-agent
+ $(CC) $(LDFLAGS) -o ssh-agent $(AGENT_OBJS) $(GMPLIBS) $(KRB4_LIBS) $(LIBS)
+
+ssh-add: $(ADD_OBJS) $(RSAREFDEP)
+ -rm -f ssh-add
+ $(CC) $(LDFLAGS) -o ssh-add $(ADD_OBJS) $(GMPLIBS) $(KRB4_LIBS) $(LIBS)
+
+scp: $(SCP_OBJS) $(LIBOBJS)
+ -rm -f scp
+ $(CC) $(LDFLAGS) -o scp $(SCP_OBJS) $(LIBOBJS) $(KRB4_LIBS) $(LIBS)
+
+ssh-askpass: ssh-askpass.wish
+ -rm -f ssh-askpass
+ echo "#! $(WISH) -f" >ssh-askpass
+ cat $(srcdir)/ssh-askpass.wish >>ssh-askpass
+ chmod +x ssh-askpass
+
+gen_minfd: $(GEN_MINFD_OBJS)
+ $(CC) $(LDFLAGS) -o gen_minfd $(GEN_MINFD_OBJS) $(LIBS)
+
+minfd.o: minfd.h
+minfd.h: gen_minfd
+ rm -f minfd.h minfd.h~
+ ./gen_minfd $(USER_SHELLS) > minfd.h~
+ mv -f minfd.h~ minfd.h
+
+$(RSAREFSRCDIR)/librsaref.a:
+ -if test '!' -d $(RSAREFDIR); then \
+ (cd $(srcdir); tar cf - $(RSAREFSRCDIR)) | tar xf -; fi
+ cd $(RSAREFSRCDIR); $(MAKE) -f ../../Makefile librsaref.a
+
+RSAREFSRCS = desc.c digit.c md2c.c md5c.c nn.c prime.c r_dh.c r_encode.c \
+ r_enhanc.c r_keygen.c r_random.c r_stdlib.c rsa.c
+
+# Note: this target is used in a recursive make, with VPATH pointing to source
+librsaref.a:
+ for i in $(RSAREFSRCS); do $(CC) $(CFLAGS) -c $$i; done
+ $(AR) rc librsaref.a $(RSAREFSRCS:.c=.o)
+ $(RANLIB) librsaref.a
+
+# Creates /etc/ssh_host_key
+generate-host-key:
+ -@if test -f $(install_prefix)$(HOST_KEY_FILE); \
+ then echo "You already have a host key in $(install_prefix)$(HOST_KEY_FILE)."; \
+ else \
+ umask 022; echo "Generating 1024 bit host key."; \
+ ./ssh-keygen -b 1024 -f $(install_prefix)$(HOST_KEY_FILE) -N ''; \
+ fi
+
+# Creates install directories
+make-dirs:
+ -umask 022; if test '!' -d $(install_prefix)$(prefix); then \
+ mkdir $(install_prefix)$(prefix); fi; \
+ if test '!' -d $(install_prefix)$(exec_prefix); then \
+ mkdir $(install_prefix)$(exec_prefix); fi; \
+ if test '!' -d $(install_prefix)$(etcdir); then \
+ mkdir $(install_prefix)$(etcdir); fi; \
+ if test '!' -d $(install_prefix)$(bindir); then \
+ mkdir $(install_prefix)$(bindir); fi; \
+ if test '!' -d $(install_prefix)$(sbindir); then \
+ mkdir $(install_prefix)$(sbindir); fi; \
+ if test '!' -d $(install_prefix)$(mandir); then \
+ mkdir $(install_prefix)$(mandir); fi; \
+ if test '!' -d $(install_prefix)$(man1dir); then \
+ mkdir $(install_prefix)$(man1dir); fi; \
+ if test '!' -d $(install_prefix)$(man8dir); then \
+ mkdir $(install_prefix)$(man8dir); fi
+
+# Ssh is much to large and hairy to be installed suid root by
+# default. Disabled for now/bg. If you really need rhosts
+# authentication do a manual chmod u+s $(install_prefix)$(bindir)/ssh.
+#
+# Ssh is preferably installed suid root. It can also be used non-root,
+# but then it cannot connect from a privileged socket, and rhosts
+# authentication will be disabled.
+#
+# Sshd is not suid root, but should preferably be run as root
+# (otherwise it can only log in as the user it runs as, and must be
+# bound to a non-privileged port). Also, password authentication may
+# not be available if non-root and using shadow passwords.
+install: $(PROGRAMS) make-dirs generate-host-key
+ $(INSTALL_PROGRAM) -o root -m 0755 ssh $(install_prefix)$(bindir)/ssh
+ -if test "`echo ssh | sed '$(transform)'`" '!=' ssh; then \
+ rm -f $(install_prefix)$(bindir)/`echo ssh | sed '$(transform)'`; \
+ $(LN_S) ssh \
+ $(install_prefix)$(bindir)/`echo ssh | sed '$(transform)'`; fi
+ rm -f $(install_prefix)$(bindir)/slogin
+ $(LN_S) ssh $(install_prefix)$(bindir)/slogin
+ -if test "`echo slogin | sed '$(transform)'`" '!=' slogin; then \
+ rm -f $(install_prefix)$(bindir)/`echo slogin | sed '$(transform)'`;\
+ $(LN_S) ssh \
+ $(install_prefix)$(bindir)/`echo slogin | sed '$(transform)'`; fi
+ -for p in $(NORMAL_PROGRAMS); do \
+ $(INSTALL_PROGRAM) -m 0755 $$p $(install_prefix)$(bindir)/$$p; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(bindir)/`echo $$p | sed '$(transform)'`; \
+ $(LN_S) $$p \
+ $(install_prefix)$(bindir)/`echo $$p | sed '$(transform)'`; fi; \
+ done
+# Remove $(etcdir)/sshd_pid as it is now $(bindir)/sshd.pid
+ -rm -f $(install_prefix)$(etcdir)/sshd_pid
+# Remove $(bindir)/sshd to avoid confusion since it is now in $(sbindir)
+ -rm -f $(install_prefix)$(bindir)/sshd
+ -rm -f $(install_prefix)$(bindir)/`echo sshd | sed '$(transform)'`
+ -for p in $(SBIN_PROGRAMS); do \
+ $(INSTALL_PROGRAM) -m 0755 $$p $(install_prefix)$(sbindir)/$$p; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(sbindir)/`echo $$p | sed '$(transform)'`;\
+ $(LN_S) $$p \
+ $(install_prefix)$(sbindir)/`echo $$p | sed '$(transform)'`; fi;\
+ done
+ -for p in $(MAN1PAGES); do \
+ $(INSTALL_DATA) -m 0644 $(srcdir)/$$p $(install_prefix)$(man1dir)/$$p ; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`;\
+ $(LN_S) $$p \
+ $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`; \
+ fi; \
+ done
+ rm -f $(install_prefix)$(man1dir)/slogin.1
+ $(LN_S) ssh.1 $(install_prefix)$(man1dir)/slogin.1
+ if test "`echo slogin.1 | sed '$(transform)'`" '!=' slogin.1; then \
+ rm -f $(install_prefix)$(man1dir)/`echo slogin.1 | sed '$(transform)'`;\
+ $(LN_S) ssh.1 \
+ $(install_prefix)$(man1dir)/`echo slogin.1 | sed '$(transform)'`; \
+ fi
+ -for p in $(MAN1GENERATED); do \
+ $(INSTALL_DATA) -m 0644 $$p $(install_prefix)$(man1dir)/$$p ; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`;\
+ $(LN_S) $$p \
+ $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`; \
+ fi; \
+ done
+ -for p in $(MAN8GENERATED); do \
+ $(INSTALL_DATA) -m 0644 $$p $(install_prefix)$(man8dir)/$$p; \
+ if test "`echo $$p | sed '$(transform)'`" '!=' $$p; then \
+ rm -f $(install_prefix)$(man8dir)/`echo $$p | sed '$(transform)'`;\
+ $(LN_S) $$p \
+ $(install_prefix)$(man8dir)/`echo $$p | sed '$(transform)'`; fi;\
+ done
+ -if test '!' -f $(install_prefix)$(HOST_CONFIG_FILE); then \
+ $(INSTALL_DATA) -m 0644 $(srcdir)/host_config.sample \
+ $(install_prefix)$(HOST_CONFIG_FILE); fi
+ -if test '!' -f $(install_prefix)$(SERVER_CONFIG_FILE); then \
+ cat $(srcdir)/server_config.sample | \
+ sed "s#_ETCDIR_#$(etcdir)#g" >/tmp/ssh_inst.$$; \
+ $(INSTALL_DATA) -m 0644 /tmp/ssh_inst.$$ \
+ $(install_prefix)$(SERVER_CONFIG_FILE); \
+ rm -f /tmp/ssh_inst.$$; fi
+
+uninstall:
+ for p in ssh $(NORMAL_PROGRAMS); do \
+ rm -f $(install_prefix)$(bindir)/$$p; \
+ rm -f $(install_prefix)$(bindir)/`echo $$p | sed '$(transform)'`; \
+ done
+ for p in $(SBIN_PROGRAMS); do \
+ rm -f $(install_prefix)$(sbindir)/$$p; \
+ rm -f $(install_prefix)$(sbindir)/`echo $$p | sed '$(transform)'`; \
+ done
+ rm -f $(install_prefix)$(bindir)/slogin
+ rm -f $(install_prefix)$(bindir)/`echo slogin | sed '$(transform)'`
+ for p in $(MAN1PAGES) $(MAN1GENERATED); do \
+ rm -f $(install_prefix)$(man1dir)/$$p; \
+ rm -f $(install_prefix)$(man1dir)/`echo $$p | sed '$(transform)'`; \
+ done
+ for p in $(MAN8GENERATED); do \
+ rm -f $(install_prefix)$(man8dir)/$$p; \
+ rm -f $(install_prefix)$(man8dir)/`echo $$p | sed '$(transform)'`; \
+ done
+
+clean:
+ -rm -f *.o minfd.h gmon.out core $(PROGRAMS) gen_minfd rfc-pg
+# cd $(RSAREFSRCDIR); rm -f *.o *.a
+
+distclean: clean
+ -rm -f Makefile config.status config.cache config.log config.h
+ -rm -f ssh.1 sshd.8
+
+dist:
+ -rm -rf $(DISTNAME)
+ -mkdir $(DISTNAME)
+ cp $(DISTFILES) $(DISTNAME)
+ -rm -f $(DISTNAME)/config.h
+# tar cf - $(RSAREFDIR) | (cd $(DISTNAME); tar xf -)
+# cd $(DISTNAME)/$(RSAREFSRCDIR); rm -f *.o *.a
+ tar cf $(DISTNAME).tar $(DISTNAME)
+ -rm -f $(DISTNAME).tar.gz
+ gzip $(DISTNAME).tar
+ rm -rf $(DISTNAME)
+ @echo Distribution left in $(DISTNAME).tar.gz
+# @echo Incrementing version number...
+# @old_version=`sed 's/.*\.\([0-9][0-9]*\)"$$/\1/' version.h`; \
+# new_version=`expr $$old_version + 1`; \
+# (echo "s/\.$$old_version\"/.$$new_version\"/g"; echo w; echo q) | ed version.h >/dev/null
+
+depend:
+ $(MAKEDEP) -I$(srcdir) -I. $(GMPINCS) $(ZINCS) $(DEFS) $(SRCS)
diff --git a/usr.bin/ssh/OVERVIEW b/usr.bin/ssh/OVERVIEW
new file mode 100644
index 00000000000..3b95cda455a
--- /dev/null
+++ b/usr.bin/ssh/OVERVIEW
@@ -0,0 +1,226 @@
+This document is inteded for those who wish to read the ssh source
+code. This tries to give an overview of the structure of the code.
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>
+Updated 17 Nov 1995.
+
+The software consists of ssh (client), sshd (server), scp, sdist, and
+the auxiliary programs ssh-keygen, ssh-agent, ssh-add, and
+make-ssh-known-hosts. The main program for each of these is in a .c
+file with the same name.
+
+There are some subsystems/abstractions that are used by a number of
+these programs.
+
+ Configuration
+
+ - Ssh configures itself with "./configure" in the source
+ directory. The configuration system is based on GNU Autoconf.
+ The "configure" script is generated from configure.in using the
+ autoconf tool (2.4 required, plus a patch for AC_ARG_PROGRAM).
+ Additionally, the file config.h.in is generated from
+ configure.in and acconfig.h with the autoheader tool (also part
+ of GNU Autoconf). The configure process generates Makefile from
+ Makefile.in, the file config.h, and a few other files from their
+ respective .in files. The configure script uses the files
+ config.guess (to determine current host type), config.sub (to
+ validate given host type). It may also arrange to use the
+ install.sh script from the Makefile when installing programs.
+
+ Makefile
+
+ The Makefile (generated from Makefile.in with configure) contains the
+ following major targets:
+
+ all: (default) compile all executables.
+ install: installs executables and manual pages; installs
+ configuration files and generates host key if they don't exist.
+ uninstall: removes installed executables and manual pages.
+ clean: removes object files, executables, and some temporary files.
+ distclean: removes all generated files ("distrigution state").
+ depend: updates dependencies.
+ RFC: run RFC.nroff trough nroff to generate a new version of the RFC.
+ dist: generate a distribution ".tar.gz" file.
+
+ Buffer manipulation routines
+
+ - These provide an arbitrary size buffer, where data can be appended.
+ Data can be consumed from either end. The code is used heavily
+ throughout ssh. The basic buffer manipulation functions are in
+ buffer.c (header buffer.h), and additional code to manipulate specific
+ data types is in bufaux.c.
+
+ Compression Library
+
+ - Ssh uses the GNU GZIP compression library (ZLIB). It resides in
+ the zlib095 subdirectory.
+
+ Encryption/Decryption
+
+ - Ssh contains several encryption algorithms. These are all
+ accessed through the cipher.h interface. The interface code is
+ in cipher.c, and the implementations in des.c, idea.c, tss.c,
+ md5.c, rc4.c, and tss.c.
+
+ Multiple Precision Integer Library
+
+ - Ssh uses the GNU Multiple Precision Library (gmp). The code is in the
+ gmp-1.3.2 subdirectory.
+
+ - Some auxiliary functions for mp-int manipulation are in mpaux.c.
+
+ Random Numbers
+
+ - The random numbers for cryptographic use are generated by using
+ a generator with 1024 byte pool that uses MD5 to stir the pool.
+ The generator acquires a little amount of new entropy every time
+ it stirs the pool.
+
+ - The distribution also contains the file random.c which offers a
+ substitute for the BSD random() function. This function is only
+ refernced from the gmp library; the function where it is used is
+ only used in the gmp primality checking functions (ssh uses the
+ Fermat test in addition to the gmp primality test).
+
+ RSA key generation, encryption, decryption
+
+ - Ssh contains its own RSA routines. It can, however, also be compiled to
+ use RSAREF. The interface to RSA encryption/decryption is in rsaglue.c;
+ it will either call RSAREF (which must be in the rsaref2 subdirectory
+ if it is used - it does not come with ssh). Normally it calls functions
+ in rsa.c. The file rsa.c also contains prime generation code and
+ RSA key generation.
+
+ RSA key files
+
+ - RSA keys are stored in files with a special format. The code to
+ read/write these files is in authfile.c. The files are normally
+ encrypted with a passphrase. The functions to read passphrases
+ are in readpass.c (the same code is used to read passwords).
+
+ Binary packet protocol
+
+ - The ssh binary packet protocol is implemented in packet.c. The
+ code in packet.c does not concern itself with packet types or their
+ execution; it contains code to build packets, to receive them and
+ extract data from them, and the code to compress and/or encrypt
+ packets. CRC code comes from crc32.c.
+
+ - The code in packet.c calls the buffer manipulation routines
+ (buffer.c, bufaux.c), compression routines (compress.c, zlib),
+ and the encryption routines.
+
+ X11, TCP/IP, and Agent forwarding
+
+ - Code for various types of channel forwarding is in channels.c.
+ The file defines a generic framework for arbitrary communication
+ channels inside the secure channel, and uses this framework to
+ implement X11 forwarding, TCP/IP forwarding, and authentication
+ agent forwarding.
+
+ Authentication agent
+
+ - Code to communicate with the authentication agent is in
+ authfd.c. The files gen-minfd.c, minfd.h, minfd.c
+
+ Authentication methods
+
+ - Code for various authentication methods resides in auth-*.c
+ (auth-passwd.c, auth-rh-rsa.c, auth-rhosts.c, auth-rsa.c). This
+ code is linked into the server. The routines also manipulate
+ known hosts files using code in hostfile.c. Code in canohost.c
+ is used to retrieve the canonical host name of the remote host.
+ Code in match.c is used to match host names. Code for osf C2
+ extended security is in osfc2.c.
+
+ - In the client end, authentication code is in sshconnect.c. It
+ reads Passwords/passphrases using code in readpass.c. It reads
+ RSA key files with authfile.c. It communicates the
+ authentication agent using authfd.c.
+
+ The ssh client
+
+ - The client main program is in ssh.c. It first parses arguments
+ and reads configuration (readconf.c), then calls ssh_connect (in
+ sshconnect.c) to open a connection to the server (possibly via a
+ proxy), and performs authentication (ssh_login in sshconnect.c).
+ It then makes any pty, forwarding, etc. requests. It may call
+ code in ttymodes.c to encode current tty modes. Finally it
+ calls client_loop in clientloop.c. This does the real work for
+ the session.
+
+ - The client is suid root. It tries to temporarily give up this
+ rights while reading the configuration data. The root
+ privileges are only used to make the connection (from a
+ privileged socket). Any extra privileges are dropped before
+ calling ssh_login.
+
+ Pseudo-tty manipulation and tty modes
+
+ - Code to allocate and use a pseudo tty is in pty.c. Code to
+ encode and set terminal modes is in ttymodes.c.
+
+ Logging in (updating utmp, lastlog, etc.)
+
+ - The code to do things that are done when a user logs in are in
+ login.c. This includes things such as updating the utmp, wtmp,
+ and lastlog files. Some of the code is in sshd.c.
+
+ Writing to the system log and terminal
+
+ - The programs use the functions fatal(), log(), debug(), error()
+ in many places to write messages to system log or user's
+ terminal. The implementation that logs to system log is in
+ log-server.c; it is used in the server program. The other
+ programs use an implementation that sends output to stderr; it
+ is in log-client.c. The definitions are in ssh.h.
+
+ The sshd server (daemon)
+
+ - The sshd daemon starts by processing arguments and reading the
+ configuration file (servconf.c). It then reads the host key,
+ starts listening for connections, and generates the server key.
+ The server key will be regenerated every hour by an alarm.
+
+ - When the server receives a connection, it forks, disables the
+ regeneration alarm, and starts communicating with the client.
+ They first perform identification string exchange, then
+ negotiate encryption, then perform authentication, preparatory
+ operations, and finally the server enters the normal session
+ mode by calling server_loop in serverloop.c. This does the real
+ work, calling functions in other modules.
+
+ - The code for the server is in sshd.c. It contains a lot of
+ stuff, including:
+ - server main program
+ - waiting for connections
+ - processing new connection
+ - authentication
+ - preparatory operations
+ - building up the execution environment for the user program
+ - starting the user program.
+
+ Auxiliary files
+
+ - There are several other files in the distribution that contain
+ various auxiliary routines:
+ ssh.h the main header file for ssh (various definitions)
+ getput.h byte-order independent storage of integers
+ includes.h includes most system headers. Lots of #ifdefs.
+ tildexpand.c expand tilde in file names
+ uidswap.c uid-swapping
+ xmalloc.c "safe" malloc routines
+
+ Substitutions files for missing functions
+
+ - To ease porting, the distribution contains alternative versions of some
+ functions for those platforms that don't have them. These are
+ added to the CONFOBJS target by configure where needed.
+ crypt.c password encryption crypt() (Convex needs this)
+ memmove.c memmove() function
+ putenv.c putenv() function
+ random.c random() function (see discussion above)
+ remove.c remove() function
+ socketpair.c socketpair() function (kludge; SCO needs it)
+ strerror.c strerror() function
+
diff --git a/usr.bin/ssh/README b/usr.bin/ssh/README
new file mode 100644
index 00000000000..ed360844185
--- /dev/null
+++ b/usr.bin/ssh/README
@@ -0,0 +1,563 @@
+Ssh (Secure Shell) is a program to log into another computer over a
+network, to execute commands in a remote machine, and to move files
+from one machine to another. It provides strong authentication and
+secure communications over insecure channels. It is inteded as a
+replacement for rlogin, rsh, rcp, and rdist.
+
+See the file INSTALL for installation instructions. See COPYING for
+license terms and other legal issues. See RFC for a description of
+the protocol. There is a WWW page for ssh; see http://www.cs.hut.fi/ssh.
+
+This file has been updated to match ssh-1.2.12.
+
+
+FEATURES
+
+ o Strong authentication. Closes several security holes (e.g., IP,
+ routing, and DNS spoofing). New authentication methods: .rhosts
+ together with RSA based host authentication, and pure RSA
+ authentication.
+
+ o Improved privacy. All communications are automatically and
+ transparently encrypted. RSA is used for key exchange, and a
+ conventional cipher (normally IDEA, DES, or triple-DES) for
+ encrypting the session. Encryption is started before
+ authentication, and no passwords or other information is
+ transmitted in the clear. Encryption is also used to protect
+ against spoofed packets.
+
+ o Secure X11 sessions. The program automatically sets DISPLAY on
+ the server machine, and forwards any X11 connections over the
+ secure channel. Fake Xauthority information is automatically
+ generated and forwarded to the remote machine; the local client
+ automatically examines incoming X11 connections and replaces the
+ fake authorization data with the real data (never telling the
+ remote machine the real information).
+
+ o Arbitrary TCP/IP ports can be redirected through the encrypted channel
+ in both directions (e.g., for e-cash transactions).
+
+ o No retraining needed for normal users; everything happens
+ automatically, and old .rhosts files will work with strong
+ authentication if administration installs host key files.
+
+ o Never trusts the network. Minimal trust on the remote side of
+ the connection. Minimal trust on domain name servers. Pure RSA
+ authentication never trusts anything but the private key.
+
+ o Client RSA-authenticates the server machine in the beginning of
+ every connection to prevent trojan horses (by routing or DNS
+ spoofing) and man-in-the-middle attacks, and the server
+ RSA-authenticates the client machine before accepting .rhosts or
+ /etc/hosts.equiv authentication (to prevent DNS, routing, or
+ IP-spoofing).
+
+ o Host authentication key distribution can be centrally by the
+ administration, automatically when the first connection is made
+ to a machine (the key obtained on the first connection will be
+ recorded and used for authentication in the future), or manually
+ by each user for his/her own use. The central and per-user host
+ key repositories are both used and complement each other. Host
+ keys can be generated centrally or automatically when the software
+ is installed. Host authentication keys are typically 1024 bits.
+
+ o Any user can create any number of user authentication RSA keys for
+ his/her own use. Each user has a file which lists the RSA public
+ keys for which proof of possession of the corresponding private
+ key is accepted as authentication. User authentication keys are
+ typically 1024 bits.
+
+ o The server program has its own server RSA key which is
+ automatically regenerated every hour. This key is never saved in
+ any file. Exchanged session keys are encrypted using both the
+ server key and the server host key. The purpose of the separate
+ server key is to make it impossible to decipher a captured session by
+ breaking into the server machine at a later time; one hour from
+ the connection even the server machine cannot decipher the session
+ key. The key regeneration interval is configurable. The server
+ key is normally 768 bits.
+
+ o An authentication agent, running in the user's laptop or local
+ workstation, can be used to hold the user's RSA authentication
+ keys. Ssh automatically forwards the connection to the
+ authentication agent over any connections, and there is no need to
+ store the RSA authentication keys on any machine in the network
+ (except the user's own local machine). The authentication
+ protocols never reveal the keys; they can only be used to verify
+ that the user's agent has a certain key. Eventually the agent
+ could rely on a smart card to perform all authentication
+ computations.
+
+ o The software can be installed and used (with restricted
+ functionality) even without root privileges.
+
+ o The client is customizable in system-wide and per-user
+ configuration files. Most aspects of the client's operation can
+ be configured. Different options can be specified on a per-host basis.
+
+ o Automatically executes conventional rsh (after displaying a
+ warning) if the server machine is not running sshd.
+
+ o Optional compression of all data with gzip (including forwarded X11
+ and TCP/IP port data), which may result in significant speedups on
+ slow connections.
+
+ o Complete replacement for rlogin, rsh, and rcp.
+
+
+WHY TO USE SECURE SHELL
+
+Currently, almost all communications in computer networks are done
+without encryption. As a consequence, anyone who has access to any
+machine connected to the network can listen in on any communication.
+This is being done by hackers, curious administrators, employers,
+criminals, industrial spies, and governments. Some networks leak off
+enough electromagnetic radiation that data may be captured even from a
+distance.
+
+When you log in, your password goes in the network in plain
+text. Thus, any listener can then use your account to do any evil he
+likes. Many incidents have been encountered worldwide where crackers
+have started programs on workstations without the owners knowledge
+just to listen to the network and collect passwords. Programs for
+doing this are available on the Internet, or can be built by a
+competent programmer in a few hours.
+
+Any information that you type or is printed on your screen can be
+monitored, recorded, and analyzed. For example, an intruder who has
+penetrated a host connected to a major network can start a program
+that listens to all data flowing in the network, and whenever it
+encounters a 16-digit string, it checks if it is a valid credit card
+number (using the check digit), and saves the number plus any
+surrounding text (to catch expiration date and holder) in a file.
+When the intruder has collected a few thousand credit card numbers, he
+makes smallish mail-order purchases from a few thousand stores around
+the world, and disappears when the goods arrive but before anyone
+suspects anything.
+
+Businesses have trade secrets, patent applications in preparation,
+pricing information, subcontractor information, client data, personnel
+data, financial information, etc. Currently, anyone with access to
+the network (any machine on the network) can listen to anything that
+goes in the network, without any regard to normal access restrictions.
+
+Many companies are not aware that information can so easily be
+recovered from the network. They trust that their data is safe
+since nobody is supposed to know that there is sensitive information
+in the network, or because so much other data is transferred in the
+network. This is not a safe policy.
+
+Individual persons also have confidential information, such as
+diaries, love letters, health care documents, information about their
+personal interests and habits, professional data, job applications,
+tax reports, political documents, unpublished manuscripts, etc.
+
+One should also be aware that economical intelligence and industrial
+espionage has recently become a major priority of the intelligence
+agencies of major governments. President Clinton recently assigned
+economical espionage as the primary task of the CIA, and the French
+have repeatedly been publicly boasting about their achievements on
+this field.
+
+
+There is also another frightening aspect about the poor security of
+communications. Computer storage and analysis capability has
+increased so much that it is feasible for governments, major
+companies, and criminal organizations to automatically analyze,
+identify, classify, and file information about millions of people over
+the years. Because most of the work can be automated, the cost of
+collecting this information is getting very low.
+
+Government agencies may be able to monitor major communication
+systems, telephones, fax, computer networks, etc., and passively
+collect huge amounts of information about all people with any
+significant position in the society. Most of this information is not
+sensitive, and many people would say there is no harm in someone
+getting that information. However, the information starts to get
+sensitive when someone has enough of it. You may not mind someone
+knowing what you bought from the shop one random day, but you might
+not like someone knowing every small thing you have bought in the last
+ten years.
+
+If the government some day starts to move into a more totalitarian
+direction (one should remember that Nazi Germany was created by
+democratic elections), there is considerable danger of an ultimate
+totalitarian state. With enough information (the automatically
+collected records of an individual can be manually analyzed when the
+person becomes interesting), one can form a very detailed picture of
+the individual's interests, opinions, beliefs, habits, friends,
+lovers, weaknesses, etc. This information can be used to 1) locate
+any persons who might oppose the new system 2) use deception to
+disturb any organizations which might rise against the government 3)
+eliminate difficult individuals without anyone understanding what
+happened. Additionally, if the government can monitor communications
+too effectively, it becomes too easy to locate and eliminate any
+persons distributing information contrary to the official truth.
+
+Fighting crime and terrorism are often used as grounds for domestic
+surveillance and restricting encryption. These are good goals, but
+there is considerable danger that the surveillance data starts to get
+used for questionable purposes. I find that it is better to tolerate
+a small amount of crime in the society than to let the society become
+fully controlled. I am in favor of a fairly strong state, but the
+state must never get so strong that people become unable to spread
+contra-offical information and unable to overturn the government if it
+is bad. The danger is that when you notice that the government is
+too powerful, it is too late. Also, the real power may not be where
+the official government is.
+
+For these reasons (privacy, protecting trade secrets, and making it
+more difficult to create a totalitarian state), I think that strong
+cryptography should be integrated to the tools we use every day.
+Using it causes no harm (except for those who wish to monitor
+everything), but not using it can cause huge problems. If the society
+changes in undesirable ways, then it will be to late to start
+encrypting.
+
+Encryption has had a "military" or "classified" flavor to it. There
+are no longer any grounds for this. The military can and will use its
+own encryption; that is no excuse to prevent the civilians from
+protecting their privacy and secrets. Information on strong
+encryption is available in every major bookstore, scientific library,
+and patent office around the world, and strong encryption software is
+available in every country on the Internet.
+
+Some people would like to make it illegal to use encryption, or to
+force people to use encryption that governments can break. This
+approach offers no protection if the government turns bad. Also, the
+"bad guys" will be using true strong encryption anyway. Good
+encryption techniques are too widely known to make them disappear.
+Thus, any "key escrow encryption" or other restrictions will only help
+monitor ordinary people and petty criminals. It does not help against
+powerful criminals, terrorists, or espionage, because they will know
+how to use strong encryption anyway. (One source for internationally
+available encryption software is http://www.cs.hut.fi/crypto.)
+
+
+OVERVIEW OF SECURE SHELL
+
+The software consists of a number of programs.
+
+ sshd Server program run on the server machine. This
+ listens for connections from client machines, and
+ whenever it receives a connection, it performs
+ authentication and starts serving the client.
+
+ ssh This is the client program used to log into another
+ machine or to execute commands on the other machine.
+ "slogin" is another name for this program.
+
+ scp Securely copies files from one machine to another.
+
+ ssh-keygen Used to create RSA keys (host keys and user
+ authentication keys).
+
+ ssh-agent Authentication agent. This can be used to hold RSA
+ keys for authentication.
+
+ ssh-add Used to register new keys with the agent.
+
+ make-ssh-known-hosts
+ Used to create the /etc/ssh_known_hosts file.
+
+
+Ssh is the program users normally use. It is started as
+
+ ssh host
+
+or
+
+ ssh host command
+
+The first form opens a new shell on the remote machine (after
+authentication). The latter form executes the command on the remote
+machine.
+
+When started, the ssh connects sshd on the server machine, verifies
+that the server machine really is the machine it wanted to connect,
+exchanges encryption keys (in a manner which prevents an outside
+listener from getting the keys), performs authentication using .rhosts
+and /etc/hosts.equiv, RSA authentication, or conventional password
+based authentication. The server then (normally) allocates a
+pseudo-terminal and starts an interactive shell or user program.
+
+The TERM environment variable (describing the type of the user's
+terminal) is passed from the client side to the remote side. Also,
+terminal modes will be copied from the client side to the remote side
+to preserve user preferences (e.g., the erase character).
+
+If the DISPLAY variable is set on the client side, the server will
+create a dummy X server and set DISPLAY accordingly. Any connections
+to the dummy X server will be forwarded through the secure channel,
+and will be made to the real X server from the client side. An
+arbitrary number of X programs can be started during the session, and
+starting them does not require anything special from the user. (Note
+that the user must not manually set DISPLAY, because then it would
+connect directly to the real display instead of going through the
+encrypted channel). This behavior can be disabled in the
+configuration file or by giving the -x option to the client.
+
+Arbitrary IP ports can be forwarded over the secure channel. The
+program then creates a port on one side, and whenever a connection is
+opened to this port, it will be passed over the secure channel, and a
+connection will be made from the other side to a specified host:port
+pair. Arbitrary IP forwarding must always be explicitly requested,
+and cannot be used to forward privileged ports (unless the user is
+root). It is possible to specify automatic forwards in a per-user
+configuration file, for example to make electronic cash systems work
+securely.
+
+If there is an authentication agent on the client side, connection to
+it will be automatically forwarded to the server side.
+
+For more infomation, see the manual pages ssh(1), sshd(8), scp(1),
+ssh-keygen(1), ssh-agent(1), ssh-add(1), and make-ssh-known-hosts(1)
+included in this distribution.
+
+
+X11 CONNECTION FORWARDING
+
+X11 forwarding serves two purposes: it is a convenience to the user
+because there is no need to set the DISPLAY variable, and it provides
+encrypted X11 connections. I cannot think of any other easy way to
+make X11 connections encrypted; modifying the X server, clients or
+libraries would require special work for each machine, vendor and
+application. Widely used IP-level encryption does not seem likely for
+several years. Thus what we have left is faking an X server on the
+same machine where the clients are run, and forwarding the connections
+to a real X server over the secure channel.
+
+X11 forwarding works as follows. The client extracts Xauthority
+information for the server. It then creates random authorization
+data, and sends the random data to the server. The server allocates
+an X11 display number, and stores the (fake) Xauthority data for this
+display. Whenever an X11 connection is opened, the server forwards
+the connection over the secure channel to the client, and the client
+parses the first packet of the X11 protocol, substitutes real
+authentication data for the fake data (if the fake data matched), and
+forwards the connection to the real X server.
+
+If the display does not have Xauthority data, the server will create a
+unix domain socket in /tmp/.X11-unix, and use the unix domain socket
+as the display. No authentication information is forwarded in this
+case. X11 connections are again forwarded over the secure channel.
+To the X server the connections appear to come from the client
+machine, and the server must have connections allowed from the local
+machine. Using authentication data is always recommended because not
+using it makes the display insecure. If XDM is used, it automatically
+generates the authentication data.
+
+One should be careful not to use "xin" or "xstart" or other similar
+scripts that explicitly set DISPLAY to start X sessions in a remote
+machine, because the connection will then not go over the secure
+channel. The recommended way to start a shell in a remote machine is
+
+ xterm -e ssh host &
+
+and the recommended way to execute an X11 application in a remote
+machine is
+
+ ssh -n host emacs &
+
+If you need to type a password/passphrase for the remote machine,
+
+ ssh -f host emacs
+
+may be useful.
+
+
+
+RSA AUTHENTICATION
+
+RSA authentication is based on public key cryptograpy. The idea is
+that there are two encryption keys, one for encryption and another for
+decryption. It is not possible (on human timescale) to derive the
+decryption key from the encryption key. The encryption key is called
+the public key, because it can be given to anyone and it is not
+secret. The decryption key, on the other hand, is secret, and is
+called the private key.
+
+RSA authentication is based on the impossibility of deriving the
+private key from the public key. The public key is stored on the
+server machine in the user's $HOME/.ssh/authorized_keys file. The
+private key is only kept on the user's local machine, laptop, or other
+secure storage. Then the user tries to log in, the client tells the
+server the public key that the user wishes to use for authentication.
+The server then checks if this public key is admissible. If so, it
+generates a 256 bit random number, encrypts it with the public key,
+and sends the value to the client. The client then decrypts the
+number with its private key, computes a 128 bit MD5 checksum from the
+resulting data, and sends the checksum back to the server. (Only a
+checksum is sent to prevent chosen-plaintext attacks against RSA.)
+The server checks computes a checksum from the correct data,
+and compares the checksums. Authentication is accepted if the
+checksums match. (Theoretically this indicates that the client
+only probably knows the correct key, but for all practical purposes
+there is no doubt.)
+
+The RSA private key can be protected with a passphrase. The
+passphrase can be any string; it is hashed with MD5 to produce an
+encryption key for IDEA, which is used to encrypt the private part of
+the key file. With passphrase, authorization requires access to the key
+file and the passphrase. Without passphrase, authorization only
+depends on possession of the key file.
+
+RSA authentication is the most secure form of authentication supported
+by this software. It does not rely on the network, routers, domain
+name servers, or the client machine. The only thing that matters is
+access to the private key.
+
+All this, of course, depends on the security of the RSA algorithm
+itself. RSA has been widely known since about 1978, and no effective
+methods for breaking it are known if it is used properly. Care has
+been taken to avoid the well-known pitfalls. Breaking RSA is widely
+believed to be equivalent to factoring, which is a very hard
+mathematical problem that has received considerable public research.
+So far, no effective methods are known for numbers bigger than about
+512 bits. However, as computer speeds and factoring methods are
+increasing, 512 bits can no longer be considered secure. The
+factoring work is exponential, and 768 or 1024 bits are widely
+considered to be secure in the near future.
+
+
+RHOSTS AUTHENTICATION
+
+Conventional .rhosts and hosts.equiv based authentication mechanisms
+are fundamentally insecure due to IP, DNS (domain name server) and
+routing spoofing attacks. Additionally this authentication method
+relies on the integrity of the client machine. These weaknesses is
+tolerable, and been known and exploited for a long time.
+
+Ssh provides an improved version of these types of authentication,
+because they are very convenient for the user (and allow easy
+transition from rsh and rlogin). It permits these types of
+authentication, but additionally requires that the client host be
+authenticated using RSA.
+
+The server has a list of host keys stored in /etc/ssh_known_host, and
+additionally each user has host keys in $HOME/.ssh/known_hosts. Ssh
+uses the name servers to obtain the canonical name of the client host,
+looks for its public key in its known host files, and requires the
+client to prove that it knows the private host key. This prevents IP
+and routing spoofing attacks (as long as the client machine private
+host key has not been compromized), but is still vulnerable to DNS
+attacks (to a limited extent), and relies on the integrity of the
+client machine as to who is requesting to log in. This prevents
+outsiders from attacking, but does not protect against very powerful
+attackers. If maximal security is desired, only RSA authentication
+should be used.
+
+It is possible to enable conventional .rhosts and /etc/hosts.equiv
+authentication (without host authentication) at compile time by giving
+the option --with-rhosts to configure. However, this is not
+recommended, and is not done by default.
+
+These weaknesses are present in rsh and rlogin. No improvement in
+security will be obtained unless rlogin and rsh are completely
+disabled (commented out in /etc/inetd.conf). This is highly
+recommended.
+
+
+WEAKEST LINKS IN SECURITY
+
+One should understand that while this software may provide
+cryptographically secure communications, it may be easy to
+monitor the communications at their endpoints.
+
+Basically, anyone with root access on the local machine on which you
+are running the software may be able to do anything. Anyone with root
+access on the server machine may be able to monitor your
+communications, and a very talented root user might even be able to
+send his/her own requests to your authentication agent.
+
+One should also be aware that computers send out electromagnetic
+radition that can sometimes be picked up hundreds of meters away.
+Your keyboard is particularly easy to listen to. The image on your
+monitor might also be seen on another monitor in a van parked behind
+your house.
+
+Beware that unwanted visitors might come to your home or office and
+use your machine while you are away. They might also make
+modifications or install bugs in your hardware or software.
+
+Beware that the most effective way for someone to decrypt your data
+may be with a rubber hose.
+
+
+LEGAL ISSUES
+
+As far as I am concerned, anyone is permitted to use this software
+freely. However, see the file COPYING for detailed copying,
+licensing, and distribution information.
+
+In some countries, particularly France, Russia, Iraq, and Pakistan,
+it may be illegal to use any encryption at all without a special
+permit, and the rumor has it that you cannot get a permit for any
+strong encryption.
+
+This software may be freely imported into the United States; however,
+the United States Government may consider re-exporting it a criminal
+offence.
+
+Note that any information and cryptographic algorithms used in this
+software are publicly available on the Internet and at any major
+bookstore, scientific library, or patent office worldwide.
+
+THERE IS NO WARRANTY FOR THIS PROGRAM. Please consult the file
+COPYING for more information.
+
+
+MAILING LISTS AND OTHER INFORMATION
+
+There is a mailing list for ossh. It is ossh@sics.se. If you would
+like to join, send a message to majordomo@sics.se with "subscribe
+ssh" in body.
+
+The WWW home page for ssh is http://www.cs.hut.fi/ssh. It contains an
+archive of the mailing list, and detailed information about new
+releases, mailing lists, and other relevant issues.
+
+Bug reports should be sent to ossh-bugs@sics.se.
+
+
+ABOUT THE AUTHOR
+
+This software was written by Tatu Ylonen <ylo@cs.hut.fi>. I work as a
+researcher at Helsinki University of Technology, Finland. For more
+information, see http://www.cs.hut.fi/~ylo/. My PGP public key is
+available via finger from ylo@cs.hut.fi and from the key servers. I
+prefer PGP encrypted mail.
+
+The author can be contacted via ordinary mail at
+ Tatu Ylonen
+ Helsinki University of Technology
+ Otakaari 1
+ FIN-02150 ESPOO
+ Finland
+
+ Fax. +358-0-4513293
+
+
+ACKNOWLEDGEMENTS
+
+I thank Tero Kivinen, Timo Rinne, Janne Snabb, and Heikki Suonsivu for
+their help and comments in the design, implementation and porting of
+this software. I also thank numerous contributors, including but not
+limited to Walker Aumann, Jurgen Botz, Hans-Werner Braun, Stephane
+Bortzmeyer, Adrian Colley, Michael Cooper, David Dombek, Jerome
+Etienne, Bill Fithen, Mark Fullmer, Bert Gijsbers, Andreas Gustafsson,
+Michael Henits, Steve Johnson, Thomas Koenig, Felix Leitner, Gunnar
+Lindberg, Andrew Macpherson, Marc Martinec, Paul Mauvais, Donald
+McKillican, Leon Mlakar, Robert Muchsel, Mark Treacy, Bryan
+O'Sullivan, Mikael Suokas, Ollivier Robert, Jakob Schlyter, Tomasz
+Surmacz, Alvar Vinacua, Petri Virkkula, Michael Warfield, and
+Cristophe Wolfhugel.
+
+Thanks also go to Philip Zimmermann, whose PGP software and the
+associated legal battle provided inspiration, motivation, and many
+useful techniques, and to Bruce Schneier whose book Applied
+Cryptography has done a great service in widely distributing knowledge
+about cryptographic methods.
+
+
+Copyright (c) 1995 Tatu Ylonen, Espoo, Finland.
diff --git a/usr.bin/ssh/README.AFS-KERBEROS b/usr.bin/ssh/README.AFS-KERBEROS
new file mode 100644
index 00000000000..6e03c976b51
--- /dev/null
+++ b/usr.bin/ssh/README.AFS-KERBEROS
@@ -0,0 +1,44 @@
+
+ssh-1.2.26-afs-kerberos.patch-1
+AFS, Kerberos v4 support for SSH
+
+Here are the extra flags to configure, and what they do:
+
+--with-krb4[=PATH] Compile in Kerberos v4 support:
+ Kerberos v4 authentication
+ Kerberos v4 password authentication
+ Kerberos v4 ~/.klogin authorization
+
+These are all enabled by the 'KerberosAuthentication' config option.
+Kerberos v4 and Kerberos v5 support are mutually exclusive for now.
+PATH default is /usr/kerberos.
+
+--with-hesiod[=PATH] Compile in support for Hesiod:
+ getpwnam(), getpwuid() replacements
+
+--with-afs Compile in AFS support (requires KTH krb4):
+ ticket/token passing
+ process authentication groups
+ local Xauthority files (for AFS home dirs)
+ /ticket TKT_ROOT directory (if it exists)
+
+Binaries built with AFS support will work just fine on non-AFS machines!
+You will need to use the KTH krb4 libs (ftp://ftp.pdc.kth.se/pub/krb/src),
+or just their libkafs, also available separately from CMU as libkrbafs
+(http://andrew2.andrew.cmu.edu/dist/krbafs.html).
+
+Additional Kerberos client and server config options (and their defaults):
+
+ KerberosAuthentication yes
+ KerberosOrLocalPasswd no
+ KerberosTgtPassing yes
+ AFSTokenPassing yes
+ KerberosTicketCleanup yes
+
+See sshd(8) and ssh(1) for details.
+
+The latest version of this patch can be found at
+
+ http://www.monkey.org/~dugsong/ssh-afs-kerberos.html
+
+dugsong@monkey.org
diff --git a/usr.bin/ssh/RFC b/usr.bin/ssh/RFC
new file mode 100644
index 00000000000..91195b16255
--- /dev/null
+++ b/usr.bin/ssh/RFC
@@ -0,0 +1,2187 @@
+
+
+
+
+
+
+Network Working Group T. Ylonen
+Internet-Draft Helsinki University of Technology
+draft-ylonen-ssh-protocol-00.txt 15 November 1995
+Expires: 15 May 1996
+
+
+ The SSH (Secure Shell) Remote Login Protocol
+
+Status of This Memo
+
+ This document is an Internet-Draft. Internet-Drafts are working
+ documents of the Internet Engineering Task Force (IETF), its areas,
+ and its working groups. Note that other groups may also distribute
+ working documents as Internet-Drafts.
+
+ Internet-Drafts are draft documents valid for a maximum of six
+ months and may be updated, replaced, or obsoleted by other docu-
+ ments at any time. It is inappropriate to use Internet-Drafts as
+ reference material or to cite them other than as ``work in pro-
+ gress.''
+
+ To learn the current status of any Internet-Draft, please check the
+ ``1id-abstracts.txt'' listing contained in the Internet- Drafts
+ Shadow Directories on ftp.is.co.za (Africa), nic.nordu.net (Europe),
+ munnari.oz.au (Pacific Rim), ds.internic.net (US East Coast), or
+ ftp.isi.edu (US West Coast).
+
+ The distribution of this memo is unlimited.
+
+Introduction
+
+ SSH (Secure Shell) is a program to log into another computer over a
+ network, to execute commands in a remote machine, and to move files
+ from one machine to another. It provides strong authentication and
+ secure communications over insecure networks. Its features include
+ the following:
+
+ o Closes several security holes (e.g., IP, routing, and DNS spoof-
+ ing). New authentication methods: .rhosts together with RSA
+ [RSA] based host authentication, and pure RSA authentication.
+
+ o All communications are automatically and transparently
+ encrypted. Encryption is also used to protect integrity.
+
+ o X11 connection forwarding provides secure X11 sessions.
+
+ o Arbitrary TCP/IP ports can be redirected over the encrypted
+ channel in both directions.
+
+
+
+Ylonen [Page 1]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ o Client RSA-authenticates the server machine in the beginning of
+ every connection to prevent trojan horses (by routing or DNS
+ spoofing) and man-in-the-middle attacks, and the server RSA-
+ authenticates the client machine before accepting .rhosts or
+ /etc/hosts.equiv authentication (to prevent DNS, routing, or IP
+ spoofing).
+
+ o An authentication agent, running in the user's local workstation
+ or laptop, can be used to hold the user's RSA authentication
+ keys.
+
+ The goal has been to make the software as easy to use as possible for
+ ordinary users. The protocol has been designed to be as secure as
+ possible while making it possible to create implementations that are
+ easy to use and install. The sample implementation has a number of
+ convenient features that are not described in this document as they
+ are not relevant for the protocol.
+
+
+Overview of the Protocol
+
+ The software consists of a server program running on a server
+ machine, and a client program running on a client machine (plus a few
+ auxiliary programs). The machines are connected by an insecure IP
+ [RFC0791] network (that can be monitored, tampered with, and spoofed
+ by hostile parties).
+
+ A connection is always initiated by the client side. The server
+ listens on a specific port waiting for connections. Many clients may
+ connect to the same server machine.
+
+ The client and the server are connected via a TCP/IP [RFC0793] socket
+ that is used for bidirectional communication. Other types of tran-
+ sport can be used but are currently not defined.
+
+ When the client connects the server, the server accepts the connec-
+ tion and responds by sending back its version identification string.
+ The client parses the server's identification, and sends its own
+ identification. The purpose of the identification strings is to
+ validate that the connection was to the correct port, declare the
+ protocol version number used, and to declare the software version
+ used on each side (for debugging purposes). The identification
+ strings are human-readable. If either side fails to understand or
+ support the other side's version, it closes the connection.
+
+ After the protocol identification phase, both sides switch to a
+ packet based binary protocol. The server starts by sending its host
+ key (every host has an RSA key used to authenticate the host), server
+
+
+
+Ylonen [Page 2]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ key (an RSA key regenerated every hour), and other information to the
+ client. The client then generates a 256 bit session key, encrypts it
+ using both RSA keys (see below for details), and sends the encrypted
+ session key and selected cipher type to the server. Both sides then
+ turn on encryption using the selected algorithm and key. The server
+ sends an encrypted confirmation message to the client.
+
+ The client then authenticates itself using any of a number of authen-
+ tication methods. The currently supported authentication methods are
+ .rhosts or /etc/hosts.equiv authentication (disabled by default), the
+ same with RSA-based host authentication, RSA authentication, and
+ password authentication.
+
+ After successful authentication, the client makes a number of
+ requests to prepare for the session. Typical requests include allo-
+ cating a pseudo tty, starting X11 [X11] or TCP/IP port forwarding,
+ starting authentication agent forwarding, and executing the shell or
+ a command.
+
+ When a shell or command is executed, the connection enters interac-
+ tive session mode. In this mode, data is passed in both directions,
+ new forwarded connections may be opened, etc. The interactive ses-
+ sion normally terminates when the server sends the exit status of the
+ program to the client.
+
+
+ The protocol makes several reservations for future extensibility.
+ First of all, the initial protocol identification messages include
+ the protocol version number. Second, the first packet by both sides
+ includes a protocol flags field, which can be used to agree on exten-
+ sions in a compatible manner. Third, the authentication and session
+ preparation phases work so that the client sends requests to the
+ server, and the server responds with success or failure. If the
+ client sends a request that the server does not support, the server
+ simply returns failure for it. This permits compatible addition of
+ new authentication methods and preparation operations. The interac-
+ tive session phase, on the other hand, works asynchronously and does
+ not permit the use of any extensions (because there is no easy and
+ reliable way to signal rejection to the other side and problems would
+ be hard to debug). Any compatible extensions to this phase must be
+ agreed upon during any of the earlier phases.
+
+The Binary Packet Protocol
+
+ After the protocol identification strings, both sides only send spe-
+ cially formatted packets. The packet layout is as follows:
+
+ o Packet length: 32 bit unsigned integer, coded as four 8-bit
+
+
+
+Ylonen [Page 3]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ bytes, msb first. Gives the length of the packet, not including
+ the length field and padding. The maximum length of a packet
+ (not including the length field and padding) is 262144 bytes.
+
+ o Padding: 1-8 bytes of random data (or zeroes if not encrypting).
+ The amount of padding is (8 - (length % 8)) bytes (where %
+ stands for the modulo operator). The rationale for always hav-
+ ing some random padding at the beginning of each packet is to
+ make known plaintext attacks more difficult.
+
+ o Packet type: 8-bit unsigned byte. The value 255 is reserved for
+ future extension.
+
+ o Data: binary data bytes, depending on the packet type. The
+ number of data bytes is the "length" field minus 5.
+
+ o Check bytes: 32-bit crc, four 8-bit bytes, msb first. The crc
+ is the Cyclic Redundancy Check, with the polynomial 0xedb88320,
+ of the Padding, Packet type, and Data fields. The crc is com-
+ puted before any encryption.
+
+ The packet, except for the length field, may be encrypted using any
+ of a number of algorithms. The length of the encrypted part (Padding
+ + Type + Data + Check) is always a multiple of 8 bytes. Typically
+ the cipher is used in a chained mode, with all packets chained
+ together as if it was a single data stream (the length field is never
+ included in the encryption process). Details of encryption are
+ described below.
+
+ When the session starts, encryption is turned off. Encryption is
+ enabled after the client has sent the session key. The encryption
+ algorithm to use is selected by the client.
+
+
+Packet Compression
+
+ If compression is supported (it is an optional feature, see
+ SSH_CMSG_REQUEST_COMPRESSION below), the packet type and data fields
+ of the packet are compressed using the gzip deflate algorithm [GZIP].
+ If compression is in effect, the packet length field indicates the
+ length of the compressed data, plus 4 for the crc. The amount of
+ padding is computed from the compressed data, so that the amount of
+ data to be encrypted becomes a multiple of 8 bytes.
+
+ When compressing, the packets (type + data portions) in each direc-
+ tion are compressed as if they formed a continuous data stream, with
+ only the current compression block flushed between packets. This
+ corresponds to the GNU ZLIB library Z_PARTIAL_FLUSH option. The
+
+
+
+Ylonen [Page 4]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ compression dictionary is not flushed between packets. The two
+ directions are compressed independently of each other.
+
+
+Packet Encryption
+
+ The protocol supports several encryption methods. During session
+ initialization, the server sends a bitmask of all encryption methods
+ that it supports, and the client selects one of these methods. The
+ client also generates a 256-bit random session key (32 8-bit bytes)
+ and sends it to the server.
+
+ The encryption methods supported by the current implementation, and
+ their codes are:
+
+ SSH_CIPHER_NONE 0 No encryption
+ SSH_CIPHER_IDEA 1 IDEA in CFB mode
+ SSH_CIPHER_DES 2 DES in CBC mode
+ SSH_CIPHER_3DES 3 Triple-DES in CBC mode
+ SSH_CIPHER_TSS 4 An experimental stream cipher
+ SSH_CIPHER_RC4 5 RC4
+
+
+ All implementations are required to support SSH_CIPHER_DES and
+ SSH_CIPHER_3DES. Supporting SSH_CIPHER_IDEA, SSH_CIPHER_RC4, and
+ SSH_CIPHER_NONE is recommended. Support for SSH_CIPHER_TSS is
+ optional (and it is not described in this document). Other ciphers
+ may be added at a later time; support for them is optional.
+
+ For encryption, the encrypted portion of the packet is considered a
+ linear byte stream. The length of the stream is always a multiple of
+ 8. The encrypted portions of consecutive packets (in the same direc-
+ tion) are encrypted as if they were a continuous buffer (that is, any
+ initialization vectors are passed from the previous packet to the
+ next packet). Data in each direction is encrypted independently.
+
+ SSH_CIPHER_DES
+ The key is taken from the first 8 bytes of the session key. The
+ least significant bit of each byte is ignored. This results in
+ 56 bits of key data. DES [DES] is used in CBC mode. The iv
+ (initialization vector) is initialized to all zeroes.
+
+ SSH_CIPHER_3DES
+ The variant of triple-DES used here works as follows: there are
+ three independent DES-CBC ciphers, with independent initializa-
+ tion vectors. The data (the whole encrypted data stream) is
+ first encrypted with the first cipher, then decrypted with the
+ second cipher, and finally encrypted with the third cipher. All
+
+
+
+Ylonen [Page 5]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ these operations are performed in CBC mode.
+
+ The key for the first cipher is taken from the first 8 bytes of
+ the session key; the key for the next cipher from the next 8
+ bytes, and the key for the third cipher from the following 8
+ bytes. All three initialization vectors are initialized to
+ zero.
+
+ (Note: the variant of 3DES used here differs from some other
+ descriptions.)
+
+ SSH_CIPHER_IDEA
+ The key is taken from the first 16 bytes of the session key.
+ IDEA [IDEA] is used in CFB mode. The initialization vector is
+ initialized to all zeroes.
+
+ SSH_CIPHER_TSS
+ All 32 bytes of the session key are used as the key.
+
+ There is no reference available for the TSS algorithm; it is
+ currently only documented in the sample implementation source
+ code. The security of this cipher is unknown (but it is quite
+ fast). The cipher is basically a stream cipher that uses MD5 as
+ a random number generator and takes feedback from the data.
+
+ SSH_CIPHER_RC4
+ The first 16 bytes of the session key are used as the key for
+ the server to client direction. The remaining 16 bytes are used
+ as the key for the client to server direction. This gives
+ independent 128-bit keys for each direction.
+
+ This algorithm is the alleged RC4 cipher posted to the Usenet in
+ 1995. It is widely believed to be equivalent with the original
+ RSADSI RC4 cipher. This is a very fast algorithm.
+
+
+Data Type Encodings
+
+ The Data field of each packet contains data encoded as described in
+ this section. There may be several data items; each item is coded as
+ described here, and their representations are concatenated together
+ (without any alignment or padding).
+
+ Each data type is stored as follows:
+
+ 8-bit byte
+ The byte is stored directly as a single byte.
+
+
+
+
+Ylonen [Page 6]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ 32-bit unsigned integer
+ Stored in 4 bytes, msb first.
+
+ Arbitrary length binary string
+ First 4 bytes are the length of the string, msb first (not
+ including the length itself). The following "length" bytes are
+ the string value. There are no terminating null characters.
+
+ Multiple-precision integer
+ First 2 bytes are the number of bits in the integer, msb first
+ (for example, the value 0x00012345 would have 17 bits). The
+ value zero has zero bits. It is permissible that the number of
+ bits be larger than the real number of bits.
+
+ The number of bits is followed by (bits + 7) / 8 bytes of binary
+ data, msb first, giving the value of the integer.
+
+
+TCP/IP Port Number and Other Options
+
+ The server listens for connections on TCP/IP port 22.
+
+ The client may connect the server from any port. However, if the
+ client wishes to use any form of .rhosts or /etc/hosts.equiv authen-
+ tication, it must connect from a privileged port (less than 1024).
+
+ For the IP Type of Service field [RFC0791], it is recommended that
+ interactive sessions (those having a user terminal or forwarding X11
+ connections) use the IPTOS_LOWDELAY, and non-interactive connections
+ use IPTOS_THROUGHPUT.
+
+ It is recommended that keepalives are used, because otherwise pro-
+ grams on the server may never notice if the other end of the connec-
+ tion is rebooted.
+
+
+Protocol Version Identification
+
+ After the socket is opened, the server sends an identification
+ string, which is of the form "SSH-<protocolmajor>.<protocolminor>-
+ <version>\n", where <protocolmajor> and <protocolminor> are integers
+ and specify the protocol version number (not software distribution
+ version). <version> is server side software version string (max 40
+ characters); it is not interpreted by the remote side but may be use-
+ ful for debugging.
+
+ The client parses the server's string, and sends a corresponding
+ string with its own information in response. If the server has lower
+
+
+
+Ylonen [Page 7]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ version number, and the client contains special code to emulate it,
+ the client responds with the lower number; otherwise it responds with
+ its own number. The server then compares the version number the
+ client sent with its own, and determines whether they can work
+ together. The server either disconnects, or sends the first packet
+ using the binary packet protocol and both sides start working accord-
+ ing to the lower of the protocol versions.
+
+ By convention, changes which keep the protocol compatible with previ-
+ ous versions keep the same major protocol version; changes that are
+ not compatible increment the major version (which will hopefully
+ never happen). The version described in this document is 1.3.
+
+ The client will
+
+Key Exchange and Server Host Authentication
+
+ The first message sent by the server using the packet protocol is
+ SSH_SMSG_PUBLIC_KEY. It declares the server's host key, server pub-
+ lic key, supported ciphers, supported authentication methods, and
+ flags for protocol extensions. It also contains a 64-bit random
+ number (cookie) that must be returned in the client's reply (to make
+ IP spoofing more difficult). No encryption is used for this message.
+
+ Both sides compute a session id as follows. The modulus of the
+ server key is interpreted as a byte string (without explicit length
+ field, with minimum length able to hold the whole value), most signi-
+ ficant byte first. This string is concatenated with the server host
+ key interpreted the same way. Additionally, the cookie is con-
+ catenated with this. Both sides compute MD5 of the resulting string.
+ The resulting 16 bytes (128 bits) are stored by both parties and are
+ called the session id.
+
+ The client responds with a SSH_CMSG_SESSION_KEY message, which con-
+ tains the selected cipher type, a copy of the 64-bit cookie sent by
+ the server, client's protocol flags, and a session key encrypted with
+ both the server's host key and server key. No encryption is used for
+ this message.
+
+ The session key is 32 8-bit bytes (a total of 256 random bits gen-
+ erated by the client). The client first xors the 16 bytes of the
+ session id with the first 16 bytes of the session key. The resulting
+ string is then encrypted using the smaller key (one with smaller
+ modulus), and the result is then encrypted using the other key. The
+ number of bits in the public modulus of the two keys must differ by
+ at least 128 bits.
+
+ At each encryption step, a multiple-precision integer is constructed
+
+
+
+Ylonen [Page 8]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ from the data to be encrypted as follows (the integer is here inter-
+ preted as a sequence of bytes, msb first; the number of bytes is the
+ number of bytes needed to represent the modulus).
+
+ The most significant byte (which is only partial as the value must be
+ less than the public modulus, which is never a power of two) is zero.
+
+ The next byte contains the value 2 (which stands for public-key
+ encrypted data in the PKCS standard [PKCS#1]). Then, there are non-
+ zero random bytes to fill any unused space, a zero byte, and the data
+ to be encrypted in the least significant bytes, the last byte of the
+ data in the least significant byte.
+
+ This algorithm is used twice. First, it is used to encrypt the 32
+ random bytes generated by the client to be used as the session key
+ (xored by the session id). This value is converted to an integer as
+ described above, and encrypted with RSA using the key with the
+ smaller modulus. The resulting integer is converted to a byte
+ stream, msb first. This byte stream is padded and encrypted identi-
+ cally using the key with the larger modulus.
+
+ After the client has sent the session key, it starts to use the
+ selected algorithm and key for decrypting any received packets, and
+ for encrypting any sent packets. Separate ciphers are used for dif-
+ ferent directions (that is, both directions have separate initializa-
+ tion vectors or other state for the ciphers).
+
+ When the server has received the session key message, and has turned
+ on encryption, it sends a SSH_SMSG_SUCCESS message to the client.
+
+ The recommended size of the host key is 1024 bits, and 768 bits for
+ the server key. The minimum size is 512 bits for the smaller key.
+
+
+Declaring the User Name
+
+ The client then sends a SSH_CMSG_USER message to the server. This
+ message specifies the user name to log in as.
+
+ The server validates that such a user exists, checks whether authen-
+ tication is needed, and responds with either SSH_SMSG_SUCCESS or
+ SSH_SMSG_FAILURE. SSH_SMSG_SUCCESS indicates that no authentication
+ is needed for this user (no password), and authentication phase has
+ now been completed. SSH_SMSG_FAILURE indicates that authentication
+ is needed (or the user does not exist).
+
+ If the user does not exist, it is recommended that this returns
+ failure, but the server keeps reading messages from the client, and
+
+
+
+Ylonen [Page 9]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ responds to any messages (except SSH_MSG_DISCONNECT, SSH_MSG_IGNORE,
+ and SSH_MSG_DEBUG) with SSH_SMSG_FAILURE. This way the client cannot
+ be certain whether the user exists.
+
+
+Authentication Phase
+
+ Provided the server didn't immediately accept the login, an authenti-
+ cation exchange begins. The client sends messages to the server
+ requesting different types of authentication in arbitrary order as
+ many times as desired (however, the server may close the connection
+ after a timeout). The server always responds with SSH_SMSG_SUCCESS
+ if it has accepted the authentication, and with SSH_SMSG_FAILURE if
+ it has denied authentication with the requested method or it does not
+ recognize the message. Some authentication methods cause an exchange
+ of further messages before the final result is sent. The authentica-
+ tion phase ends when the server responds with success.
+
+ The recommended value for the authentication timeout (timeout before
+ disconnecting if no successful authentication has been made) is 5
+ minutes.
+
+ The following authentication methods are currently supported:
+
+ SSH_AUTH_RHOSTS 1 .rhosts or /etc/hosts.equiv
+ SSH_AUTH_RSA 2 pure RSA authentication
+ SSH_AUTH_PASSWORD 3 password authentication
+ SSH_AUTH_RHOSTS_RSA 4 .rhosts with RSA host authentication
+
+
+ SSH_AUTH_RHOSTS
+
+ This is the authentication method used by rlogin and rsh
+ [RFC1282].
+
+ The client sends SSH_CMSG_AUTH_RHOSTS with the client-side user
+ name as an argument.
+
+ The server checks whether to permit authentication. On UNIX
+ systems, this is usually done by checking /etc/hosts.equiv, and
+ .rhosts in the user's home directory. The connection must come
+ from a privileged port.
+
+ It is recommended that the server checks that there are no IP
+ options (such as source routing) specified for the socket before
+ accepting this type of authentication. The client host name
+ should be reverse-mapped and then forward mapped to ensure that
+ it has the proper IP-address.
+
+
+
+Ylonen [Page 10]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ This authentication method trusts the remote host (root on the
+ remote host can pretend to be any other user on that host), the
+ name services, and partially the network: anyone who can see
+ packets coming out from the server machine can do IP-spoofing
+ and pretend to be any machine; however, the protocol prevents
+ blind IP-spoofing (which used to be possible with rlogin).
+
+ Many sites probably want to disable this authentication method
+ because of the fundamental insecurity of conventional .rhosts or
+ /etc/hosts.equiv authentication when faced with spoofing. It is
+ recommended that this method not be supported by the server by
+ default.
+
+ SSH_AUTH_RHOSTS_RSA
+
+ In addition to conventional .rhosts and hosts.equiv authentica-
+ tion, this method additionally requires that the client host be
+ authenticated using RSA.
+
+ The client sends SSH_CMSG_AUTH_RHOSTS_RSA specifying the
+ client-side user name, and the public host key of the client
+ host.
+
+ The server first checks if normal .rhosts or /etc/hosts.equiv
+ authentication would be accepted, and if not, responds with
+ SSH_SMSG_FAILURE. Otherwise, it checks whether it knows the
+ host key for the client machine (using the same name for the
+ host that was used for checking the .rhosts and /etc/hosts.equiv
+ files). If it does not know the RSA key for the client, access
+ is denied and SSH_SMSG_FAILURE is sent.
+
+ If the server knows the host key of the client machine, it veri-
+ fies that the given host key matches that known for the client.
+ If not, access is denied and SSH_SMSG_FAILURE is sent.
+
+ The server then sends a SSH_SMSG_AUTH_RSA_CHALLENGE message con-
+ taining an encrypted challenge for the client. The challenge is
+ 32 8-bit random bytes (256 bits). When encrypted, the highest
+ (partial) byte is left as zero, the next byte contains the value
+ 2, the following are non-zero random bytes, followed by a zero
+ byte, and the challenge put in the remaining bytes. This is
+ then encrypted using RSA with the client host's public key.
+ (The padding and encryption algorithm is the same as that used
+ for the session key.)
+
+ The client decrypts the challenge using its private host key,
+ concatenates this with the session id, and computes an MD5
+ checksum of the resulting 48 bytes. The MD5 output is returned
+
+
+
+Ylonen [Page 11]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ as 16 bytes in a SSH_CMSG_AUTH_RSA_RESPONSE message. (MD5 is
+ used to deter chosen plaintext attacks against RSA; the session
+ id binds it to a specific session).
+
+ The server verifies that the MD5 of the decrypted challenge
+ returned by the client matches that of the original value, and
+ sends SSH_SMSG_SUCCESS if so. Otherwise it sends
+ SSH_SMSG_FAILURE and refuses the authentication attempt.
+
+ This authentication method trusts the client side machine in
+ that root on that machine can pretend to be any user on that
+ machine. Additionally, it trusts the client host key. The name
+ and/or IP address of the client host is only used to select the
+ public host key. The same host name is used when scanning
+ .rhosts or /etc/hosts.equiv and when selecting the host key. It
+ would in principle be possible to eliminate the host name
+ entirely and substitute it directly by the host key. IP and/or
+ DNS [RFC1034] spoofing can only be used to pretend to be a host
+ for which the attacker has the private host key.
+
+ SSH_AUTH_RSA
+
+ The idea behind RSA authentication is that the server recognizes
+ the public key offered by the client, generates a random chal-
+ lenge, and encrypts the challenge with the public key. The
+ client must then prove that it has the corresponding private key
+ by decrypting the challenge.
+
+ The client sends SSH_CMSG_AUTH_RSA with public key modulus (n)
+ as an argument.
+
+ The server may respond immediately with SSH_SMSG_FAILURE if it
+ does not permit authentication with this key. Otherwise it gen-
+ erates a challenge, encrypts it using the user's public key
+ (stored on the server and identified using the modulus), and
+ sends SSH_SMSG_AUTH_RSA_CHALLENGE with the challenge (mp-int) as
+ an argument.
+
+ The challenge is 32 8-bit random bytes (256 bits). When
+ encrypted, the highest (partial) byte is left as zero, the next
+ byte contains the value 2, the following are non-zero random
+ bytes, followed by a zero byte, and the challenge put in the
+ remaining bytes. This is then encrypted with the public key.
+ (The padding and encryption algorithm is the same as that used
+ for the session key.)
+
+ The client decrypts the challenge using its private key, con-
+ catenates it with the session id, and computes an MD5 checksum
+
+
+
+Ylonen [Page 12]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ of the resulting 48 bytes. The MD5 output is returned as 16
+ bytes in a SSH_CMSG_AUTH_RSA_RESPONSE message. (Note that the
+ MD5 is necessary to avoid chosen plaintext attacks against RSA;
+ the session id binds it to a specific session.)
+
+ The server verifies that the MD5 of the decrypted challenge
+ returned by the client matches that of the original value, and
+ sends SSH_SMSG_SUCCESS if so. Otherwise it sends
+ SSH_SMSG_FAILURE and refuses the authentication attempt.
+
+ This authentication method does not trust the remote host, the
+ network, name services, or anything else. Authentication is
+ based solely on the possession of the private identification
+ keys. Anyone in possession of the private keys can log in, but
+ nobody else.
+
+ The server may have additional requirements for a successful
+ authentiation. For example, to limit damage due to a comprom-
+ ised RSA key, a server might restrict access to a limited set of
+ hosts.
+
+ SSH_AUTH_PASSWORD
+
+ The client sends a SSH_CMSG_AUTH_PASSWORD message with the plain
+ text password. (Note that even though the password is plain
+ text inside the message, it is normally encrypted by the packet
+ mechanism.)
+
+ The server verifies the password, and sends SSH_SMSG_SUCCESS if
+ authentication was accepted and SSH_SMSG_FAILURE otherwise.
+
+ Note that the password is read from the user by the client; the
+ user never interacts with a login program.
+
+ This authentication method does not trust the remote host, the
+ network, name services or anything else. Authentication is
+ based solely on the possession of the password. Anyone in pos-
+ session of the password can log in, but nobody else.
+
+Preparatory Operations
+
+ After successful authentication, the server waits for a request from
+ the client, processes the request, and responds with SSH_SMSG_SUCCESS
+ whenever a request has been successfully processed. If it receives a
+ message that it does not recognize or it fails to honor a request, it
+ returns SSH_SMSG_FAILURE. It is expected that new message types
+ might be added to this phase in future.
+
+
+
+
+Ylonen [Page 13]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ The following messages are currently defined for this phase.
+
+ SSH_CMSG_REQUEST_COMPRESSION
+ Requests that compression be enabled for this session. A gzip-
+ compatible compression level (1-9) is passed as an argument.
+
+ SSH_CMSG_REQUEST_PTY
+ Requests that a pseudo terminal device be allocated for this
+ session. The user terminal type and terminal modes are supplied
+ as arguments.
+
+ SSH_CMSG_X11_REQUEST_FORWARDING
+ Requests forwarding of X11 connections from the remote machine
+ to the local machine over the secure channel. Causes an
+ internet-domain socket to be allocated and the DISPLAY variable
+ to be set on the server. X11 authentication data is automati-
+ cally passed to the server, and the client may implement spoof-
+ ing of authentication data for added security. The authentica-
+ tion data is passed as arguments.
+
+ SSH_CMSG_PORT_FORWARD_REQUEST
+ Requests forwarding of a TCP/IP port on the server host over the
+ secure channel. What happens is that whenever a connection is
+ made to the port on the server, a connection will be made from
+ the client end to the specified host/port. Any user can forward
+ unprivileged ports; only the root can forward privileged ports
+ (as determined by authentication done earlier).
+
+ SSH_CMSG_AGENT_REQUEST_FORWARDING
+ Requests forwarding of the connection to the authentication
+ agent.
+
+ SSH_CMSG_EXEC_SHELL
+ Starts a shell (command interpreter) for the user, and moves
+ into interactive session mode.
+
+ SSH_CMSG_EXEC_CMD
+ Executes the given command (actually "<shell> -c <command>" or
+ equivalent) for the user, and moves into interactive session
+ mode.
+
+
+Interactive Session and Exchange of Data
+
+ During the interactive session, any data written by the shell or com-
+ mand running on the server machine is forwarded to stdin or stderr on
+ the client machine, and any input available from stdin on the client
+ machine is forwarded to the program on the server machine.
+
+
+
+Ylonen [Page 14]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ All exchange is asynchronous; either side can send at any time, and
+ there are no acknowledgements (TCP/IP already provides reliable tran-
+ sport, and the packet protocol protects against tampering or IP
+ spoofing).
+
+ When the client receives EOF from its standard input, it will send
+ SSH_CMSG_EOF; however, this in no way terminates the exchange. The
+ exchange terminates and interactive mode is left when the server
+ sends SSH_SMSG_EXITSTATUS to indicate that the client program has
+ terminated. Alternatively, either side may disconnect at any time by
+ sending SSH_MSG_DISCONNECT or closing the connection.
+
+ The server may send any of the following messages:
+
+ SSH_SMSG_STDOUT_DATA
+ Data written to stdout by the program running on the server.
+ The data is passed as a string argument. The client writes this
+ data to stdout.
+
+ SSH_SMSG_STDERR_DATA
+ Data written to stderr by the program running on the server.
+ The data is passed as a string argument. The client writes this
+ data to stderr. (Note that if the program is running on a tty,
+ it is not possible to separate stdout and stderr data, and all
+ data will be sent as stdout data.)
+
+ SSH_SMSG_EXITSTATUS
+ Indicates that the shell or command has exited. Exit status is
+ passed as an integer argument. This message causes termination
+ of the interactive session.
+
+ SSH_SMSG_AGENT_OPEN
+ Indicates that someone on the server side is requesting a con-
+ nection to the authentication agent. The server-side channel
+ number is passed as an argument. The client must respond with
+ either SSH_CHANNEL_OPEN_CONFIRMATION or
+ SSH_CHANNEL_OPEN_FAILURE.
+
+ SSH_SMSG_X11_OPEN
+ Indicates that a connection has been made to the X11 socket on
+ the server side and should be forwarded to the real X server.
+ An integer argument indicates the channel number allocated for
+ this connection on the server side. The client should send back
+ either SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+ SSH_MSG_CHANNEL_OPEN_FAILURE with the same server side channel
+ number.
+
+ SSH_MSG_PORT_OPEN
+
+
+
+Ylonen [Page 15]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ Indicates that a connection has been made to a port on the
+ server side for which forwarding has been requested. Arguments
+ are server side channel number, host name to connect to, and
+ port to connect to. The client should send back either
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+ SSH_MSG_CHANNEL_OPEN_FAILURE with the same server side channel
+ number.
+
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION
+ This is sent by the server to indicate that it has opened a con-
+ nection as requested in a previous message. The first argument
+ indicates the client side channel number, and the second argu-
+ ment is the channel number that the server has allocated for
+ this connection.
+
+ SSH_MSG_CHANNEL_OPEN_FAILURE
+ This is sent by the server to indicate that it failed to open a
+ connection as requested in a previous message. The client-side
+ channel number is passed as an argument. The client will close
+ the descriptor associated with the channel and free the channel.
+
+ SSH_MSG_CHANNEL_DATA
+ This packet contains data for a channel from the server. The
+ first argument is the client-side channel number, and the second
+ argument (a string) is the data.
+
+ SSH_MSG_CHANNEL_CLOSE
+ This is sent by the server to indicate that whoever was in the
+ other end of the channel has closed it. The argument is the
+ client side channel number. The client will let all buffered
+ data in the channel to drain, and when ready, will close the
+ socket, free the channel, and send the server a
+ SSH_MSG_CHANNEL_CLOSE_CONFIRMATION message for the channel.
+
+ SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
+ This is send by the server to indicate that a channel previously
+ closed by the client has now been closed on the server side as
+ well. The argument indicates the client channel number. The
+ client frees the channel.
+
+ The client may send any of the following messages:
+
+ SSH_CMSG_STDIN_DATA
+ This is data to be sent as input to the program running on the
+ server. The data is passed as a string.
+
+ SSH_CMSG_EOF
+ Indicates that the client has encountered EOF while reading
+
+
+
+Ylonen [Page 16]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ standard input. The server will allow any buffered input data
+ to drain, and will then close the input to the program.
+
+ SSH_CMSG_WINDOW_SIZE
+ Indicates that window size on the client has been changed. The
+ server updates the window size of the tty and causes SIGWINCH to
+ be sent to the program. The new window size is passed as four
+ integer arguments: row, col, xpixel, ypixel.
+
+ SSH_MSG_PORT_OPEN
+ Indicates that a connection has been made to a port on the
+ client side for which forwarding has been requested. Arguments
+ are client side channel number, host name to connect to, and
+ port to connect to. The server should send back either
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+ SSH_MSG_CHANNEL_OPEN_FAILURE with the same client side channel
+ number.
+
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION
+ This is sent by the client to indicate that it has opened a con-
+ nection as requested in a previous message. The first argument
+ indicates the server side channel number, and the second argu-
+ ment is the channel number that the client has allocated for
+ this connection.
+
+ SSH_MSG_CHANNEL_OPEN_FAILURE
+ This is sent by the client to indicate that it failed to open a
+ connection as requested in a previous message. The server side
+ channel number is passed as an argument. The server will close
+ the descriptor associated with the channel and free the channel.
+
+ SSH_MSG_CHANNEL_DATA
+ This packet contains data for a channel from the client. The
+ first argument is the server side channel number, and the second
+ argument (a string) is the data.
+
+ SSH_MSG_CHANNEL_CLOSE
+ This is sent by the client to indicate that whoever was in the
+ other end of the channel has closed it. The argument is the
+ server channel number. The server will allow buffered data to
+ drain, and when ready, will close the socket, free the channel,
+ and send the client a SSH_MSG_CHANNEL_CLOSE_CONFIRMATION message
+ for the channel.
+
+ SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
+ This is send by the client to indicate that a channel previously
+ closed by the server has now been closed on the client side as
+ well. The argument indicates the server channel number. The
+
+
+
+Ylonen [Page 17]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ server frees the channel.
+
+ Any unsupported messages during interactive mode cause the connection
+ to be terminated with SSH_MSG_DISCONNECT and an error message. Com-
+ patible protocol upgrades should agree about any extensions during
+ the preparation phase or earlier.
+
+
+Termination of the Connection
+
+ Normal termination of the connection is always initiated by the
+ server by sending SSH_SMSG_EXITSTATUS after the program has exited.
+ The client responds to this message by sending
+ SSH_CMSG_EXIT_CONFIRMATION and closes the socket; the server then
+ closes the socket. There are two purposes for the confirmation: some
+ systems may lose previously sent data when the socket is closed, and
+ closing the client side first causes any TCP/IP TIME_WAIT [RFC0793]
+ waits to occur on the client side, not consuming server resources.
+
+ If the program terminates due to a signal, the server will send
+ SSH_MSG_DISCONNECT with an appropriate message. If the connection is
+ closed, all file descriptors to the program will be closed and the
+ server will exit. If the program runs on a tty, the kernel sends it
+ the SIGHUP signal when the pty master side is closed.
+
+Protocol Flags
+
+ Both the server and the client pass 32 bits of protocol flags to the
+ other side. The flags are intended for compatible protocol exten-
+ sion; the server first announces which added capabilities it sup-
+ ports, and the client then sends the capabilities that it supports.
+
+ The following flags are currently defined (the values are bit masks):
+
+ 1 SSH_PROTOFLAG_SCREEN_NUMBER
+ This flag can only be sent by the client. It indicates that the
+ X11 forwarding requests it sends will include the screen number.
+
+ 2 SSH_PROTOFLAG_HOST_IN_FWD_OPEN
+ If both sides specify this flag, SSH_SMSG_X11_OPEN and
+ SSH_MSG_PORT_OPEN messages will contain an additional field con-
+ taining a description of the host at the other end of the con-
+ nection.
+
+Detailed Description of Packet Types and Formats
+
+ The supported packet types and the corresponding message numbers are
+ given in the following table. Messages with _MSG_ in their name may
+
+
+
+Ylonen [Page 18]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ be sent by either side. Messages with _CMSG_ are only sent by the
+ client, and messages with _SMSG_ only by the server.
+
+ A packet may contain additional data after the arguments specified
+ below. Any such data should be ignored by the receiver. However, it
+ is recommended that no such data be stored without good reason.
+ (This helps build compatible extensions.)
+
+ 0 SSH_MSG_NONE
+ This code is reserved. This message type is never sent.
+
+ 1 SSH_MSG_DISCONNECT
+
+ string Cause of disconnection
+
+ This message may be sent by either party at any time. It causes
+ the immediate disconnection of the connection. The message is
+ intended to be displayed to a human, and describes the reason
+ for disconnection.
+
+ 2 SSH_SMSG_PUBLIC_KEY
+
+ 8 bytes anti_spoofing_cookie
+ 32-bit int server_key_bits
+ mp-int server_key_public_exponent
+ mp-int server_key_public_modulus
+ 32-bit int host_key_bits
+ mp-int host_key_public_exponent
+ mp-int host_key_public_modulus
+ 32-bit int protocol_flags
+ 32-bit int supported_ciphers_mask
+ 32-bit int supported_authentications_mask
+
+ Sent as the first message by the server. This message gives the
+ server's host key, server key, protocol flags (intended for com-
+ patible protocol extension), supported_ciphers_mask (which is
+ the bitwise or of (1 << cipher_number), where << is the left
+ shift operator, for all supported ciphers), and
+ supported_authentications_mask (which is the bitwise or of (1 <<
+ authentication_type) for all supported authentication types).
+ The anti_spoofing_cookie is 64 random bytes, and must be sent
+ back verbatim by the client in its reply. It is used to make
+ IP-spoofing more difficult (encryption and host keys are the
+ real defense against spoofing).
+
+ 3 SSH_CMSG_SESSION_KEY
+
+ 1 byte cipher_type (must be one of the supported values)
+
+
+
+Ylonen [Page 19]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ 8 bytes anti_spoofing_cookie (must match data sent by the server)
+ mp-int double-encrypted session key
+ 32-bit int protocol_flags
+
+ Sent by the client as the first message in the session. Selects
+ the cipher to use, and sends the encrypted session key to the
+ server. The anti_spoofing_cookie must be the same bytes that
+ were sent by the server. Protocol_flags is intended for nego-
+ tiating compatible protocol extensions.
+
+ 4 SSH_CMSG_USER
+
+ string user login name on server
+
+ Sent by the client to begin authentication. Specifies the user
+ name on the server to log in as. The server responds with
+ SSH_SMSG_SUCCESS if no authentication is needed for this user,
+ or SSH_SMSG_FAILURE if authentication is needed (or the user
+ does not exist). [Note to the implementator: the user name is
+ of arbitrary size. The implementation must be careful not to
+ overflow internal buffers.]
+
+ 5 SSH_CMSG_AUTH_RHOSTS
+
+ string client-side user name
+
+ Requests authentication using /etc/hosts.equiv and .rhosts (or
+ equivalent mechanisms). This authentication method is normally
+ disabled in the server because it is not secure (but this is the
+ method used by rsh and rlogin). The server responds with
+ SSH_SMSG_SUCCESS if authentication was successful, and
+ SSH_SMSG_FAILURE if access was not granted. The server should
+ check that the client side port number is less than 1024 (a
+ privileged port), and immediately reject authentication if it is
+ not. Supporting this authentication method is optional. This
+ method should normally not be enabled in the server because it
+ is not safe. (However, not enabling this only helps if rlogind
+ and rshd are disabled.)
+
+ 6 SSH_CMSG_AUTH_RSA
+
+ mp-int identity_public_modulus
+
+ Requests authentication using pure RSA authentication. The
+ server checks if the given key is permitted to log in, and if
+ so, responds with SSH_SMSG_AUTH_RSA_CHALLENGE. Otherwise, it
+ responds with SSH_SMSG_FAILURE. The client often tries several
+ different keys in sequence until one supported by the server is
+
+
+
+Ylonen [Page 20]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ found. Authentication is accepted if the client gives the
+ correct response to the challenge. The server is free to add
+ other criteria for authentication, such as a requirement that
+ the connection must come from a certain host. Such additions
+ are not visible at the protocol level. Supporting this authen-
+ tication method is optional but recommended.
+
+ 7 SSH_SMSG_AUTH_RSA_CHALLENGE
+
+ mp-int encrypted challenge
+
+ Presents an RSA authentication challenge to the client. The
+ challenge is a 256-bit random value encrypted as described else-
+ where in this document. The client must decrypt the challenge
+ using the RSA private key, compute MD5 of the challenge plus
+ session id, and send back the resulting 16 bytes using
+ SSH_CMSG_AUTH_RSA_RESPONSE.
+
+ 8 SSH_CMSG_AUTH_RSA_RESPONSE
+
+ 16 bytes MD5 of decrypted challenge
+
+ This message is sent by the client in response to an RSA chal-
+ lenge. The MD5 checksum is returned instead of the decrypted
+ challenge to deter known-plaintext attacks against the RSA key.
+ The server responds to this message with either SSH_SMSG_SUCCESS
+ or SSH_SMSG_FAILURE.
+
+ 9 SSH_CMSG_AUTH_PASSWORD
+
+ string plain text password
+
+ Requests password authentication using the given password. Note
+ that even though the password is plain text inside the packet,
+ the whole packet is normally encrypted by the packet layer. It
+ would not be possible for the client to perform password
+ encryption/hashing, because it cannot know which kind of
+ encryption/hashing, if any, the server uses. The server
+ responds to this message with SSH_SMSG_SUCCESS or
+ SSH_SMSG_FAILURE.
+
+ 10 SSH_CMSG_REQUEST_PTY
+
+ string TERM environment variable value (e.g. vt100)
+ 32-bit int terminal height, rows (e.g., 24)
+ 32-bit int terminal width, columns (e.g., 80)
+ 32-bit int terminal width, pixels (0 if no graphics) (e.g., 480)
+ 32-bit int terminal height, pixels (0 if no graphics) (e.g., 640)
+
+
+
+Ylonen [Page 21]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ n bytes tty modes encoded in binary
+
+ Requests a pseudo-terminal to be allocated for this command.
+ This message can be used regardless of whether the session will
+ later execute the shell or a command. If a pty has been
+ requested with this message, the shell or command will run on a
+ pty. Otherwise it will communicate with the server using pipes,
+ sockets or some other similar mechanism.
+
+ The terminal type gives the type of the user's terminal. In the
+ UNIX environment it is passed to the shell or command in the
+ TERM environment variable.
+
+ The width and height values give the initial size of the user's
+ terminal or window. All values can be zero if not supported by
+ the operating system. The server will pass these values to the
+ kernel if supported.
+
+ Terminal modes are encoded into a byte stream in a portable for-
+ mat. The exact format is described later in this document.
+
+ The server responds to the request with either SSH_SMSG_SUCCESS
+ or SSH_SMSG_FAILURE. If the server does not have the concept of
+ pseudo terminals, it should return success if it is possible to
+ execute a shell or a command so that it looks to the client as
+ if it was running on a pseudo terminal.
+
+ 11 SSH_CMSG_WINDOW_SIZE
+
+ 32-bit int terminal height, rows
+ 32-bit int terminal width, columns
+ 32-bit int terminal width, pixels
+ 32-bit int terminal height, pixels
+
+ This message can only be sent by the client during the interac-
+ tive session. This indicates that the size of the user's window
+ has changed, and provides the new size. The server will update
+ the kernel's notion of the window size, and a SIGWINCH signal or
+ equivalent will be sent to the shell or command (if supported by
+ the operating system).
+
+ 12 SSH_CMSG_EXEC_SHELL
+
+ (no arguments)
+
+ Starts a shell (command interpreter), and enters interactive
+ session mode.
+
+
+
+
+Ylonen [Page 22]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ 13 SSH_CMSG_EXEC_CMD
+
+ string command to execute
+
+ Starts executing the given command, and enters interactive ses-
+ sion mode. On UNIX, the command is run as "<shell> -c <com-
+ mand>", where <shell> is the user's login shell.
+
+ 14 SSH_SMSG_SUCCESS
+
+ (no arguments)
+
+ This message is sent by the server in response to the session
+ key, a successful authentication request, and a successfully
+ completed preparatory operation.
+
+ 15 SSH_SMSG_FAILURE
+
+ (no arguments)
+
+ This message is sent by the server in response to a failed
+ authentication operation to indicate that the user has not yet
+ been successfully authenticated, and in response to a failed
+ preparatory operation. This is also sent in response to an
+ authentication or preparatory operation request that is not
+ recognized or supported.
+
+ 16 SSH_CMSG_STDIN_DATA
+
+ string data
+
+ Delivers data from the client to be supplied as input to the
+ shell or program running on the server side. This message can
+ only be used in the interactive session mode. No acknowledge-
+ ment is sent for this message.
+
+ 17 SSH_SMSG_STDOUT_DATA
+
+ string data
+
+ Delivers data from the server that was read from the standard
+ output of the shell or program running on the server side. This
+ message can only be used in the interactive session mode. No
+ acknowledgement is sent for this message.
+
+ 18 SSH_SMSG_STDERR_DATA
+
+ string data
+
+
+
+Ylonen [Page 23]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ Delivers data from the server that was read from the standard
+ error of the shell or program running on the server side. This
+ message can only be used in the interactive session mode. No
+ acknowledgement is sent for this message.
+
+ 19 SSH_CMSG_EOF
+
+ (no arguments)
+
+ This message is sent by the client to indicate that EOF has been
+ reached on the input. Upon receiving this message, and after
+ all buffered input data has been sent to the shell or program,
+ the server will close the input file descriptor to the program.
+ This message can only be used in the interactive session mode.
+ No acknowledgement is sent for this message.
+
+ 20 SSH_SMSG_EXITSTATUS
+
+ 32-bit int exit status of the command
+
+ Returns the exit status of the shell or program after it has
+ exited. The client should respond with
+ SSH_CMSG_EXIT_CONFIRMATION when it has received this message.
+ This will be the last message sent by the server. If the pro-
+ gram being executed dies with a signal instead of exiting nor-
+ mally, the server should terminate the session with
+ SSH_MSG_DISCONNECT (which can be used to pass a human-readable
+ string indicating that the program died due to a signal) instead
+ of using this message.
+
+ 21 SSH_MSG_CHANNEL_OPEN_CONFIRMATION
+
+ 32-bit int remote_channel
+ 32-bit int local_channel
+
+ This is sent in response to any channel open request if the
+ channel has been successfully opened. Remote_channel is the
+ channel number received in the initial open request;
+ local_channel is the channel number the side sending this mes-
+ sage has allocated for the channel. Data can be transmitted on
+ the channel after this message.
+
+ 22 SSH_MSG_CHANNEL_OPEN_FAILURE
+
+ 32-bit int remote_channel
+
+ This message indicates that an earlier channel open request by
+ the other side has failed or has been denied. Remote_channel is
+
+
+
+Ylonen [Page 24]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ the channel number given in the original request.
+
+ 23 SSH_MSG_CHANNEL_DATA
+
+ 32-bit int remote_channel
+ string data
+
+ Data is transmitted in a channel in these messages. A channel
+ is bidirectional, and both sides can send these messages. There
+ is no acknowledgement for these messages. It is possible that
+ either side receives these messages after it has sent
+ SSH_MSG_CHANNEL_CLOSE for the channel. These messages cannot be
+ received after the party has sent or received
+ SSH_MSG_CHANNEL_CLOSE_CONFIRMATION.
+
+ 24 SSH_MSG_CHANNEL_CLOSE
+
+ 32-bit int remote_channel
+
+ When a channel is closed at one end of the connection, that side
+ sends this message. Upon receiving this message, the channel
+ should be closed. When this message is received, if the channel
+ is already closed (the receiving side has sent this message for
+ the same channel earlier), the channel is freed and no further
+ action is taken; otherwise the channel is freed and
+ SSH_MSG_CHANNEL_CLOSE_CONFIRMATION is sent in response. (It is
+ possible that the channel is closed simultaneously at both
+ ends.)
+
+ 25 SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
+
+ 32-bit int remote_channel
+
+ This message is sent in response to SSH_MSG_CHANNEL_CLOSE unless
+ the channel was already closed. When this message is sent or
+ received, the channel is freed.
+
+ 26 (OBSOLETED; was unix-domain X11 forwarding)
+
+ 27 SSH_SMSG_X11_OPEN
+
+ 32-bit int local_channel
+ string originator_string (see below)
+
+ This message can be sent by the server during the interactive
+ session mode to indicate that a client has connected the fake X
+ server. Local_channel is the channel number that the server has
+ allocated for the connection. The client should try to open a
+
+
+
+Ylonen [Page 25]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ connection to the real X server, and respond with
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+ SSH_MSG_CHANNEL_OPEN_FAILURE.
+
+ The field originator_string is present if both sides specified
+ SSH_PROTOFLAG_HOST_IN_FWD_OPEN in the protocol flags. It con-
+ tains a description of the host originating the connection.
+
+ 28 SSH_CMSG_PORT_FORWARD_REQUEST
+
+ 32-bit int server_port
+ string host_to_connect
+ 32-bit int port_to_connect
+
+ Sent by the client in the preparatory phase, this message
+ requests that server_port on the server machine be forwarded
+ over the secure channel to the client machine, and from there to
+ the specified host and port. The server should start listening
+ on the port, and send SSH_MSG_PORT_OPEN whenever a connection is
+ made to it. Supporting this message is optional, and the server
+ is free to reject any forward request. For example, it is
+ highly recommended that unless the user has been authenticated
+ as root, forwarding any privileged port numbers (below 1024) is
+ denied.
+
+ 29 SSH_MSG_PORT_OPEN
+
+ 32-bit int local_channel
+ string host_name
+ 32-bit int port
+ string originator_string (see below)
+
+ Sent by either party in interactive session mode, this message
+ indicates that a connection has been opened to a forwarded
+ TCP/IP port. Local_channel is the channel number that the send-
+ ing party has allocated for the connection. Host_name is the
+ host the connection should be be forwarded to, and the port is
+ the port on that host to connect. The receiving party should
+ open the connection, and respond with
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+ SSH_MSG_CHANNEL_OPEN_FAILURE. It is recommended that the
+ receiving side check the host_name and port for validity to
+ avoid compromising local security by compromised remote side
+ software. Particularly, it is recommended that the client per-
+ mit connections only to those ports for which it has requested
+ forwarding with SSH_CMSG_PORT_FORWARD_REQUEST.
+
+ The field originator_string is present if both sides specified
+
+
+
+Ylonen [Page 26]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ SSH_PROTOFLAG_HOST_IN_FWD_OPEN in the protocol flags. It con-
+ tains a description of the host originating the connection.
+
+ 30 SSH_CMSG_AGENT_REQUEST_FORWARDING
+
+ (no arguments)
+
+ Requests that the connection to the authentication agent be for-
+ warded over the secure channel. The method used by clients to
+ contact the authentication agent within each machine is imple-
+ mentation and machine dependent. If the server accepts this
+ request, it should arrange that any clients run from this ses-
+ sion will actually contact the server program when they try to
+ contact the authentication agent. The server should then send a
+ SSH_SMSG_AGENT_OPEN to open a channel to the agent, and the
+ client should forward the connection to the real authentication
+ agent. Supporting this message is optional.
+
+ 31 SSH_SMSG_AGENT_OPEN
+
+ 32-bit int local_channel
+
+ Sent by the server in interactive session mode, this message
+ requests opening a channel to the authentication agent. The
+ client should open a channel, and respond with either
+ SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+ SSH_MSG_CHANNEL_OPEN_FAILURE.
+
+ 32 SSH_MSG_IGNORE
+
+ string data
+
+ Either party may send this message at any time. This message,
+ and the argument string, is silently ignored. This message
+ might be used in some implementations to make traffic analysis
+ more difficult. This message is not currently sent by the
+ implementation, but all implementations are required to recog-
+ nize and ignore it.
+
+ 33 SSH_CMSG_EXIT_CONFIRMATION
+
+ (no arguments)
+
+ Sent by the client in response to SSH_SMSG_EXITSTATUS. This is
+ the last message sent by the client.
+
+ 34 SSH_CMSG_X11_REQUEST_FORWARDING
+
+
+
+
+Ylonen [Page 27]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ string x11_authentication_protocol
+ string x11_authentication_data
+ 32-bit int screen number (if SSH_PROTOFLAG_SCREEN_NUMBER)
+
+ Sent by the client during the preparatory phase, this message
+ requests that the server create a fake X11 display and set the
+ DISPLAY environment variable accordingly. An internet-domain
+ display is preferable. The given authentication protocol and
+ the associated data should be recorded by the server so that it
+ is used as authentication on connections (e.g., in .Xauthority).
+ The authentication protocol must be one of the supported X11
+ authentication protocols, e.g., "MIT-MAGIC-COOKIE-1". Authenti-
+ cation data must be a lowercase hex string of even length. Its
+ interpretation is protocol dependent. The data is in a format
+ that can be used with e.g. the xauth program. Supporting this
+ message is optional.
+
+ The client is permitted (and recommended) to generate fake
+ authentication information and send fake information to the
+ server. This way, a corrupt server will not have access to the
+ user's terminal after the connection has terminated. The
+ correct authorization codes will also not be left hanging around
+ in files on the server (many users keep the same X session for
+ months, thus protecting the authorization data becomes impor-
+ tant).
+
+ X11 authentication spoofing works by initially sending fake
+ (random) authentication data to the server, and interpreting the
+ first packet sent by the X11 client after the connection has
+ been opened. The first packet contains the client's authentica-
+ tion. If the packet contains the correct fake data, it is
+ replaced by the client by the correct authentication data, and
+ then sent to the X server.
+
+ 35 SSH_CMSG_AUTH_RHOSTS_RSA
+
+ string clint-side user name
+ 32-bit int client_host_key_bits
+ mp-int client_host_key_public_exponent
+ mp-int client_host_key_public_modulus
+
+ Requests authentication using /etc/hosts.equiv and .rhosts (or
+ equivalent) together with RSA host authentication. The server
+ should check that the client side port number is less than 1024
+ (a privileged port), and immediately reject authentication if it
+ is not. The server responds with SSH_SMSG_FAILURE or
+ SSH_SMSG_AUTH_RSA_CHALLENGE. The client must respond to the
+ challenge with the proper SSH_CMSG_AUTH_RSA_RESPONSE. The
+
+
+
+Ylonen [Page 28]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ server then responds with success if access was granted, or
+ failure if the client gave a wrong response. Supporting this
+ authentication method is optional but recommended in most
+ environments.
+
+ 36 SSH_MSG_DEBUG
+
+ string debugging message sent to the other side
+
+ This message may be sent by either party at any time. It is
+ used to send debugging messages that may be informative to the
+ user in solving various problems. For example, if authentica-
+ tion fails because of some configuration error (e.g., incorrect
+ permissions for some file), it can be very helpful for the user
+ to make the cause of failure available. On the other hand, one
+ should not make too much information available for security rea-
+ sons. It is recommended that the client provides an option to
+ display the debugging information sent by the sender (the user
+ probably does not want to see it by default). The server can
+ log debugging data sent by the client (if any). Either party is
+ free to ignore any received debugging data. Every implementa-
+ tion must be able to receive this message, but no implementation
+ is required to send these.
+
+ 37 SSH_CMSG_REQUEST_COMPRESSION
+
+ 32-bit int gzip compression level (1-9)
+
+ This message can be sent by the client in the preparatory opera-
+ tions phase. The server responds with SSH_SMSG_FAILURE if it
+ does not support compression or does not want to compress; it
+ responds with SSH_SMSG_SUCCESS if it accepted the compression
+ request. In the latter case the response to this packet will
+ still be uncompressed, but all further packets in either direc-
+ tion will be compressed by gzip.
+
+
+Encoding of Terminal Modes
+
+ Terminal modes (as passed in SSH_CMSG_REQUEST_PTY) are encoded into a
+ byte stream. It is intended that the coding be portable across dif-
+ ferent environments.
+
+ The tty mode description is a stream of bytes. The stream consists
+ of opcode-argument pairs. It is terminated by opcode TTY_OP_END (0).
+ Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have 32-bit
+ integer arguments (stored msb first). Opcodes 160-255 are not yet
+ defined, and cause parsing to stop (they should only be used after
+
+
+
+Ylonen [Page 29]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ any other data).
+
+ The client puts in the stream any modes it knows about, and the
+ server ignores any modes it does not know about. This allows some
+ degree of machine-independence, at least between systems that use a
+ POSIX-like [POSIX] tty interface. The protocol can support other
+ systems as well, but the client may need to fill reasonable values
+ for a number of parameters so the server pty gets set to a reasonable
+ mode (the server leaves all unspecified mode bits in their default
+ values, and only some combinations make sense).
+
+ The following opcodes have been defined. The naming of opcodes
+ mostly follows the POSIX terminal mode flags.
+
+ 0 TTY_OP_END
+ Indicates end of options.
+
+ 1 VINTR
+ Interrupt character; 255 if none. Similarly for the other char-
+ acters. Not all of these characters are supported on all sys-
+ tems.
+
+ 2 VQUIT
+ The quit character (sends SIGQUIT signal on UNIX systems).
+
+ 3 VERASE
+ Erase the character to left of the cursor.
+
+ 4 VKILL
+ Kill the current input line.
+
+ 5 VEOF
+ End-of-file character (sends EOF from the terminal).
+
+ 6 VEOL
+ End-of-line character in addition to carriage return and/or
+ linefeed.
+
+ 7 VEOL2
+ Additional end-of-line character.
+
+ 8 VSTART
+ Continues paused output (normally ^Q).
+
+ 9 VSTOP
+ Pauses output (^S).
+
+ 10 VSUSP
+
+
+
+Ylonen [Page 30]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ Suspends the current program.
+
+ 11 VDSUSP
+ Another suspend character.
+
+ 12 VREPRINT
+ Reprints the current input line.
+
+ 13 VWERASE
+ Erases a word left of cursor.
+
+ 14 VLNEXT
+ More special input characters; these are probably not supported
+ on most systems.
+
+ 15 VFLUSH
+
+ 16 VSWTCH
+
+ 17 VSTATUS
+
+ 18 VDISCARD
+
+
+ 30 IGNPAR
+ The ignore parity flag. The next byte should be 0 if this flag
+ is not set, and 1 if it is set.
+
+ 31 PARMRK
+ More flags. The exact definitions can be found in the POSIX
+ standard.
+
+ 32 INPCK
+
+ 33 ISTRIP
+
+ 34 INLCR
+
+ 35 IGNCR
+
+ 36 ICRNL
+
+ 37 IUCLC
+
+ 38 IXON
+
+ 39 IXANY
+
+
+
+
+Ylonen [Page 31]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ 40 IXOFF
+
+ 41 IMAXBEL
+
+
+ 50 ISIG
+
+ 51 ICANON
+
+ 52 XCASE
+
+ 53 ECHO
+
+ 54 ECHOE
+
+ 55 ECHOK
+
+ 56 ECHONL
+
+ 57 NOFLSH
+
+ 58 TOSTOP
+
+ 59 IEXTEN
+
+ 60 ECHOCTL
+
+ 61 ECHOKE
+
+ 62 PENDIN
+
+
+ 70 OPOST
+
+ 71 OLCUC
+
+ 72 ONLCR
+
+ 73 OCRNL
+
+ 74 ONOCR
+
+ 75 ONLRET
+
+
+ 90 CS7
+
+ 91 CS8
+
+
+
+Ylonen [Page 32]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ 92 PARENB
+
+ 93 PARODD
+
+
+ 192 TTY_OP_ISPEED
+ Specifies the input baud rate in bits per second.
+
+ 193 TTY_OP_OSPEED
+ Specifies the output baud rate in bits per second.
+
+
+The Authentication Agent Protocol
+
+ The authentication agent is a program that can be used to hold RSA
+ authentication keys for the user (in future, it might hold data for
+ other authentication types as well). An authorized program can send
+ requests to the agent to generate a proper response to an RSA chal-
+ lenge. How the connection is made to the agent (or its representa-
+ tive) inside a host and how access control is done inside a host is
+ implementation-dependent; however, how it is forwarded and how one
+ interacts with it is specified in this protocol. The connection to
+ the agent is normally automatically forwarded over the secure chan-
+ nel.
+
+ A program that wishes to use the agent first opens a connection to
+ its local representative (typically, the agent itself or an SSH
+ server). It then writes a request to the connection, and waits for
+ response. It is recommended that at least five minutes of timeout
+ are provided waiting for the agent to respond to an authentication
+ challenge (this gives sufficient time for the user to cut-and-paste
+ the challenge to a separate machine, perform the computation there,
+ and cut-and-paste the result back if so desired).
+
+ Messages sent to and by the agent are in the following format:
+
+ 4 bytes Length, msb first. Does not include length itself.
+ 1 byte Packet type. The value 255 is reserved for future extensions.
+ data Any data, depending on packet type. Encoding as in the ssh packet
+ protocol.
+
+
+ The following message types are currently defined:
+
+ 1 SSH_AGENTC_REQUEST_RSA_IDENTITIES
+
+ (no arguments)
+
+
+
+
+Ylonen [Page 33]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ Requests the agent to send a list of all RSA keys for which it
+ can answer a challenge.
+
+ 2 SSH_AGENT_RSA_IDENTITIES_ANSWER
+
+ 32-bit int howmany
+ howmany times:
+ 32-bit int bits
+ mp-int public exponent
+ mp-int public modulus
+ string comment
+
+ The agent sends this message in response to the to
+ SSH_AGENTC_REQUEST_RSA_IDENTITIES. The answer lists all RSA
+ keys for which the agent can answer a challenge. The comment
+ field is intended to help identify each key; it may be printed
+ by an application to indicate which key is being used. If the
+ agent is not holding any keys, howmany will be zero.
+
+ 3 SSH_AGENTC_RSA_CHALLENGE
+
+ 32-bit int bits
+ mp-int public exponent
+ mp-int public modulus
+ mp-int challenge
+ 16 bytes session_id
+ 32-bit int response_type
+
+ Requests RSA decryption of random challenge to authenticate the
+ other side. The challenge will be decrypted with the RSA
+ private key corresponding to the given public key.
+
+ The decrypted challenge must contain a zero in the highest (par-
+ tial) byte, 2 in the next byte, followed by non-zero random
+ bytes, a zero byte, and then the real challenge value in the
+ lowermost bytes. The real challenge must be 32 8-bit bytes (256
+ bits).
+
+ Response_type indicates the format of the response to be
+ returned. Currently the only supported value is 1, which means
+ to compute MD5 of the real challenge plus session id, and return
+ the resulting 16 bytes in a SSH_AGENT_RSA_RESPONSE message.
+
+ 4 SSH_AGENT_RSA_RESPONSE
+
+ 16 bytes MD5 of decrypted challenge
+
+ Answers an RSA authentication challenge. The response is 16
+
+
+
+Ylonen [Page 34]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ bytes: the MD5 checksum of the 32-byte challenge.
+
+ 5 SSH_AGENT_FAILURE
+
+ (no arguments)
+
+ This message is sent whenever the agent fails to answer a
+ request properly. For example, if the agent cannot answer a
+ challenge (e.g., no longer has the proper key), it can respond
+ with this. The agent also responds with this message if it
+ receives a message it does not recognize.
+
+ 6 SSH_AGENT_SUCCESS
+
+ (no arguments)
+
+ This message is sent by the agent as a response to certain
+ requests that do not otherwise cause a message be sent.
+ Currently, this is only sent in response to
+ SSH_AGENTC_ADD_RSA_IDENTITY and SSH_AGENTC_REMOVE_RSA_IDENTITY.
+
+ 7 SSH_AGENTC_ADD_RSA_IDENTITY
+
+ 32-bit int bits
+ mp-int public modulus
+ mp-int public exponent
+ mp-int private exponent
+ mp-int multiplicative inverse of p mod q
+ mp-int p
+ mp-int q
+ string comment
+
+ Registers an RSA key with the agent. After this request, the
+ agent can use this RSA key to answer requests. The agent
+ responds with SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE.
+
+ 8 SSH_AGENT_REMOVE_RSA_IDENTITY
+
+ 32-bit int bits
+ mp-int public exponent
+ mp-int public modulus
+
+ Removes an RSA key from the agent. The agent will no longer
+ accept challenges for this key and will not list it as a sup-
+ ported identity. The agent responds with SSH_AGENT_SUCCESS or
+ SSH_AGENT_FAILURE.
+
+ If the agent receives a message that it does not understand, it
+
+
+
+Ylonen [Page 35]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ responds with SSH_AGENT_FAILURE. This permits compatible future
+ extensions.
+
+ It is possible that several clients have a connection open to the
+ authentication agent simultaneously. Each client will use a separate
+ connection (thus, any SSH connection can have multiple agent connec-
+ tions active simultaneously).
+
+
+References
+
+
+ [DES] FIPS PUB 46-1: Data Encryption Standard. National Bureau of
+ Standards, January 1988. FIPS PUB 81: DES Modes of Operation.
+ National Bureau of Standards, December 1980. Bruce Schneier:
+ Applied Cryptography. John Wiley & Sons, 1994. J. Seberry and
+ J. Pieprzyk: Cryptography: An Introduction to Computer Secu-
+ rity. Prentice-Hall, 1989.
+
+ [GZIP]
+ The GNU GZIP program; available for anonymous ftp at
+ prep.ai.mit.edu. Please let me know if you know a paper
+ describing the algorithm.
+
+ [IDEA]
+ Xuejia Lai: On the Design and Security of Block Ciphers, ETH
+ Series in Information Processing, vol. 1, Hartung-Gorre Verlag,
+ Konstanz, Switzerland, 1992. Bruce Schneier: Applied Cryptogra-
+ phy, John Wiley & Sons, 1994. See also the following patents:
+ PCT/CH91/00117, EP 0 482 154 B1, US Pat. 5,214,703.
+
+ [PKCS#1]
+ PKCS #1: RSA Encryption Standard. Version 1.5, RSA Labora-
+ tories, November 1993. Available for anonymous ftp at
+ ftp.rsa.com.
+
+ [POSIX]
+ Portable Operating System Interface (POSIX) - Part 1: Applica-
+ tion Program Interface (API) [C language], ISO/IEC 9945-1, IEEE
+ Std 1003.1, 1990.
+
+ [RFC0791]
+ J. Postel: Internet Protocol, RFC 791, USC/ISI, September 1981.
+
+ [RFC0793]
+ J. Postel: Transmission Control Protocol, RFC 793, USC/ISI, Sep-
+ tember 1981.
+
+
+
+
+Ylonen [Page 36]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ [RFC1034]
+ P. Mockapetris: Domain Names - Concepts and Facilities, RFC
+ 1034, USC/ISI, November 1987.
+
+ [RFC1282]
+ B. Kantor: BSD Rlogin, RFC 1258, UCSD, December 1991.
+
+ [RSA] Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
+ See also R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic
+ Communications System and Method. US Patent 4,405,829, 1983.
+
+ [X11] R. Scheifler: X Window System Protocol, X Consortium Standard,
+ Version 11, Release 6. Massachusetts Institute of Technology,
+ Laboratory of Computer Science, 1994.
+
+
+Security Considerations
+
+ This protocol deals with the very issue of user authentication and
+ security.
+
+ First of all, as an implementation issue, the server program will
+ have to run as root (or equivalent) on the server machine. This is
+ because the server program will need be able to change to an arbi-
+ trary user id. The server must also be able to create a privileged
+ TCP/IP port.
+
+ The client program will need to run as root if any variant of .rhosts
+ authentication is to be used. This is because the client program
+ will need to create a privileged port. The client host key is also
+ usually stored in a file which is readable by root only. The client
+ needs the host key in .rhosts authentication only. Root privileges
+ can be dropped as soon as the privileged port has been created and
+ the host key has been read.
+
+ The SSH protocol offers major security advantages over existing tel-
+ net and rlogin protocols.
+
+ o IP spoofing is restricted to closing a connection (by encryp-
+ tion, host keys, and the special random cookie). If encryption
+ is not used, IP spoofing is possible for those who can hear
+ packets going out from the server.
+
+ o DNS spoofing is made ineffective (by host keys).
+
+ o Routing spoofing is made ineffective (by host keys).
+
+ o All data is encrypted with strong algorithms to make
+
+
+
+Ylonen [Page 37]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ eavesdropping as difficult as possible. This includes encrypt-
+ ing any authentication information such as passwords. The
+ information for decrypting session keys is destroyed every hour.
+
+ o Strong authentication methods: .rhosts combined with RSA host
+ authentication, and pure RSA authentication.
+
+ o X11 connections and arbitrary TCP/IP ports can be forwarded
+ securely.
+
+ o Man-in-the-middle attacks are deterred by using the server host
+ key to encrypt the session key.
+
+ o Trojan horses to catch a password by routing manipulation are
+ deterred by checking that the host key of the server machine
+ matches that stored on the client host.
+
+ The security of SSH against man-in-the-middle attacks and the secu-
+ rity of the new form of .rhosts authentication, as well as server
+ host validation, depends on the integrity of the host key and the
+ files containing known host keys.
+
+ The host key is normally stored in a root-readable file. If the host
+ key is compromised, it permits attackers to use IP, DNS and routing
+ spoofing as with current rlogin and rsh. It should never be any
+ worse than the current situation.
+
+ The files containing known host keys are not sensitive. However, if
+ an attacker gets to modify the known host key files, it has the same
+ consequences as a compromised host key, because the attacker can then
+ change the recorded host key.
+
+ The security improvements obtained by this protocol for X11 are of
+ particular significance. Previously, there has been no way to pro-
+ tect data communicated between an X server and a client running on a
+ remote machine. By creating a fake display on the server, and for-
+ warding all X11 requests over the secure channel, SSH can be used to
+ run any X11 applications securely without any cooperation with the
+ vendors of the X server or the application.
+
+ Finally, the security of this program relies on the strength of the
+ underlying cryptographic algorithms. The RSA algorithm is used for
+ authentication key exchange. It is widely believed to be secure. Of
+ the algorithms used to encrypt the session, DES has a rather small
+ key these days, probably permitting governments and organized crimi-
+ nals to break it in very short time with specialized hardware. 3DES
+ is probably safe (but slower). IDEA is widely believed to be secure.
+ People have varying degrees of confidence in the other algorithms.
+
+
+
+Ylonen [Page 38]
+
+Internet-Draft SSH (Secure Shell) Remote Login Protocol 15 Nov 1995
+
+
+ This program is not secure if used with no encryption at all.
+
+
+Additional Information
+
+ Additional information (especially on the implementation and mailing
+ lists) is available via WWW at http://www.cs.hut.fi/ssh.
+
+ Comments should be sent to Tatu Ylonen <ylo@cs.hut.fi> or the SSH
+ Mailing List <ssh@clinet.fi>.
+
+Author's Address
+
+
+ Tatu Ylonen
+ Helsinki University of Technology
+ Otakaari 1
+ FIN-02150 Espoo, Finland
+
+ Phone: +358-0-451-3374
+ Fax: +358-0-451-3293
+ EMail: ylo@cs.hut.fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ylonen [Page 39]
+
diff --git a/usr.bin/ssh/RFC.nroff b/usr.bin/ssh/RFC.nroff
new file mode 100644
index 00000000000..dccc954c78b
--- /dev/null
+++ b/usr.bin/ssh/RFC.nroff
@@ -0,0 +1,1780 @@
+.\" -*- nroff -*-
+.\"
+.\" $Id: RFC.nroff,v 1.1 1999/09/26 20:53:32 deraadt Exp $
+.\"
+.pl 10.0i
+.po 0
+.ll 7.2i
+.lt 7.2i
+.nr LL 7.2i
+.nr LT 7.2i
+.ds LF Ylonen
+.ds RF FORMFEED[Page %]
+.ds CF
+.ds LH Internet-Draft
+.ds RH 15 November 1995
+.ds CH SSH (Secure Shell) Remote Login Protocol
+.na
+.hy 0
+.in 0
+Network Working Group T. Ylonen
+Internet-Draft Helsinki University of Technology
+draft-ylonen-ssh-protocol-00.txt 15 November 1995
+Expires: 15 May 1996
+
+.in 3
+
+.ce
+The SSH (Secure Shell) Remote Login Protocol
+
+.ti 0
+Status of This Memo
+
+This document is an Internet-Draft. Internet-Drafts are working
+documents of the Internet Engineering Task Force (IETF), its areas,
+and its working groups. Note that other groups may also distribute
+working documents as Internet-Drafts.
+
+Internet-Drafts are draft documents valid for a maximum of six
+months and may be updated, replaced, or obsoleted by other docu-
+ments at any time. It is inappropriate to use Internet-Drafts as
+reference material or to cite them other than as ``work in pro-
+gress.''
+
+To learn the current status of any Internet-Draft, please check the
+``1id-abstracts.txt'' listing contained in the Internet- Drafts Shadow
+Directories on ftp.is.co.za (Africa), nic.nordu.net (Europe),
+munnari.oz.au (Pacific Rim), ds.internic.net (US East Coast), or
+ftp.isi.edu (US West Coast).
+
+The distribution of this memo is unlimited.
+
+.ti 0
+Introduction
+
+SSH (Secure Shell) is a program to log into another computer over a
+network, to execute commands in a remote machine, and to move files
+from one machine to another. It provides strong authentication and
+secure communications over insecure networks. Its features include
+the following:
+.IP o
+Closes several security holes (e.g., IP, routing, and DNS spoofing).
+New authentication methods: .rhosts together with RSA [RSA] based host
+authentication, and pure RSA authentication.
+.IP o
+All communications are automatically and transparently encrypted.
+Encryption is also used to protect integrity.
+.IP o
+X11 connection forwarding provides secure X11 sessions.
+.IP o
+Arbitrary TCP/IP ports can be redirected over the encrypted channel
+in both directions.
+.IP o
+Client RSA-authenticates the server machine in the beginning of every
+connection to prevent trojan horses (by routing or DNS spoofing) and
+man-in-the-middle attacks, and the server RSA-authenticates the client
+machine before accepting .rhosts or /etc/hosts.equiv authentication
+(to prevent DNS, routing, or IP spoofing).
+.IP o
+An authentication agent, running in the user's local workstation or
+laptop, can be used to hold the user's RSA authentication keys.
+.RT
+
+The goal has been to make the software as easy to use as possible for
+ordinary users. The protocol has been designed to be as secure as
+possible while making it possible to create implementations that
+are easy to use and install. The sample implementation has a number
+of convenient features that are not described in this document as they
+are not relevant for the protocol.
+
+
+.ti 0
+Overview of the Protocol
+
+The software consists of a server program running on a server machine,
+and a client program running on a client machine (plus a few auxiliary
+programs). The machines are connected by an insecure IP [RFC0791]
+network (that can be monitored, tampered with, and spoofed by hostile
+parties).
+
+A connection is always initiated by the client side. The server
+listens on a specific port waiting for connections. Many clients may
+connect to the same server machine.
+
+The client and the server are connected via a TCP/IP [RFC0793] socket
+that is used for bidirectional communication. Other types of
+transport can be used but are currently not defined.
+
+When the client connects the server, the server accepts the connection
+and responds by sending back its version identification string. The
+client parses the server's identification, and sends its own
+identification. The purpose of the identification strings is to
+validate that the connection was to the correct port, declare the
+protocol version number used, and to declare the software version used
+on each side (for debugging purposes). The identification strings are
+human-readable. If either side fails to understand or support the
+other side's version, it closes the connection.
+
+After the protocol identification phase, both sides switch to a packet
+based binary protocol. The server starts by sending its host key
+(every host has an RSA key used to authenticate the host), server key
+(an RSA key regenerated every hour), and other information to the
+client. The client then generates a 256 bit session key, encrypts it
+using both RSA keys (see below for details), and sends the encrypted
+session key and selected cipher type to the server. Both sides then
+turn on encryption using the selected algorithm and key. The server
+sends an encrypted confirmation message to the client.
+
+The client then authenticates itself using any of a number of
+authentication methods. The currently supported authentication
+methods are .rhosts or /etc/hosts.equiv authentication (disabled by
+default), the same with RSA-based host authentication, RSA
+authentication, and password authentication.
+
+After successful authentication, the client makes a number of requests
+to prepare for the session. Typical requests include allocating a
+pseudo tty, starting X11 [X11] or TCP/IP port forwarding, starting
+authentication agent forwarding, and executing the shell or a command.
+
+When a shell or command is executed, the connection enters interactive
+session mode. In this mode, data is passed in both directions,
+new forwarded connections may be opened, etc. The interactive session
+normally terminates when the server sends the exit status of the
+program to the client.
+
+
+The protocol makes several reservations for future extensibility.
+First of all, the initial protocol identification messages include the
+protocol version number. Second, the first packet by both sides
+includes a protocol flags field, which can be used to agree on
+extensions in a compatible manner. Third, the authentication and
+session preparation phases work so that the client sends requests to
+the server, and the server responds with success or failure. If the
+client sends a request that the server does not support, the server
+simply returns failure for it. This permits compatible addition of
+new authentication methods and preparation operations. The
+interactive session phase, on the other hand, works asynchronously and
+does not permit the use of any extensions (because there is no easy
+and reliable way to signal rejection to the other side and problems
+would be hard to debug). Any compatible extensions to this phase must
+be agreed upon during any of the earlier phases.
+
+.ti 0
+The Binary Packet Protocol
+
+After the protocol identification strings, both sides only send
+specially formatted packets. The packet layout is as follows:
+.IP o
+Packet length: 32 bit unsigned integer, coded as four 8-bit bytes, msb
+first. Gives the length of the packet, not including the length field
+and padding. The maximum length of a packet (not including the length
+field and padding) is 262144 bytes.
+.IP o
+Padding: 1-8 bytes of random data (or zeroes if not encrypting). The
+amount of padding is (8 - (length % 8)) bytes (where % stands for the
+modulo operator). The rationale for always having some random padding
+at the beginning of each packet is to make known plaintext attacks
+more difficult.
+.IP o
+Packet type: 8-bit unsigned byte. The value 255 is reserved for
+future extension.
+.IP o
+Data: binary data bytes, depending on the packet type. The number of
+data bytes is the "length" field minus 5.
+.IP o
+Check bytes: 32-bit crc, four 8-bit bytes, msb first. The crc is the
+Cyclic Redundancy Check, with the polynomial 0xedb88320, of the
+Padding, Packet type, and Data fields. The crc is computed before
+any encryption.
+.RT
+
+The packet, except for the length field, may be encrypted using any of
+a number of algorithms. The length of the encrypted part (Padding +
+Type + Data + Check) is always a multiple of 8 bytes. Typically the
+cipher is used in a chained mode, with all packets chained together as
+if it was a single data stream (the length field is never included in
+the encryption process). Details of encryption are described below.
+
+When the session starts, encryption is turned off. Encryption is
+enabled after the client has sent the session key. The encryption
+algorithm to use is selected by the client.
+
+
+.ti 0
+Packet Compression
+
+If compression is supported (it is an optional feature, see
+SSH_CMSG_REQUEST_COMPRESSION below), the packet type and data fields
+of the packet are compressed using the gzip deflate algorithm [GZIP].
+If compression is in effect, the packet length field indicates the
+length of the compressed data, plus 4 for the crc. The amount of
+padding is computed from the compressed data, so that the amount of
+data to be encrypted becomes a multiple of 8 bytes.
+
+When compressing, the packets (type + data portions) in each direction
+are compressed as if they formed a continuous data stream, with only the
+current compression block flushed between packets. This corresponds
+to the GNU ZLIB library Z_PARTIAL_FLUSH option. The compression
+dictionary is not flushed between packets. The two directions are
+compressed independently of each other.
+
+
+.ti 0
+Packet Encryption
+
+The protocol supports several encryption methods. During session
+initialization, the server sends a bitmask of all encryption methods
+that it supports, and the client selects one of these methods. The
+client also generates a 256-bit random session key (32 8-bit bytes) and
+sends it to the server.
+
+The encryption methods supported by the current implementation, and
+their codes are:
+.TS
+center;
+l r l.
+SSH_CIPHER_NONE 0 No encryption
+SSH_CIPHER_IDEA 1 IDEA in CFB mode
+SSH_CIPHER_DES 2 DES in CBC mode
+SSH_CIPHER_3DES 3 Triple-DES in CBC mode
+SSH_CIPHER_TSS 4 An experimental stream cipher
+SSH_CIPHER_RC4 5 RC4
+.TE
+
+All implementations are required to support SSH_CIPHER_DES and
+SSH_CIPHER_3DES. Supporting SSH_CIPHER_IDEA, SSH_CIPHER_RC4, and
+SSH_CIPHER_NONE is recommended. Support for SSH_CIPHER_TSS is
+optional (and it is not described in this document). Other ciphers
+may be added at a later time; support for them is optional.
+
+For encryption, the encrypted portion of the packet is considered a
+linear byte stream. The length of the stream is always a multiple of
+8. The encrypted portions of consecutive packets (in the same
+direction) are encrypted as if they were a continuous buffer (that is,
+any initialization vectors are passed from the previous packet to the
+next packet). Data in each direction is encrypted independently.
+.IP SSH_CIPHER_DES
+The key is taken from the first 8 bytes of the session key. The least
+significant bit of each byte is ignored. This results in 56 bits of
+key data. DES [DES] is used in CBC mode. The iv (initialization vector) is
+initialized to all zeroes.
+.IP SSH_CIPHER_3DES
+The variant of triple-DES used here works as follows: there are three
+independent DES-CBC ciphers, with independent initialization vectors.
+The data (the whole encrypted data stream) is first encrypted with the
+first cipher, then decrypted with the second cipher, and finally
+encrypted with the third cipher. All these operations are performed
+in CBC mode.
+
+The key for the first cipher is taken from the first 8 bytes of the
+session key; the key for the next cipher from the next 8 bytes, and
+the key for the third cipher from the following 8 bytes. All three
+initialization vectors are initialized to zero.
+
+(Note: the variant of 3DES used here differs from some other
+descriptions.)
+.IP SSH_CIPHER_IDEA
+The key is taken from the first 16 bytes of the session key. IDEA
+[IDEA] is used in CFB mode. The initialization vector is initialized
+to all zeroes.
+.IP SSH_CIPHER_TSS
+All 32 bytes of the session key are used as the key.
+
+There is no reference available for the TSS algorithm; it is currently
+only documented in the sample implementation source code. The
+security of this cipher is unknown (but it is quite fast). The cipher
+is basically a stream cipher that uses MD5 as a random number
+generator and takes feedback from the data.
+.IP SSH_CIPHER_RC4
+The first 16 bytes of the session key are used as the key for the
+server to client direction. The remaining 16 bytes are used as the
+key for the client to server direction. This gives independent
+128-bit keys for each direction.
+
+This algorithm is the alleged RC4 cipher posted to the Usenet in 1995.
+It is widely believed to be equivalent with the original RSADSI RC4
+cipher. This is a very fast algorithm.
+.RT
+
+
+.ti 0
+Data Type Encodings
+
+The Data field of each packet contains data encoded as described in
+this section. There may be several data items; each item is coded as
+described here, and their representations are concatenated together
+(without any alignment or padding).
+
+Each data type is stored as follows:
+.IP "8-bit byte"
+The byte is stored directly as a single byte.
+.IP "32-bit unsigned integer"
+Stored in 4 bytes, msb first.
+.IP "Arbitrary length binary string"
+First 4 bytes are the length of the string, msb first (not including
+the length itself). The following "length" bytes are the string
+value. There are no terminating null characters.
+.IP "Multiple-precision integer"
+First 2 bytes are the number of bits in the integer, msb first (for
+example, the value 0x00012345 would have 17 bits). The value zero has
+zero bits. It is permissible that the number of bits be larger than the
+real number of bits.
+
+The number of bits is followed by (bits + 7) / 8 bytes of binary data,
+msb first, giving the value of the integer.
+.RT
+
+
+.ti 0
+TCP/IP Port Number and Other Options
+
+The server listens for connections on TCP/IP port 22.
+
+The client may connect the server from any port. However, if the
+client wishes to use any form of .rhosts or /etc/hosts.equiv
+authentication, it must connect from a privileged port (less than
+1024).
+
+For the IP Type of Service field [RFC0791], it is recommended that
+interactive sessions (those having a user terminal or forwarding X11
+connections) use the IPTOS_LOWDELAY, and non-interactive connections
+use IPTOS_THROUGHPUT.
+
+It is recommended that keepalives are used, because otherwise programs
+on the server may never notice if the other end of the connection is
+rebooted.
+
+
+.ti 0
+Protocol Version Identification
+
+After the socket is opened, the server sends an identification string,
+which is of the form
+"SSH-<protocolmajor>.<protocolminor>-<version>\\n", where
+<protocolmajor> and <protocolminor> are integers and specify the
+protocol version number (not software distribution version).
+<version> is server side software version string (max 40 characters);
+it is not interpreted by the remote side but may be useful for
+debugging.
+
+The client parses the server's string, and sends a corresponding
+string with its own information in response. If the server has lower
+version number, and the client contains special code to emulate it,
+the client responds with the lower number; otherwise it responds with
+its own number. The server then compares the version number the
+client sent with its own, and determines whether they can work
+together. The server either disconnects, or sends the first packet
+using the binary packet protocol and both sides start working
+according to the lower of the protocol versions.
+
+By convention, changes which keep the protocol compatible with
+previous versions keep the same major protocol version; changes that
+are not compatible increment the major version (which will hopefully
+never happen). The version described in this document is 1.3.
+
+The client will
+
+.ti 0
+Key Exchange and Server Host Authentication
+
+The first message sent by the server using the packet protocol is
+SSH_SMSG_PUBLIC_KEY. It declares the server's host key, server public
+key, supported ciphers, supported authentication methods, and flags
+for protocol extensions. It also contains a 64-bit random number
+(cookie) that must be returned in the client's reply (to make IP
+spoofing more difficult). No encryption is used for this message.
+
+Both sides compute a session id as follows. The modulus of the server
+key is interpreted as a byte string (without explicit length field,
+with minimum length able to hold the whole value), most significant
+byte first. This string is concatenated with the server host key
+interpreted the same way. Additionally, the cookie is concatenated
+with this. Both sides compute MD5 of the resulting string. The
+resulting 16 bytes (128 bits) are stored by both parties and are
+called the session id.
+
+The client responds with a SSH_CMSG_SESSION_KEY message, which
+contains the selected cipher type, a copy of the 64-bit cookie sent by
+the server, client's protocol flags, and a session key encrypted
+with both the server's host key and server key. No encryption is used
+for this message.
+
+The session key is 32 8-bit bytes (a total of 256 random bits
+generated by the client). The client first xors the 16 bytes of the
+session id with the first 16 bytes of the session key. The resulting
+string is then encrypted using the smaller key (one with smaller
+modulus), and the result is then encrypted using the other key. The
+number of bits in the public modulus of the two keys must differ by at
+least 128 bits.
+
+At each encryption step, a multiple-precision integer is constructed
+from the data to be encrypted as follows (the integer is here
+interpreted as a sequence of bytes, msb first; the number of bytes is
+the number of bytes needed to represent the modulus).
+
+The most significant byte (which is only partial as the value must be
+less than the public modulus, which is never a power of two) is zero.
+
+The next byte contains the value 2 (which stands for public-key
+encrypted data in the PKCS standard [PKCS#1]). Then, there are
+non-zero random bytes to fill any unused space, a zero byte, and the
+data to be encrypted in the least significant bytes, the last byte of
+the data in the least significant byte.
+
+This algorithm is used twice. First, it is used to encrypt the 32
+random bytes generated by the client to be used as the session key
+(xored by the session id). This value is converted to an integer as
+described above, and encrypted with RSA using the key with the smaller
+modulus. The resulting integer is converted to a byte stream, msb
+first. This byte stream is padded and encrypted identically using the
+key with the larger modulus.
+
+After the client has sent the session key, it starts to use the
+selected algorithm and key for decrypting any received packets, and
+for encrypting any sent packets. Separate ciphers are used for
+different directions (that is, both directions have separate
+initialization vectors or other state for the ciphers).
+
+When the server has received the session key message, and has turned
+on encryption, it sends a SSH_SMSG_SUCCESS message to the client.
+
+The recommended size of the host key is 1024 bits, and 768 bits for
+the server key. The minimum size is 512 bits for the smaller key.
+
+
+.ti 0
+Declaring the User Name
+
+The client then sends a SSH_CMSG_USER message to the server. This
+message specifies the user name to log in as.
+
+The server validates that such a user exists, checks whether
+authentication is needed, and responds with either SSH_SMSG_SUCCESS or
+SSH_SMSG_FAILURE. SSH_SMSG_SUCCESS indicates that no authentication
+is needed for this user (no password), and authentication phase has
+now been completed. SSH_SMSG_FAILURE indicates that authentication is
+needed (or the user does not exist).
+
+If the user does not exist, it is recommended that this returns
+failure, but the server keeps reading messages from the client, and
+responds to any messages (except SSH_MSG_DISCONNECT, SSH_MSG_IGNORE,
+and SSH_MSG_DEBUG) with SSH_SMSG_FAILURE. This way the client cannot
+be certain whether the user exists.
+
+
+.ti 0
+Authentication Phase
+
+Provided the server didn't immediately accept the login, an
+authentication exchange begins. The client sends messages to the
+server requesting different types of authentication in arbitrary order as
+many times as desired (however, the server may close the connection
+after a timeout). The server always responds with SSH_SMSG_SUCCESS if
+it has accepted the authentication, and with SSH_SMSG_FAILURE if it has
+denied authentication with the requested method or it does not
+recognize the message. Some authentication methods cause an exchange
+of further messages before the final result is sent. The
+authentication phase ends when the server responds with success.
+
+The recommended value for the authentication timeout (timeout before
+disconnecting if no successful authentication has been made) is 5
+minutes.
+
+The following authentication methods are currently supported:
+.TS
+center;
+l r l.
+SSH_AUTH_RHOSTS 1 .rhosts or /etc/hosts.equiv
+SSH_AUTH_RSA 2 pure RSA authentication
+SSH_AUTH_PASSWORD 3 password authentication
+SSH_AUTH_RHOSTS_RSA 4 .rhosts with RSA host authentication
+.TE
+.IP SSH_AUTH_RHOSTS
+
+This is the authentication method used by rlogin and rsh [RFC1282].
+
+The client sends SSH_CMSG_AUTH_RHOSTS with the client-side user name
+as an argument.
+
+The server checks whether to permit authentication. On UNIX systems,
+this is usually done by checking /etc/hosts.equiv, and .rhosts in the
+user's home directory. The connection must come from a privileged
+port.
+
+It is recommended that the server checks that there are no IP options
+(such as source routing) specified for the socket before accepting
+this type of authentication. The client host name should be
+reverse-mapped and then forward mapped to ensure that it has the
+proper IP-address.
+
+This authentication method trusts the remote host (root on the remote
+host can pretend to be any other user on that host), the name
+services, and partially the network: anyone who can see packets coming
+out from the server machine can do IP-spoofing and pretend to be any
+machine; however, the protocol prevents blind IP-spoofing (which used
+to be possible with rlogin).
+
+Many sites probably want to disable this authentication method because
+of the fundamental insecurity of conventional .rhosts or
+/etc/hosts.equiv authentication when faced with spoofing. It is
+recommended that this method not be supported by the server by
+default.
+.IP SSH_AUTH_RHOSTS_RSA
+
+In addition to conventional .rhosts and hosts.equiv authentication,
+this method additionally requires that the client host be
+authenticated using RSA.
+
+The client sends SSH_CMSG_AUTH_RHOSTS_RSA specifying the client-side
+user name, and the public host key of the client host.
+
+The server first checks if normal .rhosts or /etc/hosts.equiv
+authentication would be accepted, and if not, responds with
+SSH_SMSG_FAILURE. Otherwise, it checks whether it knows the host key
+for the client machine (using the same name for the host that was used
+for checking the .rhosts and /etc/hosts.equiv files). If it does not
+know the RSA key for the client, access is denied and SSH_SMSG_FAILURE
+is sent.
+
+If the server knows the host key of the client machine, it verifies
+that the given host key matches that known for the client. If not,
+access is denied and SSH_SMSG_FAILURE is sent.
+
+The server then sends a SSH_SMSG_AUTH_RSA_CHALLENGE message containing
+an encrypted challenge for the client. The challenge is 32 8-bit
+random bytes (256 bits). When encrypted, the highest (partial) byte
+is left as zero, the next byte contains the value 2, the following are
+non-zero random bytes, followed by a zero byte, and the challenge put
+in the remaining bytes. This is then encrypted using RSA with the
+client host's public key. (The padding and encryption algorithm is
+the same as that used for the session key.)
+
+The client decrypts the challenge using its private host key,
+concatenates this with the session id, and computes an MD5 checksum
+of the resulting 48 bytes. The MD5 output is returned as 16 bytes in
+a SSH_CMSG_AUTH_RSA_RESPONSE message. (MD5 is used to deter chosen
+plaintext attacks against RSA; the session id binds it to a specific
+session).
+
+The server verifies that the MD5 of the decrypted challenge returned by
+the client matches that of the original value, and sends SSH_SMSG_SUCCESS if
+so. Otherwise it sends SSH_SMSG_FAILURE and refuses the
+authentication attempt.
+
+This authentication method trusts the client side machine in that root
+on that machine can pretend to be any user on that machine.
+Additionally, it trusts the client host key. The name and/or IP
+address of the client host is only used to select the public host key.
+The same host name is used when scanning .rhosts or /etc/hosts.equiv
+and when selecting the host key. It would in principle be possible to
+eliminate the host name entirely and substitute it directly by the
+host key. IP and/or DNS [RFC1034] spoofing can only be used
+to pretend to be a host for which the attacker has the private host
+key.
+.IP SSH_AUTH_RSA
+
+The idea behind RSA authentication is that the server recognizes the
+public key offered by the client, generates a random challenge, and
+encrypts the challenge with the public key. The client must then
+prove that it has the corresponding private key by decrypting the
+challenge.
+
+The client sends SSH_CMSG_AUTH_RSA with public key modulus (n) as an
+argument.
+
+The server may respond immediately with SSH_SMSG_FAILURE if it does
+not permit authentication with this key. Otherwise it generates a
+challenge, encrypts it using the user's public key (stored on the
+server and identified using the modulus), and sends
+SSH_SMSG_AUTH_RSA_CHALLENGE with the challenge (mp-int) as an
+argument.
+
+The challenge is 32 8-bit random bytes (256 bits). When encrypted,
+the highest (partial) byte is left as zero, the next byte contains the
+value 2, the following are non-zero random bytes, followed by a zero
+byte, and the challenge put in the remaining bytes. This is then
+encrypted with the public key. (The padding and encryption algorithm
+is the same as that used for the session key.)
+
+The client decrypts the challenge using its private key, concatenates
+it with the session id, and computes an MD5 checksum of the resulting
+48 bytes. The MD5 output is returned as 16 bytes in a
+SSH_CMSG_AUTH_RSA_RESPONSE message. (Note that the MD5 is necessary
+to avoid chosen plaintext attacks against RSA; the session id binds it
+to a specific session.)
+
+The server verifies that the MD5 of the decrypted challenge returned
+by the client matches that of the original value, and sends
+SSH_SMSG_SUCCESS if so. Otherwise it sends SSH_SMSG_FAILURE and
+refuses the authentication attempt.
+
+This authentication method does not trust the remote host, the
+network, name services, or anything else. Authentication is based
+solely on the possession of the private identification keys. Anyone
+in possession of the private keys can log in, but nobody else.
+
+The server may have additional requirements for a successful
+authentiation. For example, to limit damage due to a compromised RSA
+key, a server might restrict access to a limited set of hosts.
+.IP SSH_AUTH_PASSWORD
+
+The client sends a SSH_CMSG_AUTH_PASSWORD message with the plain text
+password. (Note that even though the password is plain text inside
+the message, it is normally encrypted by the packet mechanism.)
+
+The server verifies the password, and sends SSH_SMSG_SUCCESS if
+authentication was accepted and SSH_SMSG_FAILURE otherwise.
+
+Note that the password is read from the user by the client; the user
+never interacts with a login program.
+
+This authentication method does not trust the remote host, the
+network, name services or anything else. Authentication is based
+solely on the possession of the password. Anyone in possession of the
+password can log in, but nobody else.
+.RT
+
+.ti 0
+Preparatory Operations
+
+After successful authentication, the server waits for a request from
+the client, processes the request, and responds with SSH_SMSG_SUCCESS
+whenever a request has been successfully processed. If it receives a
+message that it does not recognize or it fails to honor a request, it
+returns SSH_SMSG_FAILURE. It is expected that new message types might
+be added to this phase in future.
+
+The following messages are currently defined for this phase.
+.IP SSH_CMSG_REQUEST_COMPRESSION
+Requests that compression be enabled for this session. A
+gzip-compatible compression level (1-9) is passed as an argument.
+.IP SSH_CMSG_REQUEST_PTY
+Requests that a pseudo terminal device be allocated for this session.
+The user terminal type and terminal modes are supplied as arguments.
+.IP SSH_CMSG_X11_REQUEST_FORWARDING
+Requests forwarding of X11 connections from the remote machine to the
+local machine over the secure channel. Causes an internet-domain
+socket to be allocated and the DISPLAY variable to be set on the server.
+X11 authentication data is automatically passed to the server, and the
+client may implement spoofing of authentication data for added
+security. The authentication data is passed as arguments.
+.IP SSH_CMSG_PORT_FORWARD_REQUEST
+Requests forwarding of a TCP/IP port on the server host over the
+secure channel. What happens is that whenever a connection is made to
+the port on the server, a connection will be made from the client end
+to the specified host/port. Any user can forward unprivileged ports;
+only the root can forward privileged ports (as determined by
+authentication done earlier).
+.IP SSH_CMSG_AGENT_REQUEST_FORWARDING
+Requests forwarding of the connection to the authentication agent.
+.IP SSH_CMSG_EXEC_SHELL
+Starts a shell (command interpreter) for the user, and moves into
+interactive session mode.
+.IP SSH_CMSG_EXEC_CMD
+Executes the given command (actually "<shell> -c <command>" or
+equivalent) for the user, and moves into interactive session mode.
+.RT
+
+
+.ti 0
+Interactive Session and Exchange of Data
+
+During the interactive session, any data written by the shell or
+command running on the server machine is forwarded to stdin or
+stderr on the client machine, and any input available from stdin on
+the client machine is forwarded to the program on the server machine.
+
+All exchange is asynchronous; either side can send at any time, and
+there are no acknowledgements (TCP/IP already provides reliable
+transport, and the packet protocol protects against tampering or IP
+spoofing).
+
+When the client receives EOF from its standard input, it will send
+SSH_CMSG_EOF; however, this in no way terminates the exchange. The
+exchange terminates and interactive mode is left when the server sends
+SSH_SMSG_EXITSTATUS to indicate that the client program has
+terminated. Alternatively, either side may disconnect at any time by
+sending SSH_MSG_DISCONNECT or closing the connection.
+
+The server may send any of the following messages:
+.IP SSH_SMSG_STDOUT_DATA
+Data written to stdout by the program running on the server. The data
+is passed as a string argument. The client writes this data to
+stdout.
+.IP SSH_SMSG_STDERR_DATA
+Data written to stderr by the program running on the server. The data
+is passed as a string argument. The client writes this data to
+stderr. (Note that if the program is running on a tty, it is not
+possible to separate stdout and stderr data, and all data will be sent
+as stdout data.)
+.IP SSH_SMSG_EXITSTATUS
+Indicates that the shell or command has exited. Exit status is passed
+as an integer argument. This message causes termination of the
+interactive session.
+.IP SSH_SMSG_AGENT_OPEN
+Indicates that someone on the server side is requesting a connection
+to the authentication agent. The server-side channel number is passed
+as an argument. The client must respond with either
+SSH_CHANNEL_OPEN_CONFIRMATION or SSH_CHANNEL_OPEN_FAILURE.
+.IP SSH_SMSG_X11_OPEN
+Indicates that a connection has been made to the X11 socket on the
+server side and should be forwarded to the real X server. An integer
+argument indicates the channel number allocated for this connection on
+the server side. The client should send back either
+SSH_MSG_CHANNEL_OPEN_CONFIRMATION or SSH_MSG_CHANNEL_OPEN_FAILURE with
+the same server side channel number.
+.IP SSH_MSG_PORT_OPEN
+Indicates that a connection has been made to a port on the server side
+for which forwarding has been requested. Arguments are server side
+channel number, host name to connect to, and port to connect to. The
+client should send back either
+SSH_MSG_CHANNEL_OPEN_CONFIRMATION or SSH_MSG_CHANNEL_OPEN_FAILURE with
+the same server side channel number.
+.IP SSH_MSG_CHANNEL_OPEN_CONFIRMATION
+This is sent by the server to indicate that it has opened a connection
+as requested in a previous message. The first argument indicates the
+client side channel number, and the second argument is the channel number
+that the server has allocated for this connection.
+.IP SSH_MSG_CHANNEL_OPEN_FAILURE
+This is sent by the server to indicate that it failed to open a
+connection as requested in a previous message. The client-side
+channel number is passed as an argument. The client will close the
+descriptor associated with the channel and free the channel.
+.IP SSH_MSG_CHANNEL_DATA
+This packet contains data for a channel from the server. The first
+argument is the client-side channel number, and the second argument (a
+string) is the data.
+.IP SSH_MSG_CHANNEL_CLOSE
+This is sent by the server to indicate that whoever was in the other
+end of the channel has closed it. The argument is the client side channel
+number. The client will let all buffered data in the channel to
+drain, and when ready, will close the socket, free the channel, and
+send the server a SSH_MSG_CHANNEL_CLOSE_CONFIRMATION message for the
+channel.
+.IP SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
+This is send by the server to indicate that a channel previously
+closed by the client has now been closed on the server side as well.
+The argument indicates the client channel number. The client frees
+the channel.
+.RT
+
+The client may send any of the following messages:
+.IP SSH_CMSG_STDIN_DATA
+This is data to be sent as input to the program running on the server.
+The data is passed as a string.
+.IP SSH_CMSG_EOF
+Indicates that the client has encountered EOF while reading standard
+input. The server will allow any buffered input data to drain, and
+will then close the input to the program.
+.IP SSH_CMSG_WINDOW_SIZE
+Indicates that window size on the client has been changed. The server
+updates the window size of the tty and causes SIGWINCH to be sent to
+the program. The new window size is passed as four integer arguments:
+row, col, xpixel, ypixel.
+.IP SSH_MSG_PORT_OPEN
+Indicates that a connection has been made to a port on the client side
+for which forwarding has been requested. Arguments are client side
+channel number, host name to connect to, and port to connect to. The
+server should send back either SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+SSH_MSG_CHANNEL_OPEN_FAILURE with the same client side channel number.
+.IP SSH_MSG_CHANNEL_OPEN_CONFIRMATION
+This is sent by the client to indicate that it has opened a connection
+as requested in a previous message. The first argument indicates the
+server side channel number, and the second argument is the channel
+number that the client has allocated for this connection.
+.IP SSH_MSG_CHANNEL_OPEN_FAILURE
+This is sent by the client to indicate that it failed to open a
+connection as requested in a previous message. The server side
+channel number is passed as an argument. The server will close the
+descriptor associated with the channel and free the channel.
+.IP SSH_MSG_CHANNEL_DATA
+This packet contains data for a channel from the client. The first
+argument is the server side channel number, and the second argument (a
+string) is the data.
+.IP SSH_MSG_CHANNEL_CLOSE
+This is sent by the client to indicate that whoever was in the other
+end of the channel has closed it. The argument is the server channel
+number. The server will allow buffered data to drain, and when ready,
+will close the socket, free the channel, and send the client a
+SSH_MSG_CHANNEL_CLOSE_CONFIRMATION message for the channel.
+.IP SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
+This is send by the client to indicate that a channel previously
+closed by the server has now been closed on the client side as well.
+The argument indicates the server channel number. The server frees
+the channel.
+.RT
+
+Any unsupported messages during interactive mode cause the connection
+to be terminated with SSH_MSG_DISCONNECT and an error message.
+Compatible protocol upgrades should agree about any extensions during
+the preparation phase or earlier.
+
+
+.ti 0
+Termination of the Connection
+
+Normal termination of the connection is always initiated by the server
+by sending SSH_SMSG_EXITSTATUS after the program has exited. The
+client responds to this message by sending SSH_CMSG_EXIT_CONFIRMATION
+and closes the socket; the server then closes the socket. There are
+two purposes for the confirmation: some systems may lose previously
+sent data when the socket is closed, and closing the client side first
+causes any TCP/IP TIME_WAIT [RFC0793] waits to occur on the client side, not
+consuming server resources.
+
+If the program terminates due to a signal, the server will send
+SSH_MSG_DISCONNECT with an appropriate message. If the connection is
+closed, all file descriptors to the program will be closed and the
+server will exit. If the program runs on a tty, the kernel sends it
+the SIGHUP signal when the pty master side is closed.
+
+.ti 0
+Protocol Flags
+
+Both the server and the client pass 32 bits of protocol flags to the
+other side. The flags are intended for compatible protocol extension;
+the server first announces which added capabilities it supports, and
+the client then sends the capabilities that it supports.
+
+The following flags are currently defined (the values are bit masks):
+.IP "1 SSH_PROTOFLAG_SCREEN_NUMBER"
+This flag can only be sent by the client. It indicates that the X11
+forwarding requests it sends will include the screen number.
+.IP "2 SSH_PROTOFLAG_HOST_IN_FWD_OPEN"
+If both sides specify this flag, SSH_SMSG_X11_OPEN and
+SSH_MSG_PORT_OPEN messages will contain an additional field containing
+a description of the host at the other end of the connection.
+.RT
+
+.ti 0
+Detailed Description of Packet Types and Formats
+
+The supported packet types and the corresponding message numbers are
+given in the following table. Messages with _MSG_ in their name may
+be sent by either side. Messages with _CMSG_ are only sent by the
+client, and messages with _SMSG_ only by the server.
+
+A packet may contain additional data after the arguments specified
+below. Any such data should be ignored by the receiver. However, it
+is recommended that no such data be stored without good reason. (This
+helps build compatible extensions.)
+.IP "0 SSH_MSG_NONE"
+This code is reserved. This message type is never sent.
+.IP "1 SSH_MSG_DISCONNECT"
+.TS
+;
+l l.
+string Cause of disconnection
+.TE
+This message may be sent by either party at any time. It causes the
+immediate disconnection of the connection. The message is intended to
+be displayed to a human, and describes the reason for disconnection.
+.IP "2 SSH_SMSG_PUBLIC_KEY"
+.TS
+;
+l l.
+8 bytes anti_spoofing_cookie
+32-bit int server_key_bits
+mp-int server_key_public_exponent
+mp-int server_key_public_modulus
+32-bit int host_key_bits
+mp-int host_key_public_exponent
+mp-int host_key_public_modulus
+32-bit int protocol_flags
+32-bit int supported_ciphers_mask
+32-bit int supported_authentications_mask
+.TE
+Sent as the first message by the server. This message gives the
+server's host key, server key, protocol flags (intended for compatible
+protocol extension), supported_ciphers_mask (which is the
+bitwise or of (1 << cipher_number), where << is the left shift
+operator, for all supported ciphers), and
+supported_authentications_mask (which is the bitwise or of (1 <<
+authentication_type) for all supported authentication types). The
+anti_spoofing_cookie is 64 random bytes, and must be sent back
+verbatim by the client in its reply. It is used to make IP-spoofing
+more difficult (encryption and host keys are the real defense against
+spoofing).
+.IP "3 SSH_CMSG_SESSION_KEY"
+.TS
+;
+l l.
+1 byte cipher_type (must be one of the supported values)
+8 bytes anti_spoofing_cookie (must match data sent by the server)
+mp-int double-encrypted session key
+32-bit int protocol_flags
+.TE
+Sent by the client as the first message in the session. Selects the
+cipher to use, and sends the encrypted session key to the server. The
+anti_spoofing_cookie must be the same bytes that were sent by the
+server. Protocol_flags is intended for negotiating compatible
+protocol extensions.
+.IP "4 SSH_CMSG_USER"
+.TS
+;
+l l.
+string user login name on server
+.TE
+Sent by the client to begin authentication. Specifies the user name
+on the server to log in as. The server responds with SSH_SMSG_SUCCESS
+if no authentication is needed for this user, or SSH_SMSG_FAILURE if
+authentication is needed (or the user does not exist). [Note to the
+implementator: the user name is of arbitrary size. The implementation
+must be careful not to overflow internal buffers.]
+.IP "5 SSH_CMSG_AUTH_RHOSTS"
+.TS
+;
+l l.
+string client-side user name
+.TE
+Requests authentication using /etc/hosts.equiv and .rhosts (or
+equivalent mechanisms). This authentication method is normally
+disabled in the server because it is not secure (but this is the
+method used by rsh and rlogin). The server responds with
+SSH_SMSG_SUCCESS if authentication was successful, and
+SSH_SMSG_FAILURE if access was not granted. The server should check
+that the client side port number is less than 1024 (a privileged
+port), and immediately reject authentication if it is not. Supporting
+this authentication method is optional. This method should normally
+not be enabled in the server because it is not safe. (However, not
+enabling this only helps if rlogind and rshd are disabled.)
+.IP "6 SSH_CMSG_AUTH_RSA"
+.TS
+;
+l l.
+mp-int identity_public_modulus
+.TE
+Requests authentication using pure RSA authentication. The server
+checks if the given key is permitted to log in, and if so, responds
+with SSH_SMSG_AUTH_RSA_CHALLENGE. Otherwise, it responds with
+SSH_SMSG_FAILURE. The client often tries several different keys in
+sequence until one supported by the server is found. Authentication
+is accepted if the client gives the correct response to the challenge.
+The server is free to add other criteria for authentication, such as a
+requirement that the connection must come from a certain host. Such
+additions are not visible at the protocol level. Supporting this
+authentication method is optional but recommended.
+.IP "7 SSH_SMSG_AUTH_RSA_CHALLENGE"
+.TS
+;
+l l.
+mp-int encrypted challenge
+.TE
+Presents an RSA authentication challenge to the client. The challenge
+is a 256-bit random value encrypted as described elsewhere in this
+document. The client must decrypt the challenge using the RSA private
+key, compute MD5 of the challenge plus session id, and send back the
+resulting 16 bytes using SSH_CMSG_AUTH_RSA_RESPONSE.
+.IP "8 SSH_CMSG_AUTH_RSA_RESPONSE"
+.TS
+;
+l l.
+16 bytes MD5 of decrypted challenge
+.TE
+This message is sent by the client in response to an RSA challenge.
+The MD5 checksum is returned instead of the decrypted challenge to
+deter known-plaintext attacks against the RSA key. The server
+responds to this message with either SSH_SMSG_SUCCESS or
+SSH_SMSG_FAILURE.
+.IP "9 SSH_CMSG_AUTH_PASSWORD"
+.TS
+;
+l l.
+string plain text password
+.TE
+Requests password authentication using the given password. Note that
+even though the password is plain text inside the packet, the whole
+packet is normally encrypted by the packet layer. It would not be
+possible for the client to perform password encryption/hashing,
+because it cannot know which kind of encryption/hashing, if any, the
+server uses. The server responds to this message with
+SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE.
+.IP "10 SSH_CMSG_REQUEST_PTY"
+.TS
+;
+l l.
+string TERM environment variable value (e.g. vt100)
+32-bit int terminal height, rows (e.g., 24)
+32-bit int terminal width, columns (e.g., 80)
+32-bit int terminal width, pixels (0 if no graphics) (e.g., 480)
+32-bit int terminal height, pixels (0 if no graphics) (e.g., 640)
+n bytes tty modes encoded in binary
+.TE
+Requests a pseudo-terminal to be allocated for this command. This
+message can be used regardless of whether the session will later
+execute the shell or a command. If a pty has been requested with this
+message, the shell or command will run on a pty. Otherwise it will
+communicate with the server using pipes, sockets or some other similar
+mechanism.
+
+The terminal type gives the type of the user's terminal. In the UNIX
+environment it is passed to the shell or command in the TERM
+environment variable.
+
+The width and height values give the initial size of the user's
+terminal or window. All values can be zero if not supported by the
+operating system. The server will pass these values to the kernel if
+supported.
+
+Terminal modes are encoded into a byte stream in a portable format.
+The exact format is described later in this document.
+
+The server responds to the request with either SSH_SMSG_SUCCESS or
+SSH_SMSG_FAILURE. If the server does not have the concept of pseudo
+terminals, it should return success if it is possible to execute a
+shell or a command so that it looks to the client as if it was running
+on a pseudo terminal.
+.IP "11 SSH_CMSG_WINDOW_SIZE"
+.TS
+;
+l l.
+32-bit int terminal height, rows
+32-bit int terminal width, columns
+32-bit int terminal width, pixels
+32-bit int terminal height, pixels
+.TE
+This message can only be sent by the client during the interactive
+session. This indicates that the size of the user's window has
+changed, and provides the new size. The server will update the
+kernel's notion of the window size, and a SIGWINCH signal or
+equivalent will be sent to the shell or command (if supported by the
+operating system).
+.IP "12 SSH_CMSG_EXEC_SHELL"
+
+(no arguments)
+
+Starts a shell (command interpreter), and enters interactive session
+mode.
+.IP "13 SSH_CMSG_EXEC_CMD"
+.TS
+;
+l l.
+string command to execute
+.TE
+Starts executing the given command, and enters interactive session
+mode. On UNIX, the command is run as "<shell> -c <command>", where
+<shell> is the user's login shell.
+.IP "14 SSH_SMSG_SUCCESS"
+
+(no arguments)
+
+This message is sent by the server in response to the session key, a
+successful authentication request, and a successfully completed
+preparatory operation.
+.IP "15 SSH_SMSG_FAILURE"
+
+(no arguments)
+
+This message is sent by the server in response to a failed
+authentication operation to indicate that the user has not yet been
+successfully authenticated, and in response to a failed preparatory
+operation. This is also sent in response to an authentication or
+preparatory operation request that is not recognized or supported.
+.IP "16 SSH_CMSG_STDIN_DATA"
+.TS
+;
+l l.
+string data
+.TE
+Delivers data from the client to be supplied as input to the shell or
+program running on the server side. This message can only be used in
+the interactive session mode. No acknowledgement is sent for this
+message.
+.IP "17 SSH_SMSG_STDOUT_DATA"
+.TS
+;
+l l.
+string data
+.TE
+Delivers data from the server that was read from the standard output of
+the shell or program running on the server side. This message can
+only be used in the interactive session mode. No acknowledgement is
+sent for this message.
+.IP "18 SSH_SMSG_STDERR_DATA"
+.TS
+;
+l l.
+string data
+.TE
+Delivers data from the server that was read from the standard error of
+the shell or program running on the server side. This message can
+only be used in the interactive session mode. No acknowledgement is
+sent for this message.
+.IP "19 SSH_CMSG_EOF"
+
+(no arguments)
+
+This message is sent by the client to indicate that EOF has been
+reached on the input. Upon receiving this message, and after all
+buffered input data has been sent to the shell or program, the server
+will close the input file descriptor to the program. This message can
+only be used in the interactive session mode. No acknowledgement is
+sent for this message.
+.IP "20 SSH_SMSG_EXITSTATUS"
+.TS
+;
+l l.
+32-bit int exit status of the command
+.TE
+Returns the exit status of the shell or program after it has exited.
+The client should respond with SSH_CMSG_EXIT_CONFIRMATION when it has
+received this message. This will be the last message sent by the
+server. If the program being executed dies with a signal instead of
+exiting normally, the server should terminate the session with
+SSH_MSG_DISCONNECT (which can be used to pass a human-readable string
+indicating that the program died due to a signal) instead of using
+this message.
+.IP "21 SSH_MSG_CHANNEL_OPEN_CONFIRMATION"
+.TS
+;
+l l.
+32-bit int remote_channel
+32-bit int local_channel
+.TE
+This is sent in response to any channel open request if the channel
+has been successfully opened. Remote_channel is the channel number
+received in the initial open request; local_channel is the channel
+number the side sending this message has allocated for the channel.
+Data can be transmitted on the channel after this message.
+.IP "22 SSH_MSG_CHANNEL_OPEN_FAILURE"
+.TS
+;
+l l.
+32-bit int remote_channel
+.TE
+This message indicates that an earlier channel open request by the
+other side has failed or has been denied. Remote_channel is the
+channel number given in the original request.
+.IP "23 SSH_MSG_CHANNEL_DATA"
+.TS
+;
+l l.
+32-bit int remote_channel
+string data
+.TE
+Data is transmitted in a channel in these messages. A channel is
+bidirectional, and both sides can send these messages. There is no
+acknowledgement for these messages. It is possible that either side
+receives these messages after it has sent SSH_MSG_CHANNEL_CLOSE for
+the channel. These messages cannot be received after the party has
+sent or received SSH_MSG_CHANNEL_CLOSE_CONFIRMATION.
+.IP "24 SSH_MSG_CHANNEL_CLOSE"
+.TS
+;
+l l.
+32-bit int remote_channel
+.TE
+When a channel is closed at one end of the connection, that side sends
+this message. Upon receiving this message, the channel should be
+closed. When this message is received, if the channel is already
+closed (the receiving side has sent this message for the same channel
+earlier), the channel is freed and no further action is taken;
+otherwise the channel is freed and SSH_MSG_CHANNEL_CLOSE_CONFIRMATION
+is sent in response. (It is possible that the channel is closed
+simultaneously at both ends.)
+.IP "25 SSH_MSG_CHANNEL_CLOSE_CONFIRMATION"
+.TS
+;
+l l.
+32-bit int remote_channel
+.TE
+This message is sent in response to SSH_MSG_CHANNEL_CLOSE unless the
+channel was already closed. When this message is sent or received,
+the channel is freed.
+.IP "26 (OBSOLETED; was unix-domain X11 forwarding)
+.IP "27 SSH_SMSG_X11_OPEN"
+.TS
+;
+l l.
+32-bit int local_channel
+string originator_string (see below)
+.TE
+This message can be sent by the server during the interactive session
+mode to indicate that a client has connected the fake X server.
+Local_channel is the channel number that the server has allocated for
+the connection. The client should try to open a connection to the
+real X server, and respond with SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+SSH_MSG_CHANNEL_OPEN_FAILURE.
+
+The field originator_string is present if both sides
+specified SSH_PROTOFLAG_HOST_IN_FWD_OPEN in the protocol flags. It
+contains a description of the host originating the connection.
+.IP "28 SSH_CMSG_PORT_FORWARD_REQUEST"
+.TS
+;
+l l.
+32-bit int server_port
+string host_to_connect
+32-bit int port_to_connect
+.TE
+Sent by the client in the preparatory phase, this message requests
+that server_port on the server machine be forwarded over the secure
+channel to the client machine, and from there to the specified host
+and port. The server should start listening on the port, and send
+SSH_MSG_PORT_OPEN whenever a connection is made to it. Supporting
+this message is optional, and the server is free to reject any forward
+request. For example, it is highly recommended that unless the user
+has been authenticated as root, forwarding any privileged port numbers
+(below 1024) is denied.
+.IP "29 SSH_MSG_PORT_OPEN"
+.TS
+;
+l l.
+32-bit int local_channel
+string host_name
+32-bit int port
+string originator_string (see below)
+.TE
+Sent by either party in interactive session mode, this message
+indicates that a connection has been opened to a forwarded TCP/IP
+port. Local_channel is the channel number that the sending party has
+allocated for the connection. Host_name is the host the connection
+should be be forwarded to, and the port is the port on that host to
+connect. The receiving party should open the connection, and respond
+with SSH_MSG_CHANNEL_OPEN_CONFIRMATION or
+SSH_MSG_CHANNEL_OPEN_FAILURE. It is recommended that the receiving
+side check the host_name and port for validity to avoid compromising
+local security by compromised remote side software. Particularly, it
+is recommended that the client permit connections only to those ports
+for which it has requested forwarding with SSH_CMSG_PORT_FORWARD_REQUEST.
+
+The field originator_string is present if both sides
+specified SSH_PROTOFLAG_HOST_IN_FWD_OPEN in the protocol flags. It
+contains a description of the host originating the connection.
+.IP "30 SSH_CMSG_AGENT_REQUEST_FORWARDING"
+
+(no arguments)
+
+Requests that the connection to the authentication agent be forwarded
+over the secure channel. The method used by clients to contact the
+authentication agent within each machine is implementation and machine
+dependent. If the server accepts this request, it should arrange that
+any clients run from this session will actually contact the server
+program when they try to contact the authentication agent. The server
+should then send a SSH_SMSG_AGENT_OPEN to open a channel to the agent,
+and the client should forward the connection to the real
+authentication agent. Supporting this message is optional.
+.IP "31 SSH_SMSG_AGENT_OPEN"
+.TS
+;
+l l.
+32-bit int local_channel
+.TE
+Sent by the server in interactive session mode, this message requests
+opening a channel to the authentication agent. The client should open
+a channel, and respond with either SSH_MSG_CHANNEL_OPEN_CONFIRMATION
+or SSH_MSG_CHANNEL_OPEN_FAILURE.
+.IP "32 SSH_MSG_IGNORE"
+.TS
+;
+l l.
+string data
+.TE
+Either party may send this message at any time. This message, and the
+argument string, is silently ignored. This message might be used in
+some implementations to make traffic analysis more difficult. This
+message is not currently sent by the implementation, but all
+implementations are required to recognize and ignore it.
+.IP "33 SSH_CMSG_EXIT_CONFIRMATION"
+
+(no arguments)
+
+Sent by the client in response to SSH_SMSG_EXITSTATUS. This is the
+last message sent by the client.
+.IP "34 SSH_CMSG_X11_REQUEST_FORWARDING"
+.TS
+;
+l l.
+string x11_authentication_protocol
+string x11_authentication_data
+32-bit int screen number (if SSH_PROTOFLAG_SCREEN_NUMBER)
+.TE
+Sent by the client during the preparatory phase, this message requests
+that the server create a fake X11 display and set the DISPLAY
+environment variable accordingly. An internet-domain display is
+preferable. The given authentication protocol and the associated data
+should be recorded by the server so that it is used as authentication
+on connections (e.g., in .Xauthority). The authentication protocol
+must be one of the supported X11 authentication protocols, e.g.,
+"MIT-MAGIC-COOKIE-1". Authentication data must be a lowercase hex
+string of even length. Its interpretation is protocol dependent.
+The data is in a format that can be used with e.g. the xauth program.
+Supporting this message is optional.
+
+The client is permitted (and recommended) to generate fake
+authentication information and send fake information to the server.
+This way, a corrupt server will not have access to the user's terminal
+after the connection has terminated. The correct authorization codes
+will also not be left hanging around in files on the server (many
+users keep the same X session for months, thus protecting the
+authorization data becomes important).
+
+X11 authentication spoofing works by initially sending fake (random)
+authentication data to the server, and interpreting the first packet
+sent by the X11 client after the connection has been opened. The
+first packet contains the client's authentication. If the packet
+contains the correct fake data, it is replaced by the client by the
+correct authentication data, and then sent to the X server.
+.IP "35 SSH_CMSG_AUTH_RHOSTS_RSA"
+.TS
+;
+l l.
+string clint-side user name
+32-bit int client_host_key_bits
+mp-int client_host_key_public_exponent
+mp-int client_host_key_public_modulus
+.TE
+Requests authentication using /etc/hosts.equiv and .rhosts (or
+equivalent) together with RSA host authentication. The server should
+check that the client side port number is less than 1024 (a privileged
+port), and immediately reject authentication if it is not. The server
+responds with SSH_SMSG_FAILURE or SSH_SMSG_AUTH_RSA_CHALLENGE. The
+client must respond to the challenge with the proper
+SSH_CMSG_AUTH_RSA_RESPONSE. The server then responds with success if
+access was granted, or failure if the client gave a wrong response.
+Supporting this authentication method is optional but recommended in
+most environments.
+.IP "36 SSH_MSG_DEBUG"
+.TS
+;
+l l.
+string debugging message sent to the other side
+.TE
+This message may be sent by either party at any time. It is used to
+send debugging messages that may be informative to the user in
+solving various problems. For example, if authentication fails
+because of some configuration error (e.g., incorrect permissions for
+some file), it can be very helpful for the user to make the cause of
+failure available. On the other hand, one should not make too much
+information available for security reasons. It is recommended that
+the client provides an option to display the debugging information
+sent by the sender (the user probably does not want to see it by default).
+The server can log debugging data sent by the client (if any). Either
+party is free to ignore any received debugging data. Every
+implementation must be able to receive this message, but no
+implementation is required to send these.
+.IP "37 SSH_CMSG_REQUEST_COMPRESSION"
+.TS
+;
+l l.
+32-bit int gzip compression level (1-9)
+.TE
+This message can be sent by the client in the preparatory operations
+phase. The server responds with SSH_SMSG_FAILURE if it does not
+support compression or does not want to compress; it responds with
+SSH_SMSG_SUCCESS if it accepted the compression request. In the
+latter case the response to this packet will still be uncompressed,
+but all further packets in either direction will be compressed by gzip.
+.RT
+
+
+.ti 0
+Encoding of Terminal Modes
+
+Terminal modes (as passed in SSH_CMSG_REQUEST_PTY) are encoded into a
+byte stream. It is intended that the coding be portable across
+different environments.
+
+The tty mode description is a stream of bytes. The stream consists of
+opcode-argument pairs. It is terminated by opcode TTY_OP_END (0).
+Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have 32-bit
+integer arguments (stored msb first). Opcodes 160-255 are not yet
+defined, and cause parsing to stop (they should only be used after any
+other data).
+
+The client puts in the stream any modes it knows about, and the server
+ignores any modes it does not know about. This allows some degree of
+machine-independence, at least between systems that use a POSIX-like
+[POSIX] tty interface. The protocol can support other systems as
+well, but the client may need to fill reasonable values for a number
+of parameters so the server pty gets set to a reasonable mode (the
+server leaves all unspecified mode bits in their default values, and
+only some combinations make sense).
+
+The following opcodes have been defined. The naming of opcodes mostly
+follows the POSIX terminal mode flags.
+.IP "0 TTY_OP_END"
+Indicates end of options.
+.IP "1 VINTR"
+Interrupt character; 255 if none. Similarly for the other characters.
+Not all of these characters are supported on all systems.
+.IP "2 VQUIT"
+The quit character (sends SIGQUIT signal on UNIX systems).
+.IP "3 VERASE"
+Erase the character to left of the cursor.
+.IP "4 VKILL"
+Kill the current input line.
+.IP "5 VEOF "
+End-of-file character (sends EOF from the terminal).
+.IP "6 VEOL "
+End-of-line character in addition to carriage return and/or linefeed.
+.IP "7 VEOL2"
+Additional end-of-line character.
+.IP "8 VSTART"
+Continues paused output (normally ^Q).
+.IP "9 VSTOP"
+Pauses output (^S).
+.IP "10 VSUSP"
+Suspends the current program.
+.IP "11 VDSUSP"
+Another suspend character.
+.IP "12 VREPRINT"
+Reprints the current input line.
+.IP "13 VWERASE"
+Erases a word left of cursor.
+.IP "14 VLNEXT"
+More special input characters; these are probably not supported on
+most systems.
+.IP "15 VFLUSH"
+.IP "16 VSWTCH"
+.IP "17 VSTATUS"
+.IP "18 VDISCARD"
+
+.IP "30 IGNPAR"
+The ignore parity flag. The next byte should be 0 if this flag is not
+set, and 1 if it is set.
+.IP "31 PARMRK"
+More flags. The exact definitions can be found in the POSIX standard.
+.IP "32 INPCK"
+.IP "33 ISTRIP"
+.IP "34 INLCR"
+.IP "35 IGNCR"
+.IP "36 ICRNL"
+.IP "37 IUCLC"
+.IP "38 IXON"
+.IP "39 IXANY"
+.IP "40 IXOFF"
+.IP "41 IMAXBEL"
+
+.IP "50 ISIG"
+.IP "51 ICANON"
+.IP "52 XCASE"
+.IP "53 ECHO"
+.IP "54 ECHOE"
+.IP "55 ECHOK"
+.IP "56 ECHONL"
+.IP "57 NOFLSH"
+.IP "58 TOSTOP"
+.IP "59 IEXTEN"
+.IP "60 ECHOCTL"
+.IP "61 ECHOKE"
+.IP "62 PENDIN"
+
+.IP "70 OPOST"
+.IP "71 OLCUC"
+.IP "72 ONLCR"
+.IP "73 OCRNL"
+.IP "74 ONOCR"
+.IP "75 ONLRET"
+
+.IP "90 CS7"
+.IP "91 CS8"
+.IP "92 PARENB"
+.IP "93 PARODD"
+
+.IP "192 TTY_OP_ISPEED"
+Specifies the input baud rate in bits per second.
+.IP "193 TTY_OP_OSPEED"
+Specifies the output baud rate in bits per second.
+.RT
+
+
+.ti 0
+The Authentication Agent Protocol
+
+The authentication agent is a program that can be used to hold RSA
+authentication keys for the user (in future, it might hold data for
+other authentication types as well). An authorized program can send
+requests to the agent to generate a proper response to an RSA
+challenge. How the connection is made to the agent (or its
+representative) inside a host and how access control is done inside a
+host is implementation-dependent; however, how it is forwarded and how
+one interacts with it is specified in this protocol. The connection
+to the agent is normally automatically forwarded over the secure
+channel.
+
+A program that wishes to use the agent first opens a connection to its
+local representative (typically, the agent itself or an SSH server).
+It then writes a request to the connection, and waits for response.
+It is recommended that at least five minutes of timeout are provided
+waiting for the agent to respond to an authentication challenge (this
+gives sufficient time for the user to cut-and-paste the challenge to a
+separate machine, perform the computation there, and cut-and-paste the
+result back if so desired).
+
+Messages sent to and by the agent are in the following format:
+.TS
+;
+l l.
+4 bytes Length, msb first. Does not include length itself.
+1 byte Packet type. The value 255 is reserved for future extensions.
+data Any data, depending on packet type. Encoding as in the ssh packet
+protocol.
+.TE
+
+The following message types are currently defined:
+.IP "1 SSH_AGENTC_REQUEST_RSA_IDENTITIES"
+
+(no arguments)
+
+Requests the agent to send a list of all RSA keys for which it can
+answer a challenge.
+.IP "2 SSH_AGENT_RSA_IDENTITIES_ANSWER"
+.TS
+;
+l l.
+32-bit int howmany
+howmany times:
+32-bit int bits
+mp-int public exponent
+mp-int public modulus
+string comment
+.TE
+The agent sends this message in response to the to
+SSH_AGENTC_REQUEST_RSA_IDENTITIES. The answer lists all RSA keys for
+which the agent can answer a challenge. The comment field is intended
+to help identify each key; it may be printed by an application to
+indicate which key is being used. If the agent is not holding any
+keys, howmany will be zero.
+.IP "3 SSH_AGENTC_RSA_CHALLENGE
+.TS
+;
+l l.
+32-bit int bits
+mp-int public exponent
+mp-int public modulus
+mp-int challenge
+16 bytes session_id
+32-bit int response_type
+.TE
+Requests RSA decryption of random challenge to authenticate the other
+side. The challenge will be decrypted with the RSA private key
+corresponding to the given public key.
+
+The decrypted challenge must contain a zero in the highest (partial)
+byte, 2 in the next byte, followed by non-zero random bytes, a zero
+byte, and then the real challenge value in the lowermost bytes. The
+real challenge must be 32 8-bit bytes (256 bits).
+
+Response_type indicates the format of the response to be returned.
+Currently the only supported value is 1, which means to compute MD5 of
+the real challenge plus session id, and return the resulting 16 bytes
+in a SSH_AGENT_RSA_RESPONSE message.
+.IP "4 SSH_AGENT_RSA_RESPONSE"
+.TS
+;
+l l.
+16 bytes MD5 of decrypted challenge
+.TE
+Answers an RSA authentication challenge. The response is 16 bytes:
+the MD5 checksum of the 32-byte challenge.
+.IP "5 SSH_AGENT_FAILURE"
+
+(no arguments)
+
+This message is sent whenever the agent fails to answer a request
+properly. For example, if the agent cannot answer a challenge (e.g.,
+no longer has the proper key), it can respond with this. The agent
+also responds with this message if it receives a message it does not
+recognize.
+.IP "6 SSH_AGENT_SUCCESS"
+
+(no arguments)
+
+This message is sent by the agent as a response to certain requests
+that do not otherwise cause a message be sent. Currently, this is
+only sent in response to SSH_AGENTC_ADD_RSA_IDENTITY and
+SSH_AGENTC_REMOVE_RSA_IDENTITY.
+.IP "7 SSH_AGENTC_ADD_RSA_IDENTITY"
+.TS
+;
+l l.
+32-bit int bits
+mp-int public modulus
+mp-int public exponent
+mp-int private exponent
+mp-int multiplicative inverse of p mod q
+mp-int p
+mp-int q
+string comment
+.TE
+Registers an RSA key with the agent. After this request, the agent can
+use this RSA key to answer requests. The agent responds with
+SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE.
+.IP "8 SSH_AGENT_REMOVE_RSA_IDENTITY"
+.TS
+;
+l l.
+32-bit int bits
+mp-int public exponent
+mp-int public modulus
+.TE
+Removes an RSA key from the agent. The agent will no longer accept
+challenges for this key and will not list it as a supported identity.
+The agent responds with SSH_AGENT_SUCCESS or SSH_AGENT_FAILURE.
+.RT
+
+If the agent receives a message that it does not understand, it
+responds with SSH_AGENT_FAILURE. This permits compatible future
+extensions.
+
+It is possible that several clients have a connection open to the
+authentication agent simultaneously. Each client will use a separate
+connection (thus, any SSH connection can have multiple agent
+connections active simultaneously).
+
+
+.ti 0
+References
+
+.IP "[DES] "
+FIPS PUB 46-1: Data Encryption Standard. National Bureau of
+Standards, January 1988. FIPS PUB 81: DES Modes of Operation.
+National Bureau of Standards, December 1980. Bruce Schneier: Applied
+Cryptography. John Wiley & Sons, 1994. J. Seberry and J. Pieprzyk:
+Cryptography: An Introduction to Computer Security. Prentice-Hall,
+1989.
+.IP "[GZIP] "
+The GNU GZIP program; available for anonymous ftp at prep.ai.mit.edu.
+Please let me know if you know a paper describing the algorithm.
+.IP "[IDEA] "
+Xuejia Lai: On the Design and Security of Block Ciphers, ETH Series in
+Information Processing, vol. 1, Hartung-Gorre Verlag, Konstanz,
+Switzerland, 1992. Bruce Schneier: Applied Cryptography, John Wiley &
+Sons, 1994. See also the following patents: PCT/CH91/00117, EP 0 482
+154 B1, US Pat. 5,214,703.
+.IP [PKCS#1]
+PKCS #1: RSA Encryption Standard. Version 1.5, RSA Laboratories,
+November 1993. Available for anonymous ftp at ftp.rsa.com.
+.IP [POSIX]
+Portable Operating System Interface (POSIX) - Part 1: Application
+Program Interface (API) [C language], ISO/IEC 9945-1, IEEE Std 1003.1,
+1990.
+.IP [RFC0791]
+J. Postel: Internet Protocol, RFC 791, USC/ISI, September 1981.
+.IP [RFC0793]
+J. Postel: Transmission Control Protocol, RFC 793, USC/ISI, September
+1981.
+.IP [RFC1034]
+P. Mockapetris: Domain Names - Concepts and Facilities, RFC 1034,
+USC/ISI, November 1987.
+.IP [RFC1282]
+B. Kantor: BSD Rlogin, RFC 1258, UCSD, December 1991.
+.IP "[RSA] "
+Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994. See
+also R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic
+Communications System and Method. US Patent 4,405,829, 1983.
+.IP "[X11] "
+R. Scheifler: X Window System Protocol, X Consortium Standard, Version
+11, Release 6. Massachusetts Institute of Technology, Laboratory of
+Computer Science, 1994.
+.RT
+
+
+.ti 0
+Security Considerations
+
+This protocol deals with the very issue of user authentication and
+security.
+
+First of all, as an implementation issue, the server program will have
+to run as root (or equivalent) on the server machine. This is because
+the server program will need be able to change to an arbitrary user
+id. The server must also be able to create a privileged TCP/IP port.
+
+The client program will need to run as root if any variant of .rhosts
+authentication is to be used. This is because the client program will
+need to create a privileged port. The client host key is also usually
+stored in a file which is readable by root only. The client needs the
+host key in .rhosts authentication only. Root privileges can be
+dropped as soon as the privileged port has been created and the host
+key has been read.
+
+The SSH protocol offers major security advantages over existing telnet
+and rlogin protocols.
+.IP o
+IP spoofing is restricted to closing a connection (by encryption, host
+keys, and the special random cookie). If encryption is not used, IP
+spoofing is possible for those who can hear packets going out from the
+server.
+.IP o
+DNS spoofing is made ineffective (by host keys).
+.IP o
+Routing spoofing is made ineffective (by host keys).
+.IP o
+All data is encrypted with strong algorithms to make eavesdropping as
+difficult as possible. This includes encrypting any authentication
+information such as passwords. The information for decrypting session
+keys is destroyed every hour.
+.IP o
+Strong authentication methods: .rhosts combined with RSA host
+authentication, and pure RSA authentication.
+.IP o
+X11 connections and arbitrary TCP/IP ports can be forwarded securely.
+.IP o
+Man-in-the-middle attacks are deterred by using the server host key to
+encrypt the session key.
+.IP o
+Trojan horses to catch a password by routing manipulation are deterred
+by checking that the host key of the server machine matches that
+stored on the client host.
+.RT
+
+The security of SSH against man-in-the-middle attacks and the security
+of the new form of .rhosts authentication, as well as server host
+validation, depends on the integrity of the host key and the files
+containing known host keys.
+
+The host key is normally stored in a root-readable file. If the host
+key is compromised, it permits attackers to use IP, DNS and routing
+spoofing as with current rlogin and rsh. It should never be any worse
+than the current situation.
+
+The files containing known host keys are not sensitive. However, if an
+attacker gets to modify the known host key files, it has the same
+consequences as a compromised host key, because the attacker can then
+change the recorded host key.
+
+The security improvements obtained by this protocol for X11 are of
+particular significance. Previously, there has been no way to protect
+data communicated between an X server and a client running on a remote
+machine. By creating a fake display on the server, and forwarding all
+X11 requests over the secure channel, SSH can be used to run any X11
+applications securely without any cooperation with the vendors of the
+X server or the application.
+
+Finally, the security of this program relies on the strength of the
+underlying cryptographic algorithms. The RSA algorithm is used for
+authentication key exchange. It is widely believed to be secure. Of
+the algorithms used to encrypt the session, DES has a rather small key
+these days, probably permitting governments and organized criminals to
+break it in very short time with specialized hardware. 3DES is
+probably safe (but slower). IDEA is widely believed to be secure.
+People have varying degrees of confidence in the other algorithms.
+This program is not secure if used with no encryption at all.
+
+
+.ti 0
+Additional Information
+
+Additional information (especially on the implementation and mailing
+lists) is available via WWW at http://www.cs.hut.fi/ssh.
+
+Comments should be sent to Tatu Ylonen <ylo@cs.hut.fi> or the SSH
+Mailing List <ssh@clinet.fi>.
+
+.ti 0
+Author's Address
+
+.TS
+;
+l.
+Tatu Ylonen
+Helsinki University of Technology
+Otakaari 1
+FIN-02150 Espoo, Finland
+
+Phone: +358-0-451-3374
+Fax: +358-0-451-3293
+EMail: ylo@cs.hut.fi
+.TE
diff --git a/usr.bin/ssh/acconfig.h b/usr.bin/ssh/acconfig.h
new file mode 100644
index 00000000000..77aa9a688fd
--- /dev/null
+++ b/usr.bin/ssh/acconfig.h
@@ -0,0 +1,186 @@
+/*
+
+acconfig.h - template used by autoheader to create config.h.in
+config.h.in - used by autoconf to create config.h
+config.h - created by autoconf; contains defines generated by autoconf
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>
+
+*/
+
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
+
+@TOP@
+
+/* Define if you have SYSV-style /dev/ptmx and /dev/pts/. */
+#undef HAVE_DEV_PTMX
+
+/* Define if you have /dev/pts and /dev/ptc devices (as in AIX). */
+#undef HAVE_DEV_PTS_AND_PTC
+
+/* Define if you have shadow passwords in /etc/security/passwd (AIX style). */
+#undef HAVE_ETC_SECURITY_PASSWD
+
+/* Define if you have shadow passwords in /etc/security/passwd.adjunct
+ (SunOS style). */
+#undef HAVE_ETC_SECURITY_PASSWD_ADJUNCT
+
+/* Define if you have OSF1 C2 security installed on the system */
+#undef HAVE_OSF1_C2_SECURITY
+
+/* Define if you have shadow passwords in /etc/shadow (Solaris style). */
+#undef HAVE_ETC_SHADOW
+
+/* Define if you have system login defaults in /etc/default/login. */
+#undef HAVE_ETC_DEFAULT_LOGIN
+
+/* Define if utmp structure has host field. */
+#undef HAVE_HOST_IN_UTMP
+
+/* Define if utmp structure has addr field. */
+#undef HAVE_ADDR_IN_UTMP
+
+/* Define if utmp structure has id field. */
+#undef HAVE_ID_IN_UTMP
+
+/* Define if utmp structure has name field. */
+#undef HAVE_NAME_IN_UTMP
+
+/* Define if utmp structure has pid field. */
+#undef HAVE_PID_IN_UTMP
+
+/* Define if utmpx structure has ut_session. */
+#undef HAVE_UT_SESSION
+
+/* Define if utmpx structure has ut_syslen. */
+#undef HAVE_UT_SYSLEN
+
+/* Define if /var/adm/lastlog or whatever it is called is a directory
+ (e.g. SGI IRIX). */
+#undef LASTLOG_IS_DIR
+
+/* Define to use RSAREF. */
+#undef RSAREF
+
+/* Define this to be the path of the rsh program to support executing rsh. */
+#undef RSH_PATH
+
+/* Define this to be the path of the xauth program. */
+#undef XAUTH_PATH
+
+/* Default path for utmp. Determined by configure. */
+#undef SSH_UTMP
+
+/* Default path for wtmp. Determined by configure. */
+#undef SSH_WTMP
+
+/* Default path for lastlog. Determined by configure. */
+#undef SSH_LASTLOG
+
+/* This is defined if we found a lastlog file. The presence of lastlog.h
+ alone is not a sufficient indicator (at least newer BSD systems have
+ lastlog but no lastlog.h. */
+#undef HAVE_LASTLOG
+
+/* Define this if libutil.a contains BSD 4.4 compatible login(), logout(),
+ and logwtmp() calls. */
+#undef HAVE_LIBUTIL_LOGIN
+
+/* Location of system mail spool directory. */
+#undef MAIL_SPOOL_DIRECTORY
+
+/* Defined if mail goes to $HOME/newmail instead of a global mail spool. */
+#undef HAVE_TILDE_NEWMAIL
+
+/* Define this to be the default user path if you don't like the default.
+ See the --with-path=<path> configure option. */
+#undef DEFAULT_PATH
+
+/* Define this if O_NONBLOCK does not work on your system (e.g., Ultrix). */
+#undef O_NONBLOCK_BROKEN
+
+/* Define this if sys/syslog.h needs to be included in addition to syslog.h.
+ This is the case on some Ultrix versions. */
+#undef NEED_SYS_SYSLOG_H
+
+/* Define this to include IDEA encryption. */
+#undef WITH_IDEA
+
+/* Define this to include RC4 encryption. */
+#undef WITH_RC4
+
+/* Define this to include Blowfish encryption. */
+#undef WITH_BLOWFISH
+
+/* Define this to include libwrap (tcp_wrappers) support. */
+#undef LIBWRAP
+
+/* This is defined to pw_encrypt on Linux when using John Faugh's shadow
+ password implementation. */
+#undef crypt
+
+/* This is defined on 386BSD to preted we are on FreeBSD. */
+#undef __FreeBSD__
+
+/* If defines, this overrides "tty" as the terminal group. */
+#undef TTY_GROUP
+
+/* Define this if you want to support Security Dynammics SecurID
+ cards. */
+#undef HAVE_SECURID
+
+/* Define this if you are using HPSUX. HPUX uses non-standard shared
+ memory communication for X, which seems to be enabled by the display name
+ matching that of the local host. This circumvents it by using the IP
+ address instead of the host name in DISPLAY. */
+#undef HPSUX_NONSTANDARD_X11_KLUDGE
+
+/* Define this if inet_network should be used instead of inet_addr. This is
+ the case on DGUX 5.4. */
+#undef BROKEN_INET_ADDR
+
+/* Define this if your system does not like sizeof(struct sockaddr_un) as the
+ size argument in bind and connect calls for unix domain sockets. */
+#undef USE_STRLEN_FOR_AF_UNIX
+
+/* Define this to use pipes instead of socketpairs for communicating with the
+ client program. Socketpairs do not seem to work on all systems. */
+#undef USE_PIPES
+
+/* Directory containing ssh_config, ssh_known_hosts, sshd_pid, etc. Normally
+ /etc. */
+#undef ETCDIR
+
+/* Define this if speed_t is defined in stdtypes.h or otherwise gets included
+ into ttymodes.c from system headers. */
+#undef SPEED_T_IN_STDTYPES_H
+
+/* Define this if compiling with SOCKS (the firewall traversal library).
+ Also, you must define connect, getsockname, bind, accept, listen, and
+ select to their R-versions. */
+#undef SOCKS
+#undef connect
+#undef getsockname
+#undef bind
+#undef accept
+#undef listen
+#undef select
+
+/* Define these if on SCO Unix. */
+#undef HAVE_SCO_ETC_SHADOW
+#undef SCO
+
+/* Define this if you want to compile in Kerberos V4 support.
+ This can be done at configure time with the --with-krb4 argument. */
+#undef KRB4
+
+/* Define this if you want to compile in AFS support.
+ This can be done at configure time with the --with-afs argument. */
+#undef AFS
+
+/* Define this if you want to enable nonstandard krb4 TGT forwarding. */
+#undef KERBEROS_TGT_PASSING
+
+/* Define this if you want to add optional compression support. */
+#undef WITH_ZLIB
diff --git a/usr.bin/ssh/auth-krb4.c b/usr.bin/ssh/auth-krb4.c
new file mode 100644
index 00000000000..f6f1cbbce57
--- /dev/null
+++ b/usr.bin/ssh/auth-krb4.c
@@ -0,0 +1,218 @@
+/*
+
+ auth-kerberos.c
+
+ Hacked together by Dug Song <dugsong@umich.edu>.
+
+ Kerberos authentication and ticket-passing routines.
+
+*/
+
+#include "includes.h"
+#include "packet.h"
+#include "xmalloc.h"
+#include "ssh.h"
+
+#ifdef KRB4
+#include <sys/param.h>
+#include <krb.h>
+
+int ssh_tf_init(uid_t uid)
+{
+ extern char *ticket;
+ char *tkt_root = TKT_ROOT;
+ struct stat st;
+ int fd;
+
+ /* Set unique ticket string manually since we're still root. */
+ ticket = xmalloc(MAXPATHLEN);
+#ifdef AFS
+ if (lstat("/ticket", &st) != -1)
+ tkt_root = "/ticket/";
+#endif /* AFS */
+ sprintf(ticket, "%.100s%d_%d", tkt_root, uid, getpid());
+ (void) krb_set_tkt_string(ticket);
+
+ /* Make sure we own this ticket file, and we created it. */
+ if (lstat(ticket, &st) < 0 && errno == ENOENT) {
+ /* good, no ticket file exists. create it. */
+ if ((fd = open(ticket, O_RDWR|O_CREAT|O_EXCL, 0600)) != -1) {
+ close(fd);
+ return 1;
+ }
+ }
+ else {
+ /* file exists. make sure server_user owns it (e.g. just passed ticket),
+ and that it isn't a symlink, and that it is mode 600. */
+ if (st.st_mode == (S_IFREG|S_IRUSR|S_IWUSR) && st.st_uid == uid)
+ return 1;
+ }
+ /* Failure. */
+ log("WARNING: bad ticket file %.100s", ticket);
+ return 0;
+}
+
+int auth_krb4(const char *server_user, KTEXT auth, char **client)
+{
+ AUTH_DAT adat = { 0 };
+ KTEXT_ST reply;
+ char instance[INST_SZ];
+ int r, s;
+ u_long cksum;
+ Key_schedule schedule;
+ struct sockaddr_in local, foreign;
+
+ s = packet_get_connection_in();
+
+ r = sizeof(local);
+ memset(&local, 0, sizeof(local));
+ if (getsockname(s, (struct sockaddr *) &local, &r) < 0)
+ debug("getsockname failed: %.100s", strerror(errno));
+ r = sizeof(foreign);
+ memset(&foreign, 0, sizeof(foreign));
+ if (getpeername(s, (struct sockaddr *)&foreign, &r) < 0)
+ debug("getpeername failed: %.100s", strerror(errno));
+
+ instance[0] = '*'; instance[1] = 0;
+
+ /* Get the encrypted request, challenge, and session key. */
+ r = krb_rd_req(auth, KRB4_SERVICE_NAME, instance, 0, &adat, "");
+ if (r != KSUCCESS) {
+ packet_send_debug("Kerberos V4 krb_rd_req: %.100s", krb_err_txt[r]);
+ return 0;
+ }
+ des_key_sched((des_cblock *)adat.session, schedule);
+
+ *client = xmalloc(MAX_K_NAME_SZ);
+ sprintf(*client, "%.100s%.100s%.100s@%.100s", adat.pname, *adat.pinst ? "." : "",
+ adat.pinst, adat.prealm);
+
+ /* Check ~/.klogin authorization now. */
+ if (kuserok(&adat, (char *)server_user) != KSUCCESS) {
+ packet_send_debug("Kerberos V4 .klogin authorization failed!");
+ log("Kerberos V4 .klogin authorization failed for %.100s to account %.100s",
+ *client, server_user);
+ return 0;
+ }
+ /* Increment the checksum, and return it encrypted with the session key. */
+ cksum = adat.checksum + 1;
+ cksum = htonl(cksum);
+
+ /* If we can't successfully encrypt the checksum, we send back an empty
+ message, admitting our failure. */
+ if ((r = krb_mk_priv((u_char *)&cksum, reply.dat, sizeof(cksum)+1,
+ schedule, &adat.session, &local, &foreign)) < 0) {
+ packet_send_debug("Kerberos V4 mk_priv: (%d) %.100s", r, krb_err_txt[r]);
+ reply.dat[0] = 0;
+ reply.length = 0;
+ }
+ else
+ reply.length = r;
+
+ /* Clear session key. */
+ memset(&adat.session, 0, sizeof(&adat.session));
+
+ packet_start(SSH_SMSG_AUTH_KERBEROS_RESPONSE);
+ packet_put_string((char *) reply.dat, reply.length);
+ packet_send();
+ packet_write_wait();
+ return 1;
+}
+#endif /* KRB4 */
+
+#ifdef AFS
+#include <kafs.h>
+
+
+#ifdef KERBEROS_TGT_PASSING
+
+int auth_kerberos_tgt(struct passwd *pw, const char *string)
+{
+ CREDENTIALS creds;
+ extern char *ticket;
+ int r;
+
+ if (!radix_to_creds(string, &creds)) {
+ log("Protocol error decoding Kerberos V4 tgt");
+ packet_send_debug("Protocol error decoding Kerberos V4 tgt");
+ goto auth_kerberos_tgt_failure;
+ }
+ if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
+ strcpy(creds.service, "krbtgt");
+
+ if (strcmp(creds.service, "krbtgt")) {
+ log("Kerberos V4 tgt (%.100s%.100s%.100s@%.100s) rejected for uid %d",
+ creds.pname, creds.pinst[0] ? "." : "", creds.pinst, creds.realm,
+ pw->pw_uid);
+ packet_send_debug("Kerberos V4 tgt (%.100s%.100s%.100s@%.100s) rejected for uid %d",
+ creds.pname, creds.pinst[0] ? "." : "", creds.pinst,
+ creds.realm, pw->pw_uid);
+ goto auth_kerberos_tgt_failure;
+ }
+ if (!ssh_tf_init(pw->pw_uid) ||
+ (r = in_tkt(creds.pname, creds.pinst)) ||
+ (r = save_credentials(creds.service,creds.instance,creds.realm,
+ creds.session,creds.lifetime,creds.kvno,
+ &creds.ticket_st,creds.issue_date))) {
+ xfree(ticket);
+ ticket = NULL;
+ packet_send_debug("Kerberos V4 tgt refused: couldn't save credentials");
+ goto auth_kerberos_tgt_failure;
+ }
+ /* Successful authentication, passed all checks. */
+ chown(ticket, pw->pw_uid, pw->pw_gid);
+ packet_send_debug("Kerberos V4 ticket accepted (%.100s.%.100s@%.100s, %.100s%.100s%.100s@%.100s)",
+ creds.service, creds.instance, creds.realm,
+ creds.pname, creds.pinst[0] ? "." : "",
+ creds.pinst, creds.realm);
+
+ packet_start(SSH_SMSG_SUCCESS);
+ packet_send();
+ packet_write_wait();
+ return 1;
+
+auth_kerberos_tgt_failure:
+ memset(&creds, 0, sizeof(creds));
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ return 0;
+}
+#endif /* KERBEROS_TGT_PASSING */
+
+int auth_afs_token(char *server_user, uid_t uid, const char *string)
+{
+ CREDENTIALS creds;
+
+ if (!radix_to_creds(string, &creds)) {
+ log("Protocol error decoding AFS token");
+ packet_send_debug("Protocol error decoding AFS token");
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ return 0;
+ }
+ if (strncmp(creds.service, "", 1) == 0) /* backward compatibility */
+ strcpy(creds.service, "afs");
+
+ if (strncmp(creds.pname, "AFS ID ", 7) == 0)
+ uid = atoi(creds.pname + 7);
+
+ if (kafs_settoken(creds.realm, uid, &creds)) {
+ log("AFS token (%.100s@%.100s) rejected for uid %d",
+ creds.pname, creds.realm, uid);
+ packet_send_debug("AFS token (%.100s@%.100s) rejected for uid %d", creds.pname,
+ creds.realm, uid);
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ return 0;
+ }
+ packet_send_debug("AFS token accepted (%.100s@%.100s, %.100s@%.100s)", creds.service,
+ creds.realm, creds.pname, creds.realm);
+ packet_start(SSH_SMSG_SUCCESS);
+ packet_send();
+ packet_write_wait();
+ return 1;
+}
+#endif /* AFS */
diff --git a/usr.bin/ssh/auth-passwd.c b/usr.bin/ssh/auth-passwd.c
new file mode 100644
index 00000000000..10d21ca0bf9
--- /dev/null
+++ b/usr.bin/ssh/auth-passwd.c
@@ -0,0 +1,343 @@
+/*
+
+auth-passwd.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 18 05:11:38 1995 ylo
+
+Password authentication. This file contains the functions to check whether
+the password is valid for the user.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: auth-passwd.c,v 1.1 1999/09/26 20:53:33 deraadt Exp $");
+
+#ifdef HAVE_SCO_ETC_SHADOW
+# include <sys/security.h>
+# include <sys/audit.h>
+# include <prot.h>
+#else /* HAVE_SCO_ETC_SHADOW */
+#ifdef HAVE_ETC_SHADOW
+#include <shadow.h>
+#endif /* HAVE_ETC_SHADOW */
+#endif /* HAVE_SCO_ETC_SHADOW */
+#ifdef HAVE_ETC_SECURITY_PASSWD_ADJUNCT
+#include <sys/label.h>
+#include <sys/audit.h>
+#include <pwdadj.h>
+#endif /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */
+#include "packet.h"
+#include "ssh.h"
+#include "servconf.h"
+#include "xmalloc.h"
+
+#ifdef HAVE_SECURID
+/* Support for Security Dynamics SecurID card.
+ Contributed by Donald McKillican <dmckilli@qc.bell.ca>. */
+#define SECURID_USERS "/etc/securid.users"
+#include "sdi_athd.h"
+#include "sdi_size.h"
+#include "sdi_type.h"
+#include "sdacmvls.h"
+#include "sdconf.h"
+union config_record configure;
+static int securid_initialized = 0;
+#endif /* HAVE_SECURID */
+
+#ifdef KRB4
+#include <sys/param.h>
+#include <krb.h>
+extern char *ticket;
+#endif /* KRB4 */
+
+/* Tries to authenticate the user using password. Returns true if
+ authentication succeeds. */
+
+int auth_password(const char *server_user, const char *password)
+{
+ extern ServerOptions options;
+ extern char *crypt(const char *key, const char *salt);
+ struct passwd *pw;
+ char *encrypted_password;
+ char correct_passwd[200];
+
+ if (*password == '\0' && options.permit_empty_passwd == 0)
+ {
+ packet_send_debug("Server does not permit empty password login.");
+ return 0;
+ }
+
+ /* Get the encrypted password for the user. */
+ pw = getpwnam(server_user);
+ if (!pw)
+ return 0;
+
+#ifdef HAVE_SECURID
+ /* Support for Security Dynamics SecurId card.
+ Contributed by Donald McKillican <dmckilli@qc.bell.ca>. */
+#if defined(KRB4)
+ if (options.kerberos_or_local_passwd)
+#endif /* KRB4 */
+ {
+ /*
+ * the way we decide if this user is a securid user or not is
+ * to check to see if they are included in /etc/securid.users
+ */
+ int found = 0;
+ FILE *securid_users = fopen(SECURID_USERS, "r");
+ char *c;
+ char su_user[257];
+
+ if (securid_users)
+ {
+ while (fgets(su_user, sizeof(su_user), securid_users))
+ {
+ if (c = strchr(su_user, '\n'))
+ *c = '\0';
+ if (strcmp(su_user, server_user) == 0)
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+ fclose(securid_users);
+
+ if (found)
+ {
+ /* The user has a SecurID card. */
+ struct SD_CLIENT sd_dat, *sd;
+ log("SecurID authentication for %.100s required.", server_user);
+
+ /*
+ * if no pass code has been supplied, fail immediately: passing
+ * a null pass code to sd_check causes a core dump
+ */
+ if (*password == '\0')
+ {
+ log("No pass code given, authentication rejected.");
+ return 0;
+ }
+
+ sd = &sd_dat;
+ if (!securid_initialized)
+ {
+ memset(&sd_dat, 0, sizeof(sd_dat)); /* clear struct */
+ creadcfg(); /* accesses sdconf.rec */
+ if (sd_init(sd))
+ packet_disconnect("Cannot contact securid server.");
+ securid_initialized = 1;
+ }
+ return sd_check(password, server_user, sd) == ACM_OK;
+ }
+ }
+ /* If the user has no SecurID card specified, we fall to normal
+ password code. */
+#endif /* HAVE_SECURID */
+
+ /* Save the encrypted password. */
+ strncpy(correct_passwd, pw->pw_passwd, sizeof(correct_passwd));
+
+#ifdef HAVE_OSF1_C2_SECURITY
+ osf1c2_getprpwent(correct_passwd, pw->pw_name, sizeof(correct_passwd));
+#else /* HAVE_OSF1_C2_SECURITY */
+ /* If we have shadow passwords, lookup the real encrypted password from
+ the shadow file, and replace the saved encrypted password with the
+ real encrypted password. */
+#ifdef HAVE_SCO_ETC_SHADOW
+ {
+ struct pr_passwd *pr = getprpwnam(pw->pw_name);
+ pr = getprpwnam(pw->pw_name);
+ if (pr)
+ strncpy(correct_passwd, pr->ufld.fd_encrypt, sizeof(correct_passwd));
+ endprpwent();
+ }
+#else /* HAVE_SCO_ETC_SHADOW */
+#ifdef HAVE_ETC_SHADOW
+ {
+ struct spwd *sp = getspnam(pw->pw_name);
+ if (sp)
+ strncpy(correct_passwd, sp->sp_pwdp, sizeof(correct_passwd));
+ endspent();
+ }
+#else /* HAVE_ETC_SHADOW */
+#ifdef HAVE_ETC_SECURITY_PASSWD_ADJUNCT
+ {
+ struct passwd_adjunct *sp = getpwanam(pw->pw_name);
+ if (sp)
+ strncpy(correct_passwd, sp->pwa_passwd, sizeof(correct_passwd));
+ endpwaent();
+ }
+#else /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */
+#ifdef HAVE_ETC_SECURITY_PASSWD
+ {
+ FILE *f;
+ char line[1024], looking_for_user[200], *cp;
+ int found_user = 0;
+ f = fopen("/etc/security/passwd", "r");
+ if (f)
+ {
+ sprintf(looking_for_user, "%.190s:", server_user);
+ while (fgets(line, sizeof(line), f))
+ {
+ if (strchr(line, '\n'))
+ *strchr(line, '\n') = 0;
+ if (strcmp(line, looking_for_user) == 0)
+ found_user = 1;
+ else
+ if (line[0] != '\t' && line[0] != ' ')
+ found_user = 0;
+ else
+ if (found_user)
+ {
+ for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ if (strncmp(cp, "password = ", strlen("password = ")) == 0)
+ {
+ strncpy(correct_passwd, cp + strlen("password = "),
+ sizeof(correct_passwd));
+ correct_passwd[sizeof(correct_passwd) - 1] = 0;
+ break;
+ }
+ }
+ }
+ fclose(f);
+ }
+ }
+#endif /* HAVE_ETC_SECURITY_PASSWD */
+#endif /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */
+#endif /* HAVE_ETC_SHADOW */
+#endif /* HAVE_SCO_ETC_SHADOW */
+#endif /* HAVE_OSF1_C2_SECURITY */
+
+ /* Check for users with no password. */
+#if defined(KRB4)
+ if (options.kerberos_or_local_passwd)
+#endif /* KRB4 */
+ if (strcmp(password, "") == 0 && strcmp(correct_passwd, "") == 0)
+ {
+ packet_send_debug("Login permitted without a password because the account has no password.");
+ return 1; /* The user has no password and an empty password was tried. */
+ }
+
+ /* Encrypt the candidate password using the proper salt. */
+#ifdef HAVE_OSF1_C2_SECURITY
+ encrypted_password = (char *)osf1c2crypt(password,
+ (correct_passwd[0] && correct_passwd[1]) ?
+ correct_passwd : "xx");
+#else /* HAVE_OSF1_C2_SECURITY */
+#ifdef HAVE_SCO_ETC_SHADOW
+ encrypted_password = bigcrypt(password,
+ (correct_passwd[0] && correct_passwd[1]) ?
+ correct_passwd : "xx");
+#else /* HAVE_SCO_ETC_SHADOW */
+ encrypted_password = crypt(password,
+ (correct_passwd[0] && correct_passwd[1]) ?
+ correct_passwd : "xx");
+#endif /* HAVE_SCO_ETC_SHADOW */
+#endif /* HAVE_OSF1_C2_SECURITY */
+
+ /* Authentication is accepted if the encrypted passwords are identical. */
+#if defined(KRB4)
+ if (options.kerberos_or_local_passwd)
+#endif /* KRB4 */
+ if (strcmp(encrypted_password, correct_passwd) == 0)
+ return 1; /* Success */
+
+#if defined(KRB4)
+ if (options.kerberos_authentication)
+ {
+ AUTH_DAT adata;
+ KTEXT_ST tkt;
+ struct hostent *hp;
+ unsigned long faddr;
+ char localhost[MAXHOSTNAMELEN]; /* local host name */
+ char phost[INST_SZ]; /* host instance */
+ char realm[REALM_SZ]; /* local Kerberos realm */
+ int r;
+
+ /* Try Kerberos password authentication only for non-root
+ users and only if Kerberos is installed. */
+ if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
+
+ /* Set up our ticket file. */
+ if (!ssh_tf_init(pw->pw_uid)) {
+ log("Couldn't initialize Kerberos ticket file for %.100s!",
+ server_user);
+ goto kerberos_auth_failure;
+ }
+ /* Try to get TGT using our password. */
+ r = krb_get_pw_in_tkt(server_user, "", realm, "krbtgt", realm,
+ DEFAULT_TKT_LIFE, password);
+ if (r != INTK_OK) {
+ packet_send_debug("Kerberos V4 password authentication for %.100s "
+ "failed: %.100s", server_user, krb_err_txt[r]);
+ goto kerberos_auth_failure;
+ }
+ /* Successful authentication. */
+ chown(ticket, pw->pw_uid, pw->pw_gid);
+
+ (void) gethostname(localhost, sizeof(localhost));
+ (void) strncpy(phost, (char *)krb_get_phost(localhost), INST_SZ);
+ phost[INST_SZ-1] = 0;
+
+ /* Now that we have a TGT, try to get a local "rcmd" ticket to
+ ensure that we are not talking to a bogus Kerberos server. */
+ r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
+
+ if (r == KSUCCESS) {
+ if (!(hp = gethostbyname(localhost))) {
+ log("Couldn't get local host address!");
+ goto kerberos_auth_failure;
+ }
+ memmove((void *)&faddr, (void *)hp->h_addr, sizeof(faddr));
+
+ /* Verify our "rcmd" ticket. */
+ r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost, faddr, &adata, "");
+ if (r == RD_AP_UNDEC) {
+ /* Probably didn't have a srvtab on localhost. Allow login. */
+ log("Kerberos V4 TGT for %.100s unverifiable, no srvtab? "
+ "krb_rd_req: %.100s", server_user, krb_err_txt[r]);
+ }
+ else if (r != KSUCCESS) {
+ log("Kerberos V4 %.100s ticket unverifiable: %.100s",
+ KRB4_SERVICE_NAME, krb_err_txt[r]);
+ goto kerberos_auth_failure;
+ }
+ }
+ else if (r == KDC_PR_UNKNOWN) {
+ /* Allow login if no rcmd service exists, but log the error. */
+ log("Kerberos V4 TGT for %.100s unverifiable: %.100s; %.100s.%.100s "
+ "not registered, or srvtab is wrong?", server_user,
+ krb_err_txt[r], KRB4_SERVICE_NAME, phost);
+ }
+ else {
+ /* TGT is bad, forget it. Possibly spoofed. */
+ packet_send_debug("WARNING: Kerberos V4 TGT possibly spoofed for"
+ "%.100s: %.100s", server_user, krb_err_txt[r]);
+ goto kerberos_auth_failure;
+ }
+
+ /* Authentication succeeded. */
+ return 1;
+
+ kerberos_auth_failure:
+ (void) dest_tkt();
+ xfree(ticket);
+ ticket = NULL;
+ if (!options.kerberos_or_local_passwd ) return 0;
+ }
+ else /* Logging in as root or no local Kerberos realm. */
+ packet_send_debug("Unable to authenticate to Kerberos.");
+
+ /* Fall back to ordinary passwd authentication. */
+ }
+#endif /* KRB4 */
+
+ return 0; /* Fail */
+}
diff --git a/usr.bin/ssh/auth-rhosts.c b/usr.bin/ssh/auth-rhosts.c
new file mode 100644
index 00000000000..0d325bb04df
--- /dev/null
+++ b/usr.bin/ssh/auth-rhosts.c
@@ -0,0 +1,332 @@
+/*
+
+auth-rhosts.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Fri Mar 17 05:12:18 1995 ylo
+
+Rhosts authentication. This file contains code to check whether to admit
+the login based on rhosts authentication. This file also processes
+/etc/hosts.equiv.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: auth-rhosts.c,v 1.1 1999/09/26 20:53:33 deraadt Exp $");
+
+#include "packet.h"
+#include "ssh.h"
+#include "xmalloc.h"
+#include "uidswap.h"
+
+/* Returns true if the strings are equal, ignoring case (a-z only). */
+
+static int casefold_equal(const char *a, const char *b)
+{
+ unsigned char cha, chb;
+ for (; *a; a++, b++)
+ {
+ cha = *a;
+ chb = *b;
+ if (!chb)
+ return 0;
+ if (cha >= 'a' && cha <= 'z')
+ cha -= 32;
+ if (chb >= 'a' && chb <= 'z')
+ chb -= 32;
+ if (cha != chb)
+ return 0;
+ }
+ return !*b;
+}
+
+/* This function processes an rhosts-style file (.rhosts, .shosts, or
+ /etc/hosts.equiv). This returns true if authentication can be granted
+ based on the file, and returns zero otherwise. */
+
+int check_rhosts_file(const char *filename, const char *hostname,
+ const char *ipaddr, const char *client_user,
+ const char *server_user)
+{
+ FILE *f;
+ char buf[1024]; /* Must not be larger than host, user, dummy below. */
+
+ /* Open the .rhosts file. */
+ f = fopen(filename, "r");
+ if (!f)
+ return 0; /* Cannot read the .rhosts - deny access. */
+
+ /* Go through the file, checking every entry. */
+ while (fgets(buf, sizeof(buf), f))
+ {
+ /* All three must be at least as big as buf to avoid overflows. */
+ char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
+ int negated;
+
+ for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+ if (*cp == '#' || *cp == '\n' || !*cp)
+ continue;
+
+ /* NO_PLUS is supported at least on OSF/1. We skip it (we don't ever
+ support the plus syntax). */
+ if (strncmp(cp, "NO_PLUS", 7) == 0)
+ continue;
+
+ /* This should be safe because each buffer is as big as the whole
+ string, and thus cannot be overwritten. */
+ switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy))
+ {
+ case 0:
+ packet_send_debug("Found empty line in %.100s.", filename);
+ continue; /* Empty line? */
+ case 1:
+ /* Host name only. */
+ strncpy(userbuf, server_user, sizeof(userbuf));
+ userbuf[sizeof(userbuf) - 1] = 0;
+ break;
+ case 2:
+ /* Got both host and user name. */
+ break;
+ case 3:
+ packet_send_debug("Found garbage in %.100s.", filename);
+ continue; /* Extra garbage */
+ default:
+ continue; /* Weird... */
+ }
+
+ host = hostbuf;
+ user = userbuf;
+ negated = 0;
+
+ /* Process negated host names, or positive netgroups. */
+ if (host[0] == '-')
+ {
+ negated = 1;
+ host++;
+ }
+ else
+ if (host[0] == '+')
+ host++;
+
+ if (user[0] == '-')
+ {
+ negated = 1;
+ user++;
+ }
+ else
+ if (user[0] == '+')
+ user++;
+
+ /* Check for empty host/user names (particularly '+'). */
+ if (!host[0] || !user[0])
+ {
+ /* We come here if either was '+' or '-'. */
+ packet_send_debug("Ignoring wild host/user names in %.100s.",
+ filename);
+ continue;
+ }
+
+#ifdef HAVE_INNETGR
+
+ /* Verify that host name matches. */
+ if (host[0] == '@')
+ {
+ if (!innetgr(host + 1, hostname, NULL, NULL) &&
+ !innetgr(host + 1, ipaddr, NULL, NULL))
+ continue;
+ }
+ else
+ if (!casefold_equal(host, hostname) && strcmp(host, ipaddr) != 0)
+ continue; /* Different hostname. */
+
+ /* Verify that user name matches. */
+ if (user[0] == '@')
+ {
+ if (!innetgr(user + 1, NULL, client_user, NULL))
+ continue;
+ }
+ else
+ if (strcmp(user, client_user) != 0)
+ continue; /* Different username. */
+
+#else /* HAVE_INNETGR */
+
+ if (!casefold_equal(host, hostname) && strcmp(host, ipaddr) != 0)
+ continue; /* Different hostname. */
+
+ if (strcmp(user, client_user) != 0)
+ continue; /* Different username. */
+
+#endif /* HAVE_INNETGR */
+
+ /* Found the user and host. */
+ fclose(f);
+
+ /* If the entry was negated, deny access. */
+ if (negated)
+ {
+ packet_send_debug("Matched negative entry in %.100s.",
+ filename);
+ return 0;
+ }
+
+ /* Accept authentication. */
+ return 1;
+ }
+
+ /* Authentication using this file denied. */
+ fclose(f);
+ return 0;
+}
+
+/* Tries to authenticate the user using the .shosts or .rhosts file.
+ Returns true if authentication succeeds. If ignore_rhosts is
+ true, only /etc/hosts.equiv will be considered (.rhosts and .shosts
+ are ignored). */
+
+int auth_rhosts(struct passwd *pw, const char *client_user,
+ int ignore_rhosts, int strict_modes)
+{
+ char buf[1024];
+ const char *hostname, *ipaddr;
+ int port;
+ struct stat st;
+ static const char *rhosts_files[] = { ".shosts", ".rhosts", NULL };
+ unsigned int rhosts_file_index;
+
+ /* Quick check: if the user has no .shosts or .rhosts files, return failure
+ immediately without doing costly lookups from name servers. */
+ /* Switch to the user's uid. */
+ temporarily_use_uid(pw->pw_uid);
+ for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
+ rhosts_file_index++)
+ {
+ /* Check users .rhosts or .shosts. */
+ sprintf(buf, "%.500s/%.100s",
+ pw->pw_dir, rhosts_files[rhosts_file_index]);
+ if (stat(buf, &st) >= 0)
+ break;
+ }
+ /* Switch back to privileged uid. */
+ restore_uid();
+
+ if (!rhosts_files[rhosts_file_index] && stat("/etc/hosts.equiv", &st) < 0 &&
+ stat(SSH_HOSTS_EQUIV, &st) < 0)
+ return 0; /* The user has no .shosts or .rhosts file and there are no
+ system-wide files. */
+
+ /* Get the name, address, and port of the remote host. */
+ hostname = get_canonical_hostname();
+ ipaddr = get_remote_ipaddr();
+ port = get_remote_port();
+
+ /* Check that the connection comes from a privileged port.
+ Rhosts authentication only makes sense for priviledged programs.
+ Of course, if the intruder has root access on his local machine,
+ he can connect from any port. So do not use .rhosts
+ authentication from machines that you do not trust. */
+ if (port >= IPPORT_RESERVED ||
+ port < IPPORT_RESERVED / 2)
+ {
+ log("Connection from %.100s from nonpriviledged port %d",
+ hostname, port);
+ packet_send_debug("Your ssh client is not running as root.");
+ return 0;
+ }
+
+ /* If not logging in as superuser, try /etc/hosts.equiv and shosts.equiv. */
+ if (pw->pw_uid != 0)
+ {
+ if (check_rhosts_file("/etc/hosts.equiv", hostname, ipaddr, client_user,
+ pw->pw_name))
+ {
+ packet_send_debug("Accepted for %.100s [%.100s] by /etc/hosts.equiv.",
+ hostname, ipaddr);
+ return 1;
+ }
+ if (check_rhosts_file(SSH_HOSTS_EQUIV, hostname, ipaddr, client_user,
+ pw->pw_name))
+ {
+ packet_send_debug("Accepted for %.100s [%.100s] by %.100s.",
+ hostname, ipaddr, SSH_HOSTS_EQUIV);
+ return 1;
+ }
+ }
+
+ /* Check that the home directory is owned by root or the user, and is not
+ group or world writable. */
+ if (stat(pw->pw_dir, &st) < 0)
+ {
+ log("Rhosts authentication refused for %.100: no home directory %.200s",
+ pw->pw_name, pw->pw_dir);
+ packet_send_debug("Rhosts authentication refused for %.100: no home directory %.200s",
+ pw->pw_name, pw->pw_dir);
+ return 0;
+ }
+ if (strict_modes &&
+ ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+ (st.st_mode & 022) != 0))
+ {
+ log("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
+ pw->pw_name);
+ packet_send_debug("Rhosts authentication refused for %.100s: bad ownership or modes for home directory.",
+ pw->pw_name);
+ return 0;
+ }
+
+ /* Check all .rhosts files (currently .shosts and .rhosts). */
+ /* Temporarily use the user's uid. */
+ temporarily_use_uid(pw->pw_uid);
+ for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
+ rhosts_file_index++)
+ {
+ /* Check users .rhosts or .shosts. */
+ sprintf(buf, "%.500s/%.100s",
+ pw->pw_dir, rhosts_files[rhosts_file_index]);
+ if (stat(buf, &st) < 0)
+ continue; /* No such file. */
+
+ /* Make sure that the file is either owned by the user or by root,
+ and make sure it is not writable by anyone but the owner. This is
+ to help avoid novices accidentally allowing access to their account
+ by anyone. */
+ if (strict_modes &&
+ ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+ (st.st_mode & 022) != 0))
+ {
+ log("Rhosts authentication refused for %.100s: bad modes for %.200s",
+ pw->pw_name, buf);
+ packet_send_debug("Bad file modes for %.200s", buf);
+ continue;
+ }
+
+ /* Check if we have been configured to ignore .rhosts and .shosts
+ files. */
+ if (ignore_rhosts)
+ {
+ packet_send_debug("Server has been configured to ignore %.100s.",
+ rhosts_files[rhosts_file_index]);
+ continue;
+ }
+
+ /* Check if authentication is permitted by the file. */
+ if (check_rhosts_file(buf, hostname, ipaddr, client_user, pw->pw_name))
+ {
+ packet_send_debug("Accepted by %.100s.",
+ rhosts_files[rhosts_file_index]);
+ /* Restore the privileged uid. */
+ restore_uid();
+ return 1;
+ }
+ }
+
+ /* Rhosts authentication denied. */
+ /* Restore the privileged uid. */
+ restore_uid();
+ return 0;
+}
diff --git a/usr.bin/ssh/authfd.c b/usr.bin/ssh/authfd.c
new file mode 100644
index 00000000000..a09dc4c2541
--- /dev/null
+++ b/usr.bin/ssh/authfd.c
@@ -0,0 +1,669 @@
+/*
+
+authfd.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Mar 29 01:30:28 1995 ylo
+
+Functions for connecting the local authentication agent.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: authfd.c,v 1.1 1999/09/26 20:53:33 deraadt Exp $");
+
+#include "ssh.h"
+#include "rsa.h"
+#include "authfd.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "xmalloc.h"
+#include "getput.h"
+
+/* Returns the number of the authentication fd, or -1 if there is none. */
+
+int ssh_get_authentication_fd()
+{
+ const char *authfd, *authsocket;
+ int sock;
+ struct sockaddr_un sunaddr;
+
+ /* Get the file descriptor number from environment. */
+ authfd = getenv(SSH_AUTHFD_ENV_NAME);
+
+ /* Convert the value to an integer and return it if we got a value. */
+ if (authfd)
+ return atoi(authfd);
+
+ authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
+ if (!authsocket)
+ return -1;
+
+ sunaddr.sun_family = AF_UNIX;
+ strncpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ return -1;
+
+ if (connect(sock, (struct sockaddr *)&sunaddr, AF_UNIX_SIZE(sunaddr)) < 0)
+ {
+ close(sock);
+ return -1;
+ }
+
+ return sock;
+}
+
+/* Closes the agent socket if it should be closed (depends on how it was
+ obtained). The argument must have been returned by
+ ssh_get_authentication_fd(). */
+
+void ssh_close_authentication_socket(int sock)
+{
+ if (getenv(SSH_AUTHSOCKET_ENV_NAME))
+ close(sock);
+}
+
+/* Dummy alarm used to prevent waiting for connection from the
+ authentication agent indefinitely. */
+
+static RETSIGTYPE dummy_alarm_handler(int sig)
+{
+ /* Do nothing; a cought signal will just cause accept to return. */
+}
+
+/* Opens a socket to the authentication server. Returns the number of
+ that socket, or -1 if no connection could be made. */
+
+int ssh_get_authentication_connection_fd()
+{
+ int authfd;
+ int listen_sock, sock, port, addrlen;
+ int old_timeout;
+ RETSIGTYPE (*old_handler)();
+ struct sockaddr_in sin;
+ char msg[3];
+
+ /* Get the the socket number from the environment. This is the socket
+ used to obtain the real authentication socket. */
+ authfd = ssh_get_authentication_fd();
+ if (authfd == -1)
+ return -1;
+
+ /* Create a local socket for listening. */
+ listen_sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (listen_sock == -1)
+ {
+ ssh_close_authentication_socket(authfd);
+ return -1;
+ }
+
+ /* Bind the socket to random unprivileged port. */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ do
+ {
+ port = 32768 + (rand() % 30000);
+ sin.sin_port = htons(port);
+ }
+ while (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0 &&
+ errno == EADDRINUSE);
+
+ /* Start listening for connections on the socket. */
+ if (listen(listen_sock, 1) < 0)
+ {
+ error("listen: %.100s", strerror(errno));
+ close(listen_sock);
+ ssh_close_authentication_socket(authfd);
+ return -1;
+ }
+
+ /* Send a message to the authentication fd requesting the agent or its
+ local representative to connect to the given socket. Note that
+ we use send() to get the packet sent atomically (there can be several
+ clients trying to use the same authentication fd simultaneously). */
+ msg[0] = (char)SSH_AUTHFD_CONNECT;
+ PUT_16BIT(msg + 1, port);
+ if (send(authfd, msg, 3, 0) < 0)
+ {
+ shutdown(listen_sock, 2);
+ close(listen_sock);
+ ssh_close_authentication_socket(authfd);
+ return -1;
+ }
+
+ /* Setup a timeout so we won't wait for the connection indefinitely. */
+ old_timeout = alarm(120);
+ old_handler = signal(SIGALRM, dummy_alarm_handler);
+
+ /* Wait for the connection from the agent or its representative. */
+ addrlen = sizeof(sin);
+ sock = accept(listen_sock, (struct sockaddr *)&sin, &addrlen);
+
+ /* Remove the alarm (restore its old values). */
+ alarm(old_timeout);
+ signal(SIGALRM, old_handler);
+
+ /* Close the socket we used for listening. It is no longer needed.
+ (The authentication fd and the new connection still remain open.) */
+ shutdown(listen_sock, 2);
+ close(listen_sock);
+ ssh_close_authentication_socket(authfd);
+
+ return sock;
+}
+
+/* Opens and connects a private socket for communication with the
+ authentication agent. Returns the file descriptor (which must be
+ shut down and closed by the caller when no longer needed).
+ Returns NULL if an error occurred and the connection could not be
+ opened. */
+
+AuthenticationConnection *ssh_get_authentication_connection()
+{
+ AuthenticationConnection *auth;
+ int sock;
+
+ /* Get a connection to the authentication agent. */
+ sock = ssh_get_authentication_connection_fd();
+
+ /* Fail if we couldn't obtain a connection. This happens if we exited
+ due to a timeout. */
+ if (sock < 0)
+ return NULL;
+
+ /* Applocate the connection structure and initialize it. */
+ auth = xmalloc(sizeof(*auth));
+ auth->fd = sock;
+ buffer_init(&auth->packet);
+ buffer_init(&auth->identities);
+ auth->howmany = 0;
+
+ return auth;
+}
+
+/* Closes the connection to the authentication agent and frees any associated
+ memory. */
+
+void ssh_close_authentication_connection(AuthenticationConnection *ac)
+{
+ buffer_free(&ac->packet);
+ buffer_free(&ac->identities);
+ close(ac->fd);
+}
+
+/* Returns the first authentication identity held by the agent.
+ Returns true if an identity is available, 0 otherwise.
+ The caller must initialize the integers before the call, and free the
+ comment after a successful call (before calling ssh_get_next_identity). */
+
+int ssh_get_first_identity(AuthenticationConnection *auth,
+ int *bitsp, MP_INT *e, MP_INT *n, char **comment)
+{
+ unsigned char msg[8192];
+ int len, l;
+
+ /* Send a message to the agent requesting for a list of the identities
+ it can represent. */
+ msg[0] = 0;
+ msg[1] = 0;
+ msg[2] = 0;
+ msg[3] = 1;
+ msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
+ if (write(auth->fd, msg, 5) != 5)
+ {
+ error("write auth->fd: %.100s", strerror(errno));
+ return 0;
+ }
+
+ /* Read the length of the response. XXX implement timeouts here. */
+ len = 4;
+ while (len > 0)
+ {
+ l = read(auth->fd, msg + 4 - len, len);
+ if (l <= 0)
+ {
+ error("read auth->fd: %.100s", strerror(errno));
+ return 0;
+ }
+ len -= l;
+ }
+
+ /* Extract the length, and check it for sanity. (We cannot trust
+ authentication agents). */
+ len = GET_32BIT(msg);
+ if (len < 1 || len > 256*1024)
+ fatal("Authentication reply message too long: %d\n", len);
+
+ /* Read the packet itself. */
+ buffer_clear(&auth->identities);
+ while (len > 0)
+ {
+ l = len;
+ if (l > sizeof(msg))
+ l = sizeof(msg);
+ l = read(auth->fd, msg, l);
+ if (l <= 0)
+ fatal("Incomplete authentication reply.");
+ buffer_append(&auth->identities, (char *)msg, l);
+ len -= l;
+ }
+
+ /* Get message type, and verify that we got a proper answer. */
+ buffer_get(&auth->identities, (char *)msg, 1);
+ if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
+ fatal("Bad authentication reply message type: %d", msg[0]);
+
+ /* Get the number of entries in the response and check it for sanity. */
+ auth->howmany = buffer_get_int(&auth->identities);
+ if (auth->howmany > 1024)
+ fatal("Too many identities in authentication reply: %d\n", auth->howmany);
+
+ /* Return the first entry (if any). */
+ return ssh_get_next_identity(auth, bitsp, e, n, comment);
+}
+
+/* Returns the next authentication identity for the agent. Other functions
+ can be called between this and ssh_get_first_identity or two calls of this
+ function. This returns 0 if there are no more identities. The caller
+ must free comment after a successful return. */
+
+int ssh_get_next_identity(AuthenticationConnection *auth,
+ int *bitsp, MP_INT *e, MP_INT *n, char **comment)
+{
+ /* Return failure if no more entries. */
+ if (auth->howmany <= 0)
+ return 0;
+
+ /* Get the next entry from the packet. These will abort with a fatal
+ error if the packet is too short or contains corrupt data. */
+ *bitsp = buffer_get_int(&auth->identities);
+ buffer_get_mp_int(&auth->identities, e);
+ buffer_get_mp_int(&auth->identities, n);
+ *comment = buffer_get_string(&auth->identities, NULL);
+
+ /* Decrement the number of remaining entries. */
+ auth->howmany--;
+
+ return 1;
+}
+
+/* Generates a random challenge, sends it to the agent, and waits for response
+ from the agent. Returns true (non-zero) if the agent gave the correct
+ answer, zero otherwise. Response type selects the style of response
+ desired, with 0 corresponding to protocol version 1.0 (no longer supported)
+ and 1 corresponding to protocol version 1.1. */
+
+int ssh_decrypt_challenge(AuthenticationConnection *auth,
+ int bits, MP_INT *e, MP_INT *n, MP_INT *challenge,
+ unsigned char session_id[16],
+ unsigned int response_type,
+ unsigned char response[16])
+{
+ Buffer buffer;
+ unsigned char buf[8192];
+ int len, l, i;
+
+ /* Response type 0 is no longer supported. */
+ if (response_type == 0)
+ fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
+
+ /* Format a message to the agent. */
+ buf[0] = SSH_AGENTC_RSA_CHALLENGE;
+ buffer_init(&buffer);
+ buffer_append(&buffer, (char *)buf, 1);
+ buffer_put_int(&buffer, bits);
+ buffer_put_mp_int(&buffer, e);
+ buffer_put_mp_int(&buffer, n);
+ buffer_put_mp_int(&buffer, challenge);
+ buffer_append(&buffer, (char *)session_id, 16);
+ buffer_put_int(&buffer, response_type);
+
+ /* Get the length of the message, and format it in the buffer. */
+ len = buffer_len(&buffer);
+ PUT_32BIT(buf, len);
+
+ /* Send the length and then the packet to the agent. */
+ if (write(auth->fd, buf, 4) != 4 ||
+ write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
+ buffer_len(&buffer))
+ {
+ error("Error writing to authentication socket.");
+ error_cleanup:
+ buffer_free(&buffer);
+ return 0;
+ }
+
+ /* Wait for response from the agent. First read the length of the
+ response packet. */
+ len = 4;
+ while (len > 0)
+ {
+ l = read(auth->fd, buf + 4 - len, len);
+ if (l <= 0)
+ {
+ error("Error reading response length from authentication socket.");
+ goto error_cleanup;
+ }
+ len -= l;
+ }
+
+ /* Extract the length, and check it for sanity. */
+ len = GET_32BIT(buf);
+ if (len > 256*1024)
+ fatal("Authentication response too long: %d", len);
+
+ /* Read the rest of the response in tothe buffer. */
+ buffer_clear(&buffer);
+ while (len > 0)
+ {
+ l = len;
+ if (l > sizeof(buf))
+ l = sizeof(buf);
+ l = read(auth->fd, buf, l);
+ if (l <= 0)
+ {
+ error("Error reading response from authentication socket.");
+ goto error_cleanup;
+ }
+ buffer_append(&buffer, (char *)buf, l);
+ len -= l;
+ }
+
+ /* Get the type of the packet. */
+ buffer_get(&buffer, (char *)buf, 1);
+
+ /* Check for agent failure message. */
+ if (buf[0] == SSH_AGENT_FAILURE)
+ {
+ log("Agent admitted failure to authenticate using the key.");
+ goto error_cleanup;
+ }
+
+ /* Now it must be an authentication response packet. */
+ if (buf[0] != SSH_AGENT_RSA_RESPONSE)
+ fatal("Bad authentication response: %d", buf[0]);
+
+ /* Get the response from the packet. This will abort with a fatal error
+ if the packet is corrupt. */
+ for (i = 0; i < 16; i++)
+ response[i] = buffer_get_char(&buffer);
+
+ /* The buffer containing the packet is no longer needed. */
+ buffer_free(&buffer);
+
+ /* Correct answer. */
+ return 1;
+}
+
+/* Adds an identity to the authentication server. This call is not meant to
+ be used by normal applications. */
+
+int ssh_add_identity(AuthenticationConnection *auth,
+ RSAPrivateKey *key, const char *comment)
+{
+ Buffer buffer;
+ unsigned char buf[8192];
+ int len, l, type;
+
+ /* Format a message to the agent. */
+ buffer_init(&buffer);
+ buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
+ buffer_put_int(&buffer, key->bits);
+ buffer_put_mp_int(&buffer, &key->n);
+ buffer_put_mp_int(&buffer, &key->e);
+ buffer_put_mp_int(&buffer, &key->d);
+ buffer_put_mp_int(&buffer, &key->u);
+ buffer_put_mp_int(&buffer, &key->p);
+ buffer_put_mp_int(&buffer, &key->q);
+ buffer_put_string(&buffer, comment, strlen(comment));
+
+ /* Get the length of the message, and format it in the buffer. */
+ len = buffer_len(&buffer);
+ PUT_32BIT(buf, len);
+
+ /* Send the length and then the packet to the agent. */
+ if (write(auth->fd, buf, 4) != 4 ||
+ write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
+ buffer_len(&buffer))
+ {
+ error("Error writing to authentication socket.");
+ error_cleanup:
+ buffer_free(&buffer);
+ return 0;
+ }
+
+ /* Wait for response from the agent. First read the length of the
+ response packet. */
+ len = 4;
+ while (len > 0)
+ {
+ l = read(auth->fd, buf + 4 - len, len);
+ if (l <= 0)
+ {
+ error("Error reading response length from authentication socket.");
+ goto error_cleanup;
+ }
+ len -= l;
+ }
+
+ /* Extract the length, and check it for sanity. */
+ len = GET_32BIT(buf);
+ if (len > 256*1024)
+ fatal("Add identity response too long: %d", len);
+
+ /* Read the rest of the response in tothe buffer. */
+ buffer_clear(&buffer);
+ while (len > 0)
+ {
+ l = len;
+ if (l > sizeof(buf))
+ l = sizeof(buf);
+ l = read(auth->fd, buf, l);
+ if (l <= 0)
+ {
+ error("Error reading response from authentication socket.");
+ goto error_cleanup;
+ }
+ buffer_append(&buffer, (char *)buf, l);
+ len -= l;
+ }
+
+ /* Get the type of the packet. */
+ type = buffer_get_char(&buffer);
+ switch (type)
+ {
+ case SSH_AGENT_FAILURE:
+ buffer_free(&buffer);
+ return 0;
+ case SSH_AGENT_SUCCESS:
+ buffer_free(&buffer);
+ return 1;
+ default:
+ fatal("Bad response to add identity from authentication agent: %d",
+ type);
+ }
+ /*NOTREACHED*/
+ return 0;
+}
+
+/* Removes an identity from the authentication server. This call is not meant
+ to be used by normal applications. */
+
+int ssh_remove_identity(AuthenticationConnection *auth, RSAPublicKey *key)
+{
+ Buffer buffer;
+ unsigned char buf[8192];
+ int len, l, type;
+
+ /* Format a message to the agent. */
+ buffer_init(&buffer);
+ buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
+ buffer_put_int(&buffer, key->bits);
+ buffer_put_mp_int(&buffer, &key->e);
+ buffer_put_mp_int(&buffer, &key->n);
+
+ /* Get the length of the message, and format it in the buffer. */
+ len = buffer_len(&buffer);
+ PUT_32BIT(buf, len);
+
+ /* Send the length and then the packet to the agent. */
+ if (write(auth->fd, buf, 4) != 4 ||
+ write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
+ buffer_len(&buffer))
+ {
+ error("Error writing to authentication socket.");
+ error_cleanup:
+ buffer_free(&buffer);
+ return 0;
+ }
+
+ /* Wait for response from the agent. First read the length of the
+ response packet. */
+ len = 4;
+ while (len > 0)
+ {
+ l = read(auth->fd, buf + 4 - len, len);
+ if (l <= 0)
+ {
+ error("Error reading response length from authentication socket.");
+ goto error_cleanup;
+ }
+ len -= l;
+ }
+
+ /* Extract the length, and check it for sanity. */
+ len = GET_32BIT(buf);
+ if (len > 256*1024)
+ fatal("Remove identity response too long: %d", len);
+
+ /* Read the rest of the response in tothe buffer. */
+ buffer_clear(&buffer);
+ while (len > 0)
+ {
+ l = len;
+ if (l > sizeof(buf))
+ l = sizeof(buf);
+ l = read(auth->fd, buf, l);
+ if (l <= 0)
+ {
+ error("Error reading response from authentication socket.");
+ goto error_cleanup;
+ }
+ buffer_append(&buffer, (char *)buf, l);
+ len -= l;
+ }
+
+ /* Get the type of the packet. */
+ type = buffer_get_char(&buffer);
+ switch (type)
+ {
+ case SSH_AGENT_FAILURE:
+ buffer_free(&buffer);
+ return 0;
+ case SSH_AGENT_SUCCESS:
+ buffer_free(&buffer);
+ return 1;
+ default:
+ fatal("Bad response to remove identity from authentication agent: %d",
+ type);
+ }
+ /*NOTREACHED*/
+ return 0;
+}
+
+/* Removes all identities from the agent. This call is not meant
+ to be used by normal applications. */
+
+int ssh_remove_all_identities(AuthenticationConnection *auth)
+{
+ Buffer buffer;
+ unsigned char buf[8192];
+ int len, l, type;
+
+ /* Get the length of the message, and format it in the buffer. */
+ PUT_32BIT(buf, 1);
+ buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
+
+ /* Send the length and then the packet to the agent. */
+ if (write(auth->fd, buf, 5) != 5)
+ {
+ error("Error writing to authentication socket.");
+ return 0;
+ }
+
+ /* Wait for response from the agent. First read the length of the
+ response packet. */
+ len = 4;
+ while (len > 0)
+ {
+ l = read(auth->fd, buf + 4 - len, len);
+ if (l <= 0)
+ {
+ error("Error reading response length from authentication socket.");
+ return 0;
+ }
+ len -= l;
+ }
+
+ /* Extract the length, and check it for sanity. */
+ len = GET_32BIT(buf);
+ if (len > 256*1024)
+ fatal("Remove identity response too long: %d", len);
+
+ /* Read the rest of the response into the buffer. */
+ buffer_init(&buffer);
+ while (len > 0)
+ {
+ l = len;
+ if (l > sizeof(buf))
+ l = sizeof(buf);
+ l = read(auth->fd, buf, l);
+ if (l <= 0)
+ {
+ error("Error reading response from authentication socket.");
+ buffer_free(&buffer);
+ return 0;
+ }
+ buffer_append(&buffer, (char *)buf, l);
+ len -= l;
+ }
+
+ /* Get the type of the packet. */
+ type = buffer_get_char(&buffer);
+ switch (type)
+ {
+ case SSH_AGENT_FAILURE:
+ buffer_free(&buffer);
+ return 0;
+ case SSH_AGENT_SUCCESS:
+ buffer_free(&buffer);
+ return 1;
+ default:
+ fatal("Bad response to remove identity from authentication agent: %d",
+ type);
+ }
+ /*NOTREACHED*/
+ return 0;
+}
+
+/* Closes the connection to the authentication agent. */
+
+void ssh_close_authentication(AuthenticationConnection *auth)
+{
+ /* Close the connection. */
+ shutdown(auth->fd, 2);
+ close(auth->fd);
+
+ /* Free the buffers. */
+ buffer_free(&auth->packet);
+ buffer_free(&auth->identities);
+
+ /* Free the connection data structure. */
+ xfree(auth);
+}
diff --git a/usr.bin/ssh/authfd.h b/usr.bin/ssh/authfd.h
new file mode 100644
index 00000000000..77f92b85b89
--- /dev/null
+++ b/usr.bin/ssh/authfd.h
@@ -0,0 +1,109 @@
+/*
+
+authfd.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Mar 29 01:17:41 1995 ylo
+
+Functions to interface with the SSH_AUTHENTICATION_FD socket.
+
+*/
+
+/* RCSID("$Id: authfd.h,v 1.1 1999/09/26 20:53:33 deraadt Exp $"); */
+
+#ifndef AUTHFD_H
+#define AUTHFD_H
+
+#include "buffer.h"
+
+/* Message types for SSH_AUTHENTICATION_FD socket. */
+#define SSH_AUTHFD_CONNECT 0xf0
+
+/* Messages for the authentication agent connection. */
+#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
+#define SSH_AGENT_RSA_IDENTITIES_ANSWER 2
+#define SSH_AGENTC_RSA_CHALLENGE 3
+#define SSH_AGENT_RSA_RESPONSE 4
+#define SSH_AGENT_FAILURE 5
+#define SSH_AGENT_SUCCESS 6
+#define SSH_AGENTC_ADD_RSA_IDENTITY 7
+#define SSH_AGENTC_REMOVE_RSA_IDENTITY 8
+#define SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9
+
+typedef struct
+{
+ int fd;
+ Buffer packet;
+ Buffer identities;
+ int howmany;
+} AuthenticationConnection;
+
+/* Returns the number of the authentication fd, or -1 if there is none. */
+int ssh_get_authentication_fd();
+
+/* This should be called for any descriptor returned by
+ ssh_get_authentication_fd(). Depending on the way the descriptor was
+ obtained, this may close the descriptor. */
+void ssh_close_authentication_socket(int authfd);
+
+/* Opens a socket to the authentication server. Returns the number of
+ that socket, or -1 if no connection could be made. */
+int ssh_get_authentication_connection_fd();
+
+/* Opens and connects a private socket for communication with the
+ authentication agent. Returns NULL if an error occurred and the
+ connection could not be opened. The connection should be closed by
+ the caller by calling ssh_close_authentication_connection(). */
+AuthenticationConnection *ssh_get_authentication_connection();
+
+/* Closes the connection to the authentication agent and frees any associated
+ memory. */
+void ssh_close_authentication_connection(AuthenticationConnection *ac);
+
+/* Returns the first authentication identity held by the agent.
+ Returns true if an identity is available, 0 otherwise.
+ The caller must initialize the integers before the call, and free the
+ comment after a successful call (before calling ssh_get_next_identity). */
+int ssh_get_first_identity(AuthenticationConnection *connection,
+ int *bitsp, MP_INT *e, MP_INT *n, char **comment);
+
+/* Returns the next authentication identity for the agent. Other functions
+ can be called between this and ssh_get_first_identity or two calls of this
+ function. This returns 0 if there are no more identities. The caller
+ must free comment after a successful return. */
+int ssh_get_next_identity(AuthenticationConnection *connection,
+ int *bitsp, MP_INT *e, MP_INT *n, char **comment);
+
+/* Requests the agent to decrypt the given challenge. Returns true if
+ the agent claims it was able to decrypt it. */
+int ssh_decrypt_challenge(AuthenticationConnection *auth,
+ int bits, MP_INT *e, MP_INT *n, MP_INT *challenge,
+ unsigned char session_id[16],
+ unsigned int response_type,
+ unsigned char response[16]);
+
+/* Adds an identity to the authentication server. This call is not meant to
+ be used by normal applications. This returns true if the identity
+ was successfully added. */
+int ssh_add_identity(AuthenticationConnection *connection,
+ RSAPrivateKey *key, const char *comment);
+
+/* Removes the identity from the authentication server. This call is
+ not meant to be used by normal applications. This returns true if the
+ identity was successfully added. */
+int ssh_remove_identity(AuthenticationConnection *connection,
+ RSAPublicKey *key);
+
+/* Removes all identities from the authentication agent. This call is not
+ meant to be used by normal applications. This returns true if the
+ operation was successful. */
+int ssh_remove_all_identities(AuthenticationConnection *connection);
+
+/* Closes the connection to the authentication agent. */
+void ssh_close_authentication(AuthenticationConnection *connection);
+
+#endif /* AUTHFD_H */
diff --git a/usr.bin/ssh/authfile.c b/usr.bin/ssh/authfile.c
new file mode 100644
index 00000000000..3fea2d14b1f
--- /dev/null
+++ b/usr.bin/ssh/authfile.c
@@ -0,0 +1,315 @@
+/*
+
+authfile.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Mar 27 03:52:05 1995 ylo
+
+This file contains functions for reading and writing identity files, and
+for reading the passphrase from the user.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: authfile.c,v 1.1 1999/09/26 20:53:33 deraadt Exp $");
+
+#include <gmp.h>
+#include "xmalloc.h"
+#include "idea.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "cipher.h"
+#include "ssh.h"
+
+/* Version identification string for identity files. */
+#define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n"
+
+/* Saves the authentication (private) key in a file, encrypting it with
+ passphrase. The identification of the file (lowest 64 bits of n)
+ will precede the key to provide identification of the key without
+ needing a passphrase. */
+
+int save_private_key(const char *filename, const char *passphrase,
+ RSAPrivateKey *key, const char *comment,
+ RandomState *state)
+{
+ Buffer buffer, encrypted;
+ char buf[100], *cp;
+ int f, i;
+ CipherContext cipher;
+ int cipher_type;
+
+ /* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting to
+ another cipher; otherwise use SSH_AUTHFILE_CIPHER. */
+ if (strcmp(passphrase, "") == 0)
+ cipher_type = SSH_CIPHER_NONE;
+ else
+ cipher_type = SSH_AUTHFILE_CIPHER;
+
+ /* This buffer is used to built the secret part of the private key. */
+ buffer_init(&buffer);
+
+ /* Put checkbytes for checking passphrase validity. */
+ buf[0] = random_get_byte(state);
+ buf[1] = random_get_byte(state);
+ buf[2] = buf[0];
+ buf[3] = buf[1];
+ buffer_append(&buffer, buf, 4);
+
+ /* Store the private key (n and e will not be stored because they will
+ be stored in plain text, and storing them also in encrypted format
+ would just give known plaintext). */
+ buffer_put_mp_int(&buffer, &key->d);
+ buffer_put_mp_int(&buffer, &key->u);
+ buffer_put_mp_int(&buffer, &key->p);
+ buffer_put_mp_int(&buffer, &key->q);
+
+ /* Pad the part to be encrypted until its size is a multiple of 8. */
+ while (buffer_len(&buffer) % 8 != 0)
+ buffer_put_char(&buffer, 0);
+
+ /* This buffer will be used to contain the data in the file. */
+ buffer_init(&encrypted);
+
+ /* First store keyfile id string. */
+ cp = AUTHFILE_ID_STRING;
+ for (i = 0; cp[i]; i++)
+ buffer_put_char(&encrypted, cp[i]);
+ buffer_put_char(&encrypted, 0);
+
+ /* Store cipher type. */
+ buffer_put_char(&encrypted, cipher_type);
+ buffer_put_int(&encrypted, 0); /* For future extension */
+
+ /* Store public key. This will be in plain text. */
+ buffer_put_int(&encrypted, key->bits);
+ buffer_put_mp_int(&encrypted, &key->n);
+ buffer_put_mp_int(&encrypted, &key->e);
+ buffer_put_string(&encrypted, comment, strlen(comment));
+
+ /* Allocate space for the private part of the key in the buffer. */
+ buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
+
+ cipher_set_key_string(&cipher, cipher_type, passphrase, 1);
+ cipher_encrypt(&cipher, (unsigned char *)cp,
+ (unsigned char *)buffer_ptr(&buffer),
+ buffer_len(&buffer));
+ memset(&cipher, 0, sizeof(cipher));
+
+ /* Destroy temporary data. */
+ memset(buf, 0, sizeof(buf));
+ buffer_free(&buffer);
+
+ /* Write to a file. */
+ f = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0600);
+ if (f < 0)
+ return 0;
+
+ if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
+ buffer_len(&encrypted))
+ {
+ debug("Write to key file %.200s failed: %.100s", filename,
+ strerror(errno));
+ buffer_free(&encrypted);
+ close(f);
+ remove(filename);
+ return 0;
+ }
+ close(f);
+ buffer_free(&encrypted);
+ return 1;
+}
+
+/* Loads the public part of the key file. Returns 0 if an error
+ was encountered (the file does not exist or is not readable), and
+ non-zero otherwise. */
+
+int load_public_key(const char *filename, RSAPublicKey *pub,
+ char **comment_return)
+{
+ int f, i;
+ unsigned long len;
+ Buffer buffer;
+ char *cp;
+
+ /* Read data from the file into the buffer. */
+ f = open(filename, O_RDONLY);
+ if (f < 0)
+ return 0;
+
+ len = lseek(f, (off_t)0L, 2);
+ lseek(f, (off_t)0L, 0);
+
+ buffer_init(&buffer);
+ buffer_append_space(&buffer, &cp, len);
+
+ if (read(f, cp, len) != len)
+ {
+ debug("Read from key file %.200s failed: %.100s", filename,
+ strerror(errno));
+ buffer_free(&buffer);
+ close(f);
+ return 0;
+ }
+ close(f);
+
+ /* Check that it is at least big enought to contain the ID string. */
+ if (len < strlen(AUTHFILE_ID_STRING) + 1)
+ {
+ debug("Bad key file %.200s.", filename);
+ buffer_free(&buffer);
+ return 0;
+ }
+
+ /* Make sure it begins with the id string. Consume the id string from
+ the buffer. */
+ for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++)
+ if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i])
+ {
+ debug("Bad key file %.200s.", filename);
+ buffer_free(&buffer);
+ return 0;
+ }
+
+ /* Skip cipher type and reserved data. */
+ (void)buffer_get_char(&buffer); /* cipher type */
+ (void)buffer_get_int(&buffer); /* reserved */
+
+ /* Read the public key from the buffer. */
+ pub->bits = buffer_get_int(&buffer);
+ mpz_init(&pub->n);
+ buffer_get_mp_int(&buffer, &pub->n);
+ mpz_init(&pub->e);
+ buffer_get_mp_int(&buffer, &pub->e);
+ if (comment_return)
+ *comment_return = buffer_get_string(&buffer, NULL);
+ /* The encrypted private part is not parsed by this function. */
+
+ buffer_free(&buffer);
+
+ return 1;
+}
+
+/* Loads the private key from the file. Returns 0 if an error is encountered
+ (file does not exist or is not readable, or passphrase is bad).
+ This initializes the private key. */
+
+int load_private_key(const char *filename, const char *passphrase,
+ RSAPrivateKey *prv, char **comment_return)
+{
+ int f, i, check1, check2, cipher_type;
+ unsigned long len;
+ Buffer buffer, decrypted;
+ char *cp;
+ CipherContext cipher;
+
+ /* Read the file into the buffer. */
+ f = open(filename, O_RDONLY);
+ if (f < 0)
+ return 0;
+
+ len = lseek(f, (off_t)0L, 2);
+ lseek(f, (off_t)0L, 0);
+
+ buffer_init(&buffer);
+ buffer_append_space(&buffer, &cp, len);
+
+ if (read(f, cp, len) != len)
+ {
+ debug("Read from key file %.200s failed: %.100s", filename,
+ strerror(errno));
+ buffer_free(&buffer);
+ close(f);
+ return 0;
+ }
+ close(f);
+
+ /* Check that it is at least big enought to contain the ID string. */
+ if (len < strlen(AUTHFILE_ID_STRING) + 1)
+ {
+ debug("Bad key file %.200s.", filename);
+ buffer_free(&buffer);
+ return 0;
+ }
+
+ /* Make sure it begins with the id string. Consume the id string from
+ the buffer. */
+ for (i = 0; i < (unsigned int)strlen(AUTHFILE_ID_STRING) + 1; i++)
+ if (buffer_get_char(&buffer) != (unsigned char)AUTHFILE_ID_STRING[i])
+ {
+ debug("Bad key file %.200s.", filename);
+ buffer_free(&buffer);
+ return 0;
+ }
+
+ /* Read cipher type. */
+ cipher_type = buffer_get_char(&buffer);
+ (void)buffer_get_int(&buffer); /* Reserved data. */
+
+ /* Read the public key from the buffer. */
+ prv->bits = buffer_get_int(&buffer);
+ mpz_init(&prv->n);
+ buffer_get_mp_int(&buffer, &prv->n);
+ mpz_init(&prv->e);
+ buffer_get_mp_int(&buffer, &prv->e);
+ if (comment_return)
+ *comment_return = buffer_get_string(&buffer, NULL);
+ else
+ xfree(buffer_get_string(&buffer, NULL));
+
+ /* Check that it is a supported cipher. */
+ if ((cipher_mask() & (1 << cipher_type)) == 0)
+ {
+ debug("Unsupported cipher %.100s used in key file %.200s.",
+ cipher_name(cipher_type), filename);
+ buffer_free(&buffer);
+ goto fail;
+ }
+
+ /* Initialize space for decrypted data. */
+ buffer_init(&decrypted);
+ buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
+
+ /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
+ cipher_set_key_string(&cipher, cipher_type, passphrase, 0);
+ cipher_decrypt(&cipher, (unsigned char *)cp,
+ (unsigned char *)buffer_ptr(&buffer),
+ buffer_len(&buffer));
+
+ buffer_free(&buffer);
+
+ check1 = buffer_get_char(&decrypted);
+ check2 = buffer_get_char(&decrypted);
+ if (check1 != buffer_get_char(&decrypted) ||
+ check2 != buffer_get_char(&decrypted))
+ {
+ if (strcmp(passphrase, "") != 0)
+ debug("Bad passphrase supplied for key file %.200s.", filename);
+ /* Bad passphrase. */
+ buffer_free(&decrypted);
+ fail:
+ mpz_clear(&prv->n);
+ mpz_clear(&prv->e);
+ if (comment_return)
+ xfree(*comment_return);
+ return 0;
+ }
+
+ /* Read the rest of the private key. */
+ mpz_init(&prv->d);
+ buffer_get_mp_int(&decrypted, &prv->d);
+ mpz_init(&prv->u);
+ buffer_get_mp_int(&decrypted, &prv->u);
+ mpz_init(&prv->p);
+ buffer_get_mp_int(&decrypted, &prv->p);
+ mpz_init(&prv->q);
+ buffer_get_mp_int(&decrypted, &prv->q);
+
+ buffer_free(&decrypted);
+
+ return 1;
+}
diff --git a/usr.bin/ssh/bf_enc.c b/usr.bin/ssh/bf_enc.c
new file mode 100644
index 00000000000..66a8604c594
--- /dev/null
+++ b/usr.bin/ssh/bf_enc.c
@@ -0,0 +1,241 @@
+/* crypto/bf/bf_enc.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "blowfish.h"
+#include "bf_locl.h"
+
+/* Blowfish as implemented from 'Blowfish: Springer-Verlag paper'
+ * (From LECTURE NOTES IN COIMPUTER SCIENCE 809, FAST SOFTWARE ENCRYPTION,
+ * CAMBRIDGE SECURITY WORKSHOP, CAMBRIDGE, U.K., DECEMBER 9-11, 1993)
+ */
+
+#if (BF_ROUNDS != 16) && (BF_ROUNDS != 20)
+If you set BF_ROUNDS to some value other than 16 or 20, you will have
+to modify the code.
+#endif
+
+void BF_encrypt(data,key)
+BF_LONG *data;
+BF_KEY *key;
+ {
+ register BF_LONG l,r,*p,*s;
+
+ p=key->P;
+ s= &(key->S[0]);
+ l=data[0];
+ r=data[1];
+
+ l^=p[0];
+ BF_ENC(r,l,s,p[ 1]);
+ BF_ENC(l,r,s,p[ 2]);
+ BF_ENC(r,l,s,p[ 3]);
+ BF_ENC(l,r,s,p[ 4]);
+ BF_ENC(r,l,s,p[ 5]);
+ BF_ENC(l,r,s,p[ 6]);
+ BF_ENC(r,l,s,p[ 7]);
+ BF_ENC(l,r,s,p[ 8]);
+ BF_ENC(r,l,s,p[ 9]);
+ BF_ENC(l,r,s,p[10]);
+ BF_ENC(r,l,s,p[11]);
+ BF_ENC(l,r,s,p[12]);
+ BF_ENC(r,l,s,p[13]);
+ BF_ENC(l,r,s,p[14]);
+ BF_ENC(r,l,s,p[15]);
+ BF_ENC(l,r,s,p[16]);
+#if BF_ROUNDS == 20
+ BF_ENC(r,l,s,p[17]);
+ BF_ENC(l,r,s,p[18]);
+ BF_ENC(r,l,s,p[19]);
+ BF_ENC(l,r,s,p[20]);
+#endif
+ r^=p[BF_ROUNDS+1];
+
+ data[1]=l&0xffffffffL;
+ data[0]=r&0xffffffffL;
+ }
+
+#ifndef BF_DEFAULT_OPTIONS
+
+void BF_decrypt(data,key)
+BF_LONG *data;
+BF_KEY *key;
+ {
+ register BF_LONG l,r,*p,*s;
+
+ p=key->P;
+ s= &(key->S[0]);
+ l=data[0];
+ r=data[1];
+
+ l^=p[BF_ROUNDS+1];
+#if BF_ROUNDS == 20
+ BF_ENC(r,l,s,p[20]);
+ BF_ENC(l,r,s,p[19]);
+ BF_ENC(r,l,s,p[18]);
+ BF_ENC(l,r,s,p[17]);
+#endif
+ BF_ENC(r,l,s,p[16]);
+ BF_ENC(l,r,s,p[15]);
+ BF_ENC(r,l,s,p[14]);
+ BF_ENC(l,r,s,p[13]);
+ BF_ENC(r,l,s,p[12]);
+ BF_ENC(l,r,s,p[11]);
+ BF_ENC(r,l,s,p[10]);
+ BF_ENC(l,r,s,p[ 9]);
+ BF_ENC(r,l,s,p[ 8]);
+ BF_ENC(l,r,s,p[ 7]);
+ BF_ENC(r,l,s,p[ 6]);
+ BF_ENC(l,r,s,p[ 5]);
+ BF_ENC(r,l,s,p[ 4]);
+ BF_ENC(l,r,s,p[ 3]);
+ BF_ENC(r,l,s,p[ 2]);
+ BF_ENC(l,r,s,p[ 1]);
+ r^=p[0];
+
+ data[1]=l&0xffffffffL;
+ data[0]=r&0xffffffffL;
+ }
+
+void BF_cbc_encrypt(in, out, length, ks, iv, encrypt)
+unsigned char *in;
+unsigned char *out;
+long length;
+BF_KEY *ks;
+unsigned char *iv;
+int encrypt;
+ {
+ register BF_LONG tin0,tin1;
+ register BF_LONG tout0,tout1,xor0,xor1;
+ register long l=length;
+ BF_LONG tin[2];
+
+ if (encrypt)
+ {
+ n2l(iv,tout0);
+ n2l(iv,tout1);
+ iv-=8;
+ for (l-=8; l>=0; l-=8)
+ {
+ n2l(in,tin0);
+ n2l(in,tin1);
+ tin0^=tout0;
+ tin1^=tout1;
+ tin[0]=tin0;
+ tin[1]=tin1;
+ BF_encrypt(tin,ks);
+ tout0=tin[0];
+ tout1=tin[1];
+ l2n(tout0,out);
+ l2n(tout1,out);
+ }
+ if (l != -8)
+ {
+ n2ln(in,tin0,tin1,l+8);
+ tin0^=tout0;
+ tin1^=tout1;
+ tin[0]=tin0;
+ tin[1]=tin1;
+ BF_encrypt(tin,ks);
+ tout0=tin[0];
+ tout1=tin[1];
+ l2n(tout0,out);
+ l2n(tout1,out);
+ }
+ l2n(tout0,iv);
+ l2n(tout1,iv);
+ }
+ else
+ {
+ n2l(iv,xor0);
+ n2l(iv,xor1);
+ iv-=8;
+ for (l-=8; l>=0; l-=8)
+ {
+ n2l(in,tin0);
+ n2l(in,tin1);
+ tin[0]=tin0;
+ tin[1]=tin1;
+ BF_decrypt(tin,ks);
+ tout0=tin[0]^xor0;
+ tout1=tin[1]^xor1;
+ l2n(tout0,out);
+ l2n(tout1,out);
+ xor0=tin0;
+ xor1=tin1;
+ }
+ if (l != -8)
+ {
+ n2l(in,tin0);
+ n2l(in,tin1);
+ tin[0]=tin0;
+ tin[1]=tin1;
+ BF_decrypt(tin,ks);
+ tout0=tin[0]^xor0;
+ tout1=tin[1]^xor1;
+ l2nn(tout0,tout1,out,l+8);
+ xor0=tin0;
+ xor1=tin1;
+ }
+ l2n(xor0,iv);
+ l2n(xor1,iv);
+ }
+ tin0=tin1=tout0=tout1=xor0=xor1=0;
+ tin[0]=tin[1]=0;
+ }
+
+#endif
diff --git a/usr.bin/ssh/bf_locl.h b/usr.bin/ssh/bf_locl.h
new file mode 100644
index 00000000000..a5663de8cae
--- /dev/null
+++ b/usr.bin/ssh/bf_locl.h
@@ -0,0 +1,242 @@
+/* crypto/bf/bf_locl.org */
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+/* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *
+ * Always modify bf_locl.org since bf_locl.h is automatically generated from
+ * it during SSLeay configuration.
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
+
+/* Special defines which change the way the code is built depending on the
+ CPU and OS. For SGI machines you can use _MIPS_SZLONG (32 or 64) to find
+ even newer MIPS CPU's, but at the moment one size fits all for
+ optimization options. Older Sparc's work better with only UNROLL, but
+ there's no way to tell at compile time what it is you're running on */
+
+#if defined( sun ) /* Newer Sparc's */
+# define BF_PTR
+#elif defined( __ultrix ) /* Older MIPS */
+# define BF_PTR
+#elif defined( __osf1__ ) /* Alpha */
+ /* None */
+#elif defined ( _AIX ) /* RS6000 */
+ /* Unknown */
+#elif defined( __hpux ) /* HP-PA */
+ /* None */
+#elif defined( __aux ) /* 68K */
+ /* Unknown */
+#elif defined( __dgux ) /* 88K (but P6 in latest boxes) */
+ /* Unknown */
+#elif defined( __sgi ) /* Newer MIPS */
+# define BF_PTR
+#elif defined( i386 ) /* x86 boxes, should be gcc */
+#elif defined( _MSC_VER ) /* x86 boxes, Visual C */
+#endif /* Systems-specific speed defines */
+
+#undef c2l
+#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \
+ l|=((unsigned long)(*((c)++)))<< 8L, \
+ l|=((unsigned long)(*((c)++)))<<16L, \
+ l|=((unsigned long)(*((c)++)))<<24L)
+
+/* NOTE - c is not incremented as per c2l */
+#undef c2ln
+#define c2ln(c,l1,l2,n) { \
+ c+=n; \
+ l1=l2=0; \
+ switch (n) { \
+ case 8: l2 =((unsigned long)(*(--(c))))<<24L; \
+ case 7: l2|=((unsigned long)(*(--(c))))<<16L; \
+ case 6: l2|=((unsigned long)(*(--(c))))<< 8L; \
+ case 5: l2|=((unsigned long)(*(--(c)))); \
+ case 4: l1 =((unsigned long)(*(--(c))))<<24L; \
+ case 3: l1|=((unsigned long)(*(--(c))))<<16L; \
+ case 2: l1|=((unsigned long)(*(--(c))))<< 8L; \
+ case 1: l1|=((unsigned long)(*(--(c)))); \
+ } \
+ }
+
+#undef l2c
+#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>24L)&0xff))
+
+/* NOTE - c is not incremented as per l2c */
+#undef l2cn
+#define l2cn(l1,l2,c,n) { \
+ c+=n; \
+ switch (n) { \
+ case 8: *(--(c))=(unsigned char)(((l2)>>24L)&0xff); \
+ case 7: *(--(c))=(unsigned char)(((l2)>>16L)&0xff); \
+ case 6: *(--(c))=(unsigned char)(((l2)>> 8L)&0xff); \
+ case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \
+ case 4: *(--(c))=(unsigned char)(((l1)>>24L)&0xff); \
+ case 3: *(--(c))=(unsigned char)(((l1)>>16L)&0xff); \
+ case 2: *(--(c))=(unsigned char)(((l1)>> 8L)&0xff); \
+ case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \
+ } \
+ }
+
+/* NOTE - c is not incremented as per n2l */
+#define n2ln(c,l1,l2,n) { \
+ c+=n; \
+ l1=l2=0; \
+ switch (n) { \
+ case 8: l2 =((unsigned long)(*(--(c)))) ; \
+ case 7: l2|=((unsigned long)(*(--(c))))<< 8; \
+ case 6: l2|=((unsigned long)(*(--(c))))<<16; \
+ case 5: l2|=((unsigned long)(*(--(c))))<<24; \
+ case 4: l1 =((unsigned long)(*(--(c)))) ; \
+ case 3: l1|=((unsigned long)(*(--(c))))<< 8; \
+ case 2: l1|=((unsigned long)(*(--(c))))<<16; \
+ case 1: l1|=((unsigned long)(*(--(c))))<<24; \
+ } \
+ }
+
+/* NOTE - c is not incremented as per l2n */
+#define l2nn(l1,l2,c,n) { \
+ c+=n; \
+ switch (n) { \
+ case 8: *(--(c))=(unsigned char)(((l2) )&0xff); \
+ case 7: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
+ case 6: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
+ case 5: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
+ case 4: *(--(c))=(unsigned char)(((l1) )&0xff); \
+ case 3: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
+ case 2: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
+ case 1: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
+ } \
+ }
+
+#undef n2l
+#define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24L, \
+ l|=((unsigned long)(*((c)++)))<<16L, \
+ l|=((unsigned long)(*((c)++)))<< 8L, \
+ l|=((unsigned long)(*((c)++))))
+
+#undef l2n
+#define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24L)&0xff), \
+ *((c)++)=(unsigned char)(((l)>>16L)&0xff), \
+ *((c)++)=(unsigned char)(((l)>> 8L)&0xff), \
+ *((c)++)=(unsigned char)(((l) )&0xff))
+
+/* This is actually a big endian algorithm, the most significate byte
+ * is used to lookup array 0 */
+
+/* use BF_PTR2 for intel boxes,
+ * BF_PTR for sparc and MIPS/SGI
+ * use nothing for Alpha and HP.
+ */
+#if !defined(BF_PTR) && !defined(BF_PTR2)
+#undef BF_PTR
+#endif
+
+#define BF_M 0x3fc
+#define BF_0 22L
+#define BF_1 14L
+#define BF_2 6L
+#define BF_3 2L /* left shift */
+
+#if defined(BF_PTR2)
+
+/* This is basically a special pentium verson */
+#define BF_ENC(LL,R,S,P) \
+ { \
+ BF_LONG t,u,v; \
+ u=R>>BF_0; \
+ v=R>>BF_1; \
+ u&=BF_M; \
+ v&=BF_M; \
+ t= *(BF_LONG *)((unsigned char *)&(S[ 0])+u); \
+ u=R>>BF_2; \
+ t+= *(BF_LONG *)((unsigned char *)&(S[256])+v); \
+ v=R<<BF_3; \
+ u&=BF_M; \
+ v&=BF_M; \
+ t^= *(BF_LONG *)((unsigned char *)&(S[512])+u); \
+ LL^=P; \
+ t+= *(BF_LONG *)((unsigned char *)&(S[768])+v); \
+ LL^=t; \
+ }
+
+#elif defined(BF_PTR)
+
+/* This is normally very good */
+
+#define BF_ENC(LL,R,S,P) \
+ LL^=P; \
+ LL^= (((*(BF_LONG *)((unsigned char *)&(S[ 0])+((R>>BF_0)&BF_M))+ \
+ *(BF_LONG *)((unsigned char *)&(S[256])+((R>>BF_1)&BF_M)))^ \
+ *(BF_LONG *)((unsigned char *)&(S[512])+((R>>BF_2)&BF_M)))+ \
+ *(BF_LONG *)((unsigned char *)&(S[768])+((R<<BF_3)&BF_M)));
+#else
+
+/* This will always work, even on 64 bit machines and strangly enough,
+ * on the Alpha it is faster than the pointer versions (both 32 and 64
+ * versions of BF_LONG) */
+
+#define BF_ENC(LL,R,S,P) \
+ LL^=P; \
+ LL^=((( S[ (int)(R>>24L) ] + \
+ S[0x0100+((int)(R>>16L)&0xff)])^ \
+ S[0x0200+((int)(R>> 8L)&0xff)])+ \
+ S[0x0300+((int)(R )&0xff)])&0xffffffffL;
+#endif
diff --git a/usr.bin/ssh/bf_pi.h b/usr.bin/ssh/bf_pi.h
new file mode 100644
index 00000000000..417b9355385
--- /dev/null
+++ b/usr.bin/ssh/bf_pi.h
@@ -0,0 +1,325 @@
+/* crypto/bf/bf_pi.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+static BF_KEY bf_init= {
+ {
+ 0x243f6a88L, 0x85a308d3L, 0x13198a2eL, 0x03707344L,
+ 0xa4093822L, 0x299f31d0L, 0x082efa98L, 0xec4e6c89L,
+ 0x452821e6L, 0x38d01377L, 0xbe5466cfL, 0x34e90c6cL,
+ 0xc0ac29b7L, 0xc97c50ddL, 0x3f84d5b5L, 0xb5470917L,
+ 0x9216d5d9L, 0x8979fb1b
+ },{
+ 0xd1310ba6L, 0x98dfb5acL, 0x2ffd72dbL, 0xd01adfb7L,
+ 0xb8e1afedL, 0x6a267e96L, 0xba7c9045L, 0xf12c7f99L,
+ 0x24a19947L, 0xb3916cf7L, 0x0801f2e2L, 0x858efc16L,
+ 0x636920d8L, 0x71574e69L, 0xa458fea3L, 0xf4933d7eL,
+ 0x0d95748fL, 0x728eb658L, 0x718bcd58L, 0x82154aeeL,
+ 0x7b54a41dL, 0xc25a59b5L, 0x9c30d539L, 0x2af26013L,
+ 0xc5d1b023L, 0x286085f0L, 0xca417918L, 0xb8db38efL,
+ 0x8e79dcb0L, 0x603a180eL, 0x6c9e0e8bL, 0xb01e8a3eL,
+ 0xd71577c1L, 0xbd314b27L, 0x78af2fdaL, 0x55605c60L,
+ 0xe65525f3L, 0xaa55ab94L, 0x57489862L, 0x63e81440L,
+ 0x55ca396aL, 0x2aab10b6L, 0xb4cc5c34L, 0x1141e8ceL,
+ 0xa15486afL, 0x7c72e993L, 0xb3ee1411L, 0x636fbc2aL,
+ 0x2ba9c55dL, 0x741831f6L, 0xce5c3e16L, 0x9b87931eL,
+ 0xafd6ba33L, 0x6c24cf5cL, 0x7a325381L, 0x28958677L,
+ 0x3b8f4898L, 0x6b4bb9afL, 0xc4bfe81bL, 0x66282193L,
+ 0x61d809ccL, 0xfb21a991L, 0x487cac60L, 0x5dec8032L,
+ 0xef845d5dL, 0xe98575b1L, 0xdc262302L, 0xeb651b88L,
+ 0x23893e81L, 0xd396acc5L, 0x0f6d6ff3L, 0x83f44239L,
+ 0x2e0b4482L, 0xa4842004L, 0x69c8f04aL, 0x9e1f9b5eL,
+ 0x21c66842L, 0xf6e96c9aL, 0x670c9c61L, 0xabd388f0L,
+ 0x6a51a0d2L, 0xd8542f68L, 0x960fa728L, 0xab5133a3L,
+ 0x6eef0b6cL, 0x137a3be4L, 0xba3bf050L, 0x7efb2a98L,
+ 0xa1f1651dL, 0x39af0176L, 0x66ca593eL, 0x82430e88L,
+ 0x8cee8619L, 0x456f9fb4L, 0x7d84a5c3L, 0x3b8b5ebeL,
+ 0xe06f75d8L, 0x85c12073L, 0x401a449fL, 0x56c16aa6L,
+ 0x4ed3aa62L, 0x363f7706L, 0x1bfedf72L, 0x429b023dL,
+ 0x37d0d724L, 0xd00a1248L, 0xdb0fead3L, 0x49f1c09bL,
+ 0x075372c9L, 0x80991b7bL, 0x25d479d8L, 0xf6e8def7L,
+ 0xe3fe501aL, 0xb6794c3bL, 0x976ce0bdL, 0x04c006baL,
+ 0xc1a94fb6L, 0x409f60c4L, 0x5e5c9ec2L, 0x196a2463L,
+ 0x68fb6fafL, 0x3e6c53b5L, 0x1339b2ebL, 0x3b52ec6fL,
+ 0x6dfc511fL, 0x9b30952cL, 0xcc814544L, 0xaf5ebd09L,
+ 0xbee3d004L, 0xde334afdL, 0x660f2807L, 0x192e4bb3L,
+ 0xc0cba857L, 0x45c8740fL, 0xd20b5f39L, 0xb9d3fbdbL,
+ 0x5579c0bdL, 0x1a60320aL, 0xd6a100c6L, 0x402c7279L,
+ 0x679f25feL, 0xfb1fa3ccL, 0x8ea5e9f8L, 0xdb3222f8L,
+ 0x3c7516dfL, 0xfd616b15L, 0x2f501ec8L, 0xad0552abL,
+ 0x323db5faL, 0xfd238760L, 0x53317b48L, 0x3e00df82L,
+ 0x9e5c57bbL, 0xca6f8ca0L, 0x1a87562eL, 0xdf1769dbL,
+ 0xd542a8f6L, 0x287effc3L, 0xac6732c6L, 0x8c4f5573L,
+ 0x695b27b0L, 0xbbca58c8L, 0xe1ffa35dL, 0xb8f011a0L,
+ 0x10fa3d98L, 0xfd2183b8L, 0x4afcb56cL, 0x2dd1d35bL,
+ 0x9a53e479L, 0xb6f84565L, 0xd28e49bcL, 0x4bfb9790L,
+ 0xe1ddf2daL, 0xa4cb7e33L, 0x62fb1341L, 0xcee4c6e8L,
+ 0xef20cadaL, 0x36774c01L, 0xd07e9efeL, 0x2bf11fb4L,
+ 0x95dbda4dL, 0xae909198L, 0xeaad8e71L, 0x6b93d5a0L,
+ 0xd08ed1d0L, 0xafc725e0L, 0x8e3c5b2fL, 0x8e7594b7L,
+ 0x8ff6e2fbL, 0xf2122b64L, 0x8888b812L, 0x900df01cL,
+ 0x4fad5ea0L, 0x688fc31cL, 0xd1cff191L, 0xb3a8c1adL,
+ 0x2f2f2218L, 0xbe0e1777L, 0xea752dfeL, 0x8b021fa1L,
+ 0xe5a0cc0fL, 0xb56f74e8L, 0x18acf3d6L, 0xce89e299L,
+ 0xb4a84fe0L, 0xfd13e0b7L, 0x7cc43b81L, 0xd2ada8d9L,
+ 0x165fa266L, 0x80957705L, 0x93cc7314L, 0x211a1477L,
+ 0xe6ad2065L, 0x77b5fa86L, 0xc75442f5L, 0xfb9d35cfL,
+ 0xebcdaf0cL, 0x7b3e89a0L, 0xd6411bd3L, 0xae1e7e49L,
+ 0x00250e2dL, 0x2071b35eL, 0x226800bbL, 0x57b8e0afL,
+ 0x2464369bL, 0xf009b91eL, 0x5563911dL, 0x59dfa6aaL,
+ 0x78c14389L, 0xd95a537fL, 0x207d5ba2L, 0x02e5b9c5L,
+ 0x83260376L, 0x6295cfa9L, 0x11c81968L, 0x4e734a41L,
+ 0xb3472dcaL, 0x7b14a94aL, 0x1b510052L, 0x9a532915L,
+ 0xd60f573fL, 0xbc9bc6e4L, 0x2b60a476L, 0x81e67400L,
+ 0x08ba6fb5L, 0x571be91fL, 0xf296ec6bL, 0x2a0dd915L,
+ 0xb6636521L, 0xe7b9f9b6L, 0xff34052eL, 0xc5855664L,
+ 0x53b02d5dL, 0xa99f8fa1L, 0x08ba4799L, 0x6e85076aL,
+ 0x4b7a70e9L, 0xb5b32944L, 0xdb75092eL, 0xc4192623L,
+ 0xad6ea6b0L, 0x49a7df7dL, 0x9cee60b8L, 0x8fedb266L,
+ 0xecaa8c71L, 0x699a17ffL, 0x5664526cL, 0xc2b19ee1L,
+ 0x193602a5L, 0x75094c29L, 0xa0591340L, 0xe4183a3eL,
+ 0x3f54989aL, 0x5b429d65L, 0x6b8fe4d6L, 0x99f73fd6L,
+ 0xa1d29c07L, 0xefe830f5L, 0x4d2d38e6L, 0xf0255dc1L,
+ 0x4cdd2086L, 0x8470eb26L, 0x6382e9c6L, 0x021ecc5eL,
+ 0x09686b3fL, 0x3ebaefc9L, 0x3c971814L, 0x6b6a70a1L,
+ 0x687f3584L, 0x52a0e286L, 0xb79c5305L, 0xaa500737L,
+ 0x3e07841cL, 0x7fdeae5cL, 0x8e7d44ecL, 0x5716f2b8L,
+ 0xb03ada37L, 0xf0500c0dL, 0xf01c1f04L, 0x0200b3ffL,
+ 0xae0cf51aL, 0x3cb574b2L, 0x25837a58L, 0xdc0921bdL,
+ 0xd19113f9L, 0x7ca92ff6L, 0x94324773L, 0x22f54701L,
+ 0x3ae5e581L, 0x37c2dadcL, 0xc8b57634L, 0x9af3dda7L,
+ 0xa9446146L, 0x0fd0030eL, 0xecc8c73eL, 0xa4751e41L,
+ 0xe238cd99L, 0x3bea0e2fL, 0x3280bba1L, 0x183eb331L,
+ 0x4e548b38L, 0x4f6db908L, 0x6f420d03L, 0xf60a04bfL,
+ 0x2cb81290L, 0x24977c79L, 0x5679b072L, 0xbcaf89afL,
+ 0xde9a771fL, 0xd9930810L, 0xb38bae12L, 0xdccf3f2eL,
+ 0x5512721fL, 0x2e6b7124L, 0x501adde6L, 0x9f84cd87L,
+ 0x7a584718L, 0x7408da17L, 0xbc9f9abcL, 0xe94b7d8cL,
+ 0xec7aec3aL, 0xdb851dfaL, 0x63094366L, 0xc464c3d2L,
+ 0xef1c1847L, 0x3215d908L, 0xdd433b37L, 0x24c2ba16L,
+ 0x12a14d43L, 0x2a65c451L, 0x50940002L, 0x133ae4ddL,
+ 0x71dff89eL, 0x10314e55L, 0x81ac77d6L, 0x5f11199bL,
+ 0x043556f1L, 0xd7a3c76bL, 0x3c11183bL, 0x5924a509L,
+ 0xf28fe6edL, 0x97f1fbfaL, 0x9ebabf2cL, 0x1e153c6eL,
+ 0x86e34570L, 0xeae96fb1L, 0x860e5e0aL, 0x5a3e2ab3L,
+ 0x771fe71cL, 0x4e3d06faL, 0x2965dcb9L, 0x99e71d0fL,
+ 0x803e89d6L, 0x5266c825L, 0x2e4cc978L, 0x9c10b36aL,
+ 0xc6150ebaL, 0x94e2ea78L, 0xa5fc3c53L, 0x1e0a2df4L,
+ 0xf2f74ea7L, 0x361d2b3dL, 0x1939260fL, 0x19c27960L,
+ 0x5223a708L, 0xf71312b6L, 0xebadfe6eL, 0xeac31f66L,
+ 0xe3bc4595L, 0xa67bc883L, 0xb17f37d1L, 0x018cff28L,
+ 0xc332ddefL, 0xbe6c5aa5L, 0x65582185L, 0x68ab9802L,
+ 0xeecea50fL, 0xdb2f953bL, 0x2aef7dadL, 0x5b6e2f84L,
+ 0x1521b628L, 0x29076170L, 0xecdd4775L, 0x619f1510L,
+ 0x13cca830L, 0xeb61bd96L, 0x0334fe1eL, 0xaa0363cfL,
+ 0xb5735c90L, 0x4c70a239L, 0xd59e9e0bL, 0xcbaade14L,
+ 0xeecc86bcL, 0x60622ca7L, 0x9cab5cabL, 0xb2f3846eL,
+ 0x648b1eafL, 0x19bdf0caL, 0xa02369b9L, 0x655abb50L,
+ 0x40685a32L, 0x3c2ab4b3L, 0x319ee9d5L, 0xc021b8f7L,
+ 0x9b540b19L, 0x875fa099L, 0x95f7997eL, 0x623d7da8L,
+ 0xf837889aL, 0x97e32d77L, 0x11ed935fL, 0x16681281L,
+ 0x0e358829L, 0xc7e61fd6L, 0x96dedfa1L, 0x7858ba99L,
+ 0x57f584a5L, 0x1b227263L, 0x9b83c3ffL, 0x1ac24696L,
+ 0xcdb30aebL, 0x532e3054L, 0x8fd948e4L, 0x6dbc3128L,
+ 0x58ebf2efL, 0x34c6ffeaL, 0xfe28ed61L, 0xee7c3c73L,
+ 0x5d4a14d9L, 0xe864b7e3L, 0x42105d14L, 0x203e13e0L,
+ 0x45eee2b6L, 0xa3aaabeaL, 0xdb6c4f15L, 0xfacb4fd0L,
+ 0xc742f442L, 0xef6abbb5L, 0x654f3b1dL, 0x41cd2105L,
+ 0xd81e799eL, 0x86854dc7L, 0xe44b476aL, 0x3d816250L,
+ 0xcf62a1f2L, 0x5b8d2646L, 0xfc8883a0L, 0xc1c7b6a3L,
+ 0x7f1524c3L, 0x69cb7492L, 0x47848a0bL, 0x5692b285L,
+ 0x095bbf00L, 0xad19489dL, 0x1462b174L, 0x23820e00L,
+ 0x58428d2aL, 0x0c55f5eaL, 0x1dadf43eL, 0x233f7061L,
+ 0x3372f092L, 0x8d937e41L, 0xd65fecf1L, 0x6c223bdbL,
+ 0x7cde3759L, 0xcbee7460L, 0x4085f2a7L, 0xce77326eL,
+ 0xa6078084L, 0x19f8509eL, 0xe8efd855L, 0x61d99735L,
+ 0xa969a7aaL, 0xc50c06c2L, 0x5a04abfcL, 0x800bcadcL,
+ 0x9e447a2eL, 0xc3453484L, 0xfdd56705L, 0x0e1e9ec9L,
+ 0xdb73dbd3L, 0x105588cdL, 0x675fda79L, 0xe3674340L,
+ 0xc5c43465L, 0x713e38d8L, 0x3d28f89eL, 0xf16dff20L,
+ 0x153e21e7L, 0x8fb03d4aL, 0xe6e39f2bL, 0xdb83adf7L,
+ 0xe93d5a68L, 0x948140f7L, 0xf64c261cL, 0x94692934L,
+ 0x411520f7L, 0x7602d4f7L, 0xbcf46b2eL, 0xd4a20068L,
+ 0xd4082471L, 0x3320f46aL, 0x43b7d4b7L, 0x500061afL,
+ 0x1e39f62eL, 0x97244546L, 0x14214f74L, 0xbf8b8840L,
+ 0x4d95fc1dL, 0x96b591afL, 0x70f4ddd3L, 0x66a02f45L,
+ 0xbfbc09ecL, 0x03bd9785L, 0x7fac6dd0L, 0x31cb8504L,
+ 0x96eb27b3L, 0x55fd3941L, 0xda2547e6L, 0xabca0a9aL,
+ 0x28507825L, 0x530429f4L, 0x0a2c86daL, 0xe9b66dfbL,
+ 0x68dc1462L, 0xd7486900L, 0x680ec0a4L, 0x27a18deeL,
+ 0x4f3ffea2L, 0xe887ad8cL, 0xb58ce006L, 0x7af4d6b6L,
+ 0xaace1e7cL, 0xd3375fecL, 0xce78a399L, 0x406b2a42L,
+ 0x20fe9e35L, 0xd9f385b9L, 0xee39d7abL, 0x3b124e8bL,
+ 0x1dc9faf7L, 0x4b6d1856L, 0x26a36631L, 0xeae397b2L,
+ 0x3a6efa74L, 0xdd5b4332L, 0x6841e7f7L, 0xca7820fbL,
+ 0xfb0af54eL, 0xd8feb397L, 0x454056acL, 0xba489527L,
+ 0x55533a3aL, 0x20838d87L, 0xfe6ba9b7L, 0xd096954bL,
+ 0x55a867bcL, 0xa1159a58L, 0xcca92963L, 0x99e1db33L,
+ 0xa62a4a56L, 0x3f3125f9L, 0x5ef47e1cL, 0x9029317cL,
+ 0xfdf8e802L, 0x04272f70L, 0x80bb155cL, 0x05282ce3L,
+ 0x95c11548L, 0xe4c66d22L, 0x48c1133fL, 0xc70f86dcL,
+ 0x07f9c9eeL, 0x41041f0fL, 0x404779a4L, 0x5d886e17L,
+ 0x325f51ebL, 0xd59bc0d1L, 0xf2bcc18fL, 0x41113564L,
+ 0x257b7834L, 0x602a9c60L, 0xdff8e8a3L, 0x1f636c1bL,
+ 0x0e12b4c2L, 0x02e1329eL, 0xaf664fd1L, 0xcad18115L,
+ 0x6b2395e0L, 0x333e92e1L, 0x3b240b62L, 0xeebeb922L,
+ 0x85b2a20eL, 0xe6ba0d99L, 0xde720c8cL, 0x2da2f728L,
+ 0xd0127845L, 0x95b794fdL, 0x647d0862L, 0xe7ccf5f0L,
+ 0x5449a36fL, 0x877d48faL, 0xc39dfd27L, 0xf33e8d1eL,
+ 0x0a476341L, 0x992eff74L, 0x3a6f6eabL, 0xf4f8fd37L,
+ 0xa812dc60L, 0xa1ebddf8L, 0x991be14cL, 0xdb6e6b0dL,
+ 0xc67b5510L, 0x6d672c37L, 0x2765d43bL, 0xdcd0e804L,
+ 0xf1290dc7L, 0xcc00ffa3L, 0xb5390f92L, 0x690fed0bL,
+ 0x667b9ffbL, 0xcedb7d9cL, 0xa091cf0bL, 0xd9155ea3L,
+ 0xbb132f88L, 0x515bad24L, 0x7b9479bfL, 0x763bd6ebL,
+ 0x37392eb3L, 0xcc115979L, 0x8026e297L, 0xf42e312dL,
+ 0x6842ada7L, 0xc66a2b3bL, 0x12754cccL, 0x782ef11cL,
+ 0x6a124237L, 0xb79251e7L, 0x06a1bbe6L, 0x4bfb6350L,
+ 0x1a6b1018L, 0x11caedfaL, 0x3d25bdd8L, 0xe2e1c3c9L,
+ 0x44421659L, 0x0a121386L, 0xd90cec6eL, 0xd5abea2aL,
+ 0x64af674eL, 0xda86a85fL, 0xbebfe988L, 0x64e4c3feL,
+ 0x9dbc8057L, 0xf0f7c086L, 0x60787bf8L, 0x6003604dL,
+ 0xd1fd8346L, 0xf6381fb0L, 0x7745ae04L, 0xd736fcccL,
+ 0x83426b33L, 0xf01eab71L, 0xb0804187L, 0x3c005e5fL,
+ 0x77a057beL, 0xbde8ae24L, 0x55464299L, 0xbf582e61L,
+ 0x4e58f48fL, 0xf2ddfda2L, 0xf474ef38L, 0x8789bdc2L,
+ 0x5366f9c3L, 0xc8b38e74L, 0xb475f255L, 0x46fcd9b9L,
+ 0x7aeb2661L, 0x8b1ddf84L, 0x846a0e79L, 0x915f95e2L,
+ 0x466e598eL, 0x20b45770L, 0x8cd55591L, 0xc902de4cL,
+ 0xb90bace1L, 0xbb8205d0L, 0x11a86248L, 0x7574a99eL,
+ 0xb77f19b6L, 0xe0a9dc09L, 0x662d09a1L, 0xc4324633L,
+ 0xe85a1f02L, 0x09f0be8cL, 0x4a99a025L, 0x1d6efe10L,
+ 0x1ab93d1dL, 0x0ba5a4dfL, 0xa186f20fL, 0x2868f169L,
+ 0xdcb7da83L, 0x573906feL, 0xa1e2ce9bL, 0x4fcd7f52L,
+ 0x50115e01L, 0xa70683faL, 0xa002b5c4L, 0x0de6d027L,
+ 0x9af88c27L, 0x773f8641L, 0xc3604c06L, 0x61a806b5L,
+ 0xf0177a28L, 0xc0f586e0L, 0x006058aaL, 0x30dc7d62L,
+ 0x11e69ed7L, 0x2338ea63L, 0x53c2dd94L, 0xc2c21634L,
+ 0xbbcbee56L, 0x90bcb6deL, 0xebfc7da1L, 0xce591d76L,
+ 0x6f05e409L, 0x4b7c0188L, 0x39720a3dL, 0x7c927c24L,
+ 0x86e3725fL, 0x724d9db9L, 0x1ac15bb4L, 0xd39eb8fcL,
+ 0xed545578L, 0x08fca5b5L, 0xd83d7cd3L, 0x4dad0fc4L,
+ 0x1e50ef5eL, 0xb161e6f8L, 0xa28514d9L, 0x6c51133cL,
+ 0x6fd5c7e7L, 0x56e14ec4L, 0x362abfceL, 0xddc6c837L,
+ 0xd79a3234L, 0x92638212L, 0x670efa8eL, 0x406000e0L,
+ 0x3a39ce37L, 0xd3faf5cfL, 0xabc27737L, 0x5ac52d1bL,
+ 0x5cb0679eL, 0x4fa33742L, 0xd3822740L, 0x99bc9bbeL,
+ 0xd5118e9dL, 0xbf0f7315L, 0xd62d1c7eL, 0xc700c47bL,
+ 0xb78c1b6bL, 0x21a19045L, 0xb26eb1beL, 0x6a366eb4L,
+ 0x5748ab2fL, 0xbc946e79L, 0xc6a376d2L, 0x6549c2c8L,
+ 0x530ff8eeL, 0x468dde7dL, 0xd5730a1dL, 0x4cd04dc6L,
+ 0x2939bbdbL, 0xa9ba4650L, 0xac9526e8L, 0xbe5ee304L,
+ 0xa1fad5f0L, 0x6a2d519aL, 0x63ef8ce2L, 0x9a86ee22L,
+ 0xc089c2b8L, 0x43242ef6L, 0xa51e03aaL, 0x9cf2d0a4L,
+ 0x83c061baL, 0x9be96a4dL, 0x8fe51550L, 0xba645bd6L,
+ 0x2826a2f9L, 0xa73a3ae1L, 0x4ba99586L, 0xef5562e9L,
+ 0xc72fefd3L, 0xf752f7daL, 0x3f046f69L, 0x77fa0a59L,
+ 0x80e4a915L, 0x87b08601L, 0x9b09e6adL, 0x3b3ee593L,
+ 0xe990fd5aL, 0x9e34d797L, 0x2cf0b7d9L, 0x022b8b51L,
+ 0x96d5ac3aL, 0x017da67dL, 0xd1cf3ed6L, 0x7c7d2d28L,
+ 0x1f9f25cfL, 0xadf2b89bL, 0x5ad6b472L, 0x5a88f54cL,
+ 0xe029ac71L, 0xe019a5e6L, 0x47b0acfdL, 0xed93fa9bL,
+ 0xe8d3c48dL, 0x283b57ccL, 0xf8d56629L, 0x79132e28L,
+ 0x785f0191L, 0xed756055L, 0xf7960e44L, 0xe3d35e8cL,
+ 0x15056dd4L, 0x88f46dbaL, 0x03a16125L, 0x0564f0bdL,
+ 0xc3eb9e15L, 0x3c9057a2L, 0x97271aecL, 0xa93a072aL,
+ 0x1b3f6d9bL, 0x1e6321f5L, 0xf59c66fbL, 0x26dcf319L,
+ 0x7533d928L, 0xb155fdf5L, 0x03563482L, 0x8aba3cbbL,
+ 0x28517711L, 0xc20ad9f8L, 0xabcc5167L, 0xccad925fL,
+ 0x4de81751L, 0x3830dc8eL, 0x379d5862L, 0x9320f991L,
+ 0xea7a90c2L, 0xfb3e7bceL, 0x5121ce64L, 0x774fbe32L,
+ 0xa8b6e37eL, 0xc3293d46L, 0x48de5369L, 0x6413e680L,
+ 0xa2ae0810L, 0xdd6db224L, 0x69852dfdL, 0x09072166L,
+ 0xb39a460aL, 0x6445c0ddL, 0x586cdecfL, 0x1c20c8aeL,
+ 0x5bbef7ddL, 0x1b588d40L, 0xccd2017fL, 0x6bb4e3bbL,
+ 0xdda26a7eL, 0x3a59ff45L, 0x3e350a44L, 0xbcb4cdd5L,
+ 0x72eacea8L, 0xfa6484bbL, 0x8d6612aeL, 0xbf3c6f47L,
+ 0xd29be463L, 0x542f5d9eL, 0xaec2771bL, 0xf64e6370L,
+ 0x740e0d8dL, 0xe75b1357L, 0xf8721671L, 0xaf537d5dL,
+ 0x4040cb08L, 0x4eb4e2ccL, 0x34d2466aL, 0x0115af84L,
+ 0xe1b00428L, 0x95983a1dL, 0x06b89fb4L, 0xce6ea048L,
+ 0x6f3f3b82L, 0x3520ab82L, 0x011a1d4bL, 0x277227f8L,
+ 0x611560b1L, 0xe7933fdcL, 0xbb3a792bL, 0x344525bdL,
+ 0xa08839e1L, 0x51ce794bL, 0x2f32c9b7L, 0xa01fbac9L,
+ 0xe01cc87eL, 0xbcc7d1f6L, 0xcf0111c3L, 0xa1e8aac7L,
+ 0x1a908749L, 0xd44fbd9aL, 0xd0dadecbL, 0xd50ada38L,
+ 0x0339c32aL, 0xc6913667L, 0x8df9317cL, 0xe0b12b4fL,
+ 0xf79e59b7L, 0x43f5bb3aL, 0xf2d519ffL, 0x27d9459cL,
+ 0xbf97222cL, 0x15e6fc2aL, 0x0f91fc71L, 0x9b941525L,
+ 0xfae59361L, 0xceb69cebL, 0xc2a86459L, 0x12baa8d1L,
+ 0xb6c1075eL, 0xe3056a0cL, 0x10d25065L, 0xcb03a442L,
+ 0xe0ec6e0eL, 0x1698db3bL, 0x4c98a0beL, 0x3278e964L,
+ 0x9f1f9532L, 0xe0d392dfL, 0xd3a0342bL, 0x8971f21eL,
+ 0x1b0a7441L, 0x4ba3348cL, 0xc5be7120L, 0xc37632d8L,
+ 0xdf359f8dL, 0x9b992f2eL, 0xe60b6f47L, 0x0fe3f11dL,
+ 0xe54cda54L, 0x1edad891L, 0xce6279cfL, 0xcd3e7e6fL,
+ 0x1618b166L, 0xfd2c1d05L, 0x848fd2c5L, 0xf6fb2299L,
+ 0xf523f357L, 0xa6327623L, 0x93a83531L, 0x56cccd02L,
+ 0xacf08162L, 0x5a75ebb5L, 0x6e163697L, 0x88d273ccL,
+ 0xde966292L, 0x81b949d0L, 0x4c50901bL, 0x71c65614L,
+ 0xe6c6c7bdL, 0x327a140aL, 0x45e1d006L, 0xc3f27b9aL,
+ 0xc9aa53fdL, 0x62a80f00L, 0xbb25bfe2L, 0x35bdd2f6L,
+ 0x71126905L, 0xb2040222L, 0xb6cbcf7cL, 0xcd769c2bL,
+ 0x53113ec0L, 0x1640e3d3L, 0x38abbd60L, 0x2547adf0L,
+ 0xba38209cL, 0xf746ce76L, 0x77afa1c5L, 0x20756060L,
+ 0x85cbfe4eL, 0x8ae88dd8L, 0x7aaaf9b0L, 0x4cf9aa7eL,
+ 0x1948c25cL, 0x02fb8a8cL, 0x01c36ae4L, 0xd6ebe1f9L,
+ 0x90d4f869L, 0xa65cdea0L, 0x3f09252dL, 0xc208e69fL,
+ 0xb74e6132L, 0xce77e25bL, 0x578fdfe3L, 0x3ac372e6L,
+ }
+ };
+
diff --git a/usr.bin/ssh/bf_skey.c b/usr.bin/ssh/bf_skey.c
new file mode 100644
index 00000000000..86574c0acc4
--- /dev/null
+++ b/usr.bin/ssh/bf_skey.c
@@ -0,0 +1,119 @@
+/* crypto/bf/bf_skey.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "blowfish.h"
+#include "bf_locl.h"
+#include "bf_pi.h"
+
+void BF_set_key(key,len,data)
+BF_KEY *key;
+int len;
+unsigned char *data;
+ {
+ int i;
+ BF_LONG *p,ri,in[2];
+ unsigned char *d,*end;
+
+
+ memcpy((char *)key,(char *)&bf_init,sizeof(BF_KEY));
+ p=key->P;
+
+ if (len > ((BF_ROUNDS+2)*4)) len=(BF_ROUNDS+2)*4;
+
+ d=data;
+ end= &(data[len]);
+ for (i=0; i<(BF_ROUNDS+2); i++)
+ {
+ ri= *(d++);
+ if (d >= end) d=data;
+
+ ri<<=8;
+ ri|= *(d++);
+ if (d >= end) d=data;
+
+ ri<<=8;
+ ri|= *(d++);
+ if (d >= end) d=data;
+
+ ri<<=8;
+ ri|= *(d++);
+ if (d >= end) d=data;
+
+ p[i]^=ri;
+ }
+
+ in[0]=0L;
+ in[1]=0L;
+ for (i=0; i<(BF_ROUNDS+2); i+=2)
+ {
+ BF_encrypt(in,key);
+ p[i ]=in[0];
+ p[i+1]=in[1];
+ }
+
+ p=key->S;
+ for (i=0; i<4*256; i+=2)
+ {
+ BF_encrypt(in,key);
+ p[i ]=in[0];
+ p[i+1]=in[1];
+ }
+ }
+
diff --git a/usr.bin/ssh/blowfish.h b/usr.bin/ssh/blowfish.h
new file mode 100644
index 00000000000..c4a8085a29c
--- /dev/null
+++ b/usr.bin/ssh/blowfish.h
@@ -0,0 +1,116 @@
+/* crypto/bf/blowfish.h */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#ifndef HEADER_BLOWFISH_H
+#define HEADER_BLOWFISH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BF_ENCRYPT 1
+#define BF_DECRYPT 0
+
+/* If you make this 'unsigned int' the pointer variants will work on
+ * the Alpha, otherwise they will not. Strangly using the '8 byte'
+ * BF_LONG and the default 'non-pointer' inner loop is the best configuration
+ * for the Alpha */
+#define BF_LONG unsigned long
+
+#define BF_ROUNDS 16
+#define BF_BLOCK 8
+
+typedef struct bf_key_st
+ {
+ BF_LONG P[BF_ROUNDS+2];
+ BF_LONG S[4*256];
+ } BF_KEY;
+
+#ifndef NOPROTO
+
+void BF_set_key(BF_KEY *key, int len, unsigned char *data);
+void BF_ecb_encrypt(unsigned char *in,unsigned char *out,BF_KEY *key,
+ int enc);
+void BF_encrypt(BF_LONG *data,BF_KEY *key);
+void BF_decrypt(BF_LONG *data,BF_KEY *key);
+void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
+ BF_KEY *ks, unsigned char *iv, int enc);
+void BF_cfb64_encrypt(unsigned char *in, unsigned char *out, long length,
+ BF_KEY *schedule, unsigned char *ivec, int *num, int enc);
+void BF_ofb64_encrypt(unsigned char *in, unsigned char *out, long length,
+ BF_KEY *schedule, unsigned char *ivec, int *num);
+char *BF_options(void);
+
+#else
+
+void BF_set_key();
+void BF_ecb_encrypt();
+void BF_encrypt();
+void BF_decrypt();
+void BF_cbc_encrypt();
+void BF_cfb64_encrypt();
+void BF_ofb64_encrypt();
+char *BF_options();
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/usr.bin/ssh/bufaux.c b/usr.bin/ssh/bufaux.c
new file mode 100644
index 00000000000..4bc77f6684b
--- /dev/null
+++ b/usr.bin/ssh/bufaux.c
@@ -0,0 +1,170 @@
+/*
+
+bufaux.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Mar 29 02:24:47 1995 ylo
+
+Auxiliary functions for storing and retrieving various data types to/from
+Buffers.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: bufaux.c,v 1.1 1999/09/26 20:53:33 deraadt Exp $");
+
+#include "ssh.h"
+#include "gmp.h"
+#include "bufaux.h"
+#include "xmalloc.h"
+#include "getput.h"
+
+/* Stores an MP_INT in the buffer with a 2-byte msb first bit count, followed
+ by (bits+7)/8 bytes of binary data, msb first. */
+
+void buffer_put_mp_int(Buffer *buffer, MP_INT *value)
+{
+ int bits = mpz_sizeinbase(value, 2);
+ int hex_size = mpz_sizeinbase(value, 16);
+ char *buf = xmalloc(hex_size + 2);
+ int i, oi, byte;
+ char msg[2];
+
+ /* Get the value of the number in hex. Too bad that gmp does not allow
+ us to get it in binary. */
+ mpz_get_str(buf, 16, value);
+
+ /* i is "input index", oi is "output index". Both point to the same array,
+ and start from the beginning. "input index" moves twice as fast. */
+ i = 0;
+ oi = 0;
+ /* Check for an odd number of hex digits. Process the odd digit
+ separately. */
+ if (hex_size & 1)
+ {
+ sscanf(buf, "%1x", &byte);
+ buf[oi++] = byte;
+ i = 1;
+ }
+
+ /* Convert the hex number into binary representation. */
+ for (; i < hex_size; i += 2)
+ {
+ sscanf(buf + i, "%2x", &byte);
+ buf[oi++] = byte;
+ }
+
+ assert(oi == ((bits + 7) / 8));
+ /* Store the number of bits in the buffer in two bytes, msb first. */
+ PUT_16BIT(msg, bits);
+ buffer_append(buffer, msg, 2);
+ /* Store the binary data. */
+ buffer_append(buffer, buf, oi);
+ /* Clear the temporary data. */
+ memset(buf, 0, hex_size);
+ xfree(buf);
+}
+
+/* Retrieves an MP_INT from the buffer. */
+
+int buffer_get_mp_int(Buffer *buffer, MP_INT *value)
+{
+ int i, bits, bytes;
+ char *hex;
+ unsigned char buf[2];
+
+ /* Get the number for bits. */
+ buffer_get(buffer, (char *)buf, 2);
+ bits = GET_16BIT(buf);
+ /* Compute the number of binary bytes that follow. */
+ bytes = (bits + 7) / 8;
+ /* Allocate space for a corresponding hex string. */
+ hex = xmalloc(2 * bytes + 1);
+
+ /* Read and convert the binary bytes into a hex string. */
+ for (i = 0; i < bytes; i++)
+ {
+ unsigned char byte;
+ buffer_get(buffer, (char *)&byte, 1);
+ sprintf(hex + 2 * i, "%02x", byte);
+ }
+ /* Read the hex string into a mp-int. */
+ mpz_set_str(value, hex, 16);
+ /* Free the string. */
+ xfree(hex);
+ return 2 + bytes;
+}
+
+/* Returns an integer from the buffer (4 bytes, msb first). */
+
+unsigned int buffer_get_int(Buffer *buffer)
+{
+ unsigned char buf[4];
+ buffer_get(buffer, (char *)buf, 4);
+ return GET_32BIT(buf);
+}
+
+/* Stores an integer in the buffer in 4 bytes, msb first. */
+
+void buffer_put_int(Buffer *buffer, unsigned int value)
+{
+ char buf[4];
+ PUT_32BIT(buf, value);
+ buffer_append(buffer, buf, 4);
+}
+
+/* Returns an arbitrary binary string from the buffer. The string cannot
+ be longer than 256k. The returned value points to memory allocated
+ with xmalloc; it is the responsibility of the calling function to free
+ the data. If length_ptr is non-NULL, the length of the returned data
+ will be stored there. A null character will be automatically appended
+ to the returned string, and is not counted in length. */
+
+char *buffer_get_string(Buffer *buffer, unsigned int *length_ptr)
+{
+ unsigned int len;
+ char *value;
+ /* Get the length. */
+ len = buffer_get_int(buffer);
+ if (len > 256*1024)
+ fatal("Received packet with bad string length %d", len);
+ /* Allocate space for the string. Add one byte for a null character. */
+ value = xmalloc(len + 1);
+ /* Get the string. */
+ buffer_get(buffer, value, len);
+ /* Append a null character to make processing easier. */
+ value[len] = 0;
+ /* Optionally return the length of the string. */
+ if (length_ptr)
+ *length_ptr = len;
+ return value;
+}
+
+/* Stores and arbitrary binary string in the buffer. */
+
+void buffer_put_string(Buffer *buffer, const void *buf, unsigned int len)
+{
+ buffer_put_int(buffer, len);
+ buffer_append(buffer, buf, len);
+}
+
+/* Returns a character from the buffer (0 - 255). */
+
+int buffer_get_char(Buffer *buffer)
+{
+ char ch;
+ buffer_get(buffer, &ch, 1);
+ return (unsigned char)ch;
+}
+
+/* Stores a character in the buffer. */
+
+void buffer_put_char(Buffer *buffer, int value)
+{
+ char ch = value;
+ buffer_append(buffer, &ch, 1);
+}
diff --git a/usr.bin/ssh/bufaux.h b/usr.bin/ssh/bufaux.h
new file mode 100644
index 00000000000..052cb14d630
--- /dev/null
+++ b/usr.bin/ssh/bufaux.h
@@ -0,0 +1,51 @@
+/*
+
+bufaux.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Mar 29 02:18:23 1995 ylo
+
+*/
+
+/* RCSID("$Id: bufaux.h,v 1.1 1999/09/26 20:53:34 deraadt Exp $"); */
+
+#ifndef BUFAUX_H
+#define BUFAUX_H
+
+#include "buffer.h"
+
+/* Stores an MP_INT in the buffer with a 2-byte msb first bit count, followed
+ by (bits+7)/8 bytes of binary data, msb first. */
+void buffer_put_mp_int(Buffer *buffer, MP_INT *value);
+
+/* Retrieves an MP_INT from the buffer. */
+int buffer_get_mp_int(Buffer *buffer, MP_INT *value);
+
+/* Returns an integer from the buffer (4 bytes, msb first). */
+unsigned int buffer_get_int(Buffer *buffer);
+
+/* Stores an integer in the buffer in 4 bytes, msb first. */
+void buffer_put_int(Buffer *buffer, unsigned int value);
+
+/* Returns a character from the buffer (0 - 255). */
+int buffer_get_char(Buffer *buffer);
+
+/* Stores a character in the buffer. */
+void buffer_put_char(Buffer *buffer, int value);
+
+/* Returns an arbitrary binary string from the buffer. The string cannot
+ be longer than 256k. The returned value points to memory allocated
+ with xmalloc; it is the responsibility of the calling function to free
+ the data. If length_ptr is non-NULL, the length of the returned data
+ will be stored there. A null character will be automatically appended
+ to the returned string, and is not counted in length. */
+char *buffer_get_string(Buffer *buffer, unsigned int *length_ptr);
+
+/* Stores and arbitrary binary string in the buffer. */
+void buffer_put_string(Buffer *buffer, const void *buf, unsigned int len);
+
+#endif /* BUFAUX_H */
diff --git a/usr.bin/ssh/buffer.c b/usr.bin/ssh/buffer.c
new file mode 100644
index 00000000000..0e81ac43588
--- /dev/null
+++ b/usr.bin/ssh/buffer.c
@@ -0,0 +1,150 @@
+/*
+
+buffer.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 18 04:15:33 1995 ylo
+
+Functions for manipulating fifo buffers (that can grow if needed).
+
+*/
+
+#include "includes.h"
+RCSID("$Id: buffer.c,v 1.1 1999/09/26 20:53:34 deraadt Exp $");
+
+#include "xmalloc.h"
+#include "buffer.h"
+#include "ssh.h"
+
+/* Initializes the buffer structure. */
+
+void buffer_init(Buffer *buffer)
+{
+ buffer->alloc = 4096;
+ buffer->buf = xmalloc(buffer->alloc);
+ buffer->offset = 0;
+ buffer->end = 0;
+}
+
+/* Frees any memory used for the buffer. */
+
+void buffer_free(Buffer *buffer)
+{
+ memset(buffer->buf, 0, buffer->alloc);
+ xfree(buffer->buf);
+}
+
+/* Clears any data from the buffer, making it empty. This does not actually
+ zero the memory. */
+
+void buffer_clear(Buffer *buffer)
+{
+ buffer->offset = 0;
+ buffer->end = 0;
+}
+
+/* Appends data to the buffer, expanding it if necessary. */
+
+void buffer_append(Buffer *buffer, const char *data, unsigned int len)
+{
+ char *cp;
+ buffer_append_space(buffer, &cp, len);
+ memcpy(cp, data, len);
+}
+
+/* Appends space to the buffer, expanding the buffer if necessary.
+ This does not actually copy the data into the buffer, but instead
+ returns a pointer to the allocated region. */
+
+void buffer_append_space(Buffer *buffer, char **datap, unsigned int len)
+{
+ /* If the buffer is empty, start using it from the beginning. */
+ if (buffer->offset == buffer->end)
+ {
+ buffer->offset = 0;
+ buffer->end = 0;
+ }
+
+ restart:
+ /* If there is enough space to store all data, store it now. */
+ if (buffer->end + len < buffer->alloc)
+ {
+ *datap = buffer->buf + buffer->end;
+ buffer->end += len;
+ return;
+ }
+
+ /* If the buffer is quite empty, but all data is at the end, move the
+ data to the beginning and retry. */
+ if (buffer->offset > buffer->alloc / 2)
+ {
+ memmove(buffer->buf, buffer->buf + buffer->offset,
+ buffer->end - buffer->offset);
+ buffer->end -= buffer->offset;
+ buffer->offset = 0;
+ goto restart;
+ }
+
+ /* Increase the size of the buffer and retry. */
+ buffer->alloc += len + 32768;
+ buffer->buf = xrealloc(buffer->buf, buffer->alloc);
+ goto restart;
+}
+
+/* Returns the number of bytes of data in the buffer. */
+
+unsigned int buffer_len(Buffer *buffer)
+{
+ return buffer->end - buffer->offset;
+}
+
+/* Gets data from the beginning of the buffer. */
+
+void buffer_get(Buffer *buffer, char *buf, unsigned int len)
+{
+ if (len > buffer->end - buffer->offset)
+ fatal("buffer_get trying to get more bytes than in buffer");
+ memcpy(buf, buffer->buf + buffer->offset, len);
+ buffer->offset += len;
+}
+
+/* Consumes the given number of bytes from the beginning of the buffer. */
+
+void buffer_consume(Buffer *buffer, unsigned int bytes)
+{
+ if (bytes > buffer->end - buffer->offset)
+ fatal("buffer_get trying to get more bytes than in buffer");
+ buffer->offset += bytes;
+}
+
+/* Consumes the given number of bytes from the end of the buffer. */
+
+void buffer_consume_end(Buffer *buffer, unsigned int bytes)
+{
+ if (bytes > buffer->end - buffer->offset)
+ fatal("buffer_get trying to get more bytes than in buffer");
+ buffer->end -= bytes;
+}
+
+/* Returns a pointer to the first used byte in the buffer. */
+
+char *buffer_ptr(Buffer *buffer)
+{
+ return buffer->buf + buffer->offset;
+}
+
+/* Dumps the contents of the buffer to stderr. */
+
+void buffer_dump(Buffer *buffer)
+{
+ int i;
+ unsigned char *ucp = (unsigned char *)buffer->buf;
+
+ for (i = buffer->offset; i < buffer->end; i++)
+ fprintf(stderr, " %02x", ucp[i]);
+ fprintf(stderr, "\n");
+}
diff --git a/usr.bin/ssh/buffer.h b/usr.bin/ssh/buffer.h
new file mode 100644
index 00000000000..f2bdac29651
--- /dev/null
+++ b/usr.bin/ssh/buffer.h
@@ -0,0 +1,66 @@
+/*
+
+buffer.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 18 04:12:25 1995 ylo
+
+Code for manipulating FIFO buffers.
+
+*/
+
+/* RCSID("$Id: buffer.h,v 1.1 1999/09/26 20:53:34 deraadt Exp $"); */
+
+#ifndef BUFFER_H
+#define BUFFER_H
+
+typedef struct
+{
+ char *buf; /* Buffer for data. */
+ unsigned int alloc; /* Number of bytes allocated for data. */
+ unsigned int offset; /* Offset of first byte containing data. */
+ unsigned int end; /* Offset of last byte containing data. */
+} Buffer;
+
+/* Initializes the buffer structure. */
+void buffer_init(Buffer *buffer);
+
+/* Frees any memory used for the buffer. */
+void buffer_free(Buffer *buffer);
+
+/* Clears any data from the buffer, making it empty. This does not actually
+ zero the memory. */
+void buffer_clear(Buffer *buffer);
+
+/* Appends data to the buffer, expanding it if necessary. */
+void buffer_append(Buffer *buffer, const char *data, unsigned int len);
+
+/* Appends space to the buffer, expanding the buffer if necessary.
+ This does not actually copy the data into the buffer, but instead
+ returns a pointer to the allocated region. */
+void buffer_append_space(Buffer *buffer, char **datap, unsigned int len);
+
+/* Returns the number of bytes of data in the buffer. */
+unsigned int buffer_len(Buffer *buffer);
+
+/* Gets data from the beginning of the buffer. */
+void buffer_get(Buffer *buffer, char *buf, unsigned int len);
+
+/* Consumes the given number of bytes from the beginning of the buffer. */
+void buffer_consume(Buffer *buffer, unsigned int bytes);
+
+/* Consumes the given number of bytes from the end of the buffer. */
+void buffer_consume_end(Buffer *buffer, unsigned int bytes);
+
+/* Returns a pointer to the first used byte in the buffer. */
+char *buffer_ptr(Buffer *buffer);
+
+/* Dumps the contents of the buffer to stderr in hex. This intended for
+ debugging purposes only. */
+void buffer_dump(Buffer *buffer);
+
+#endif /* BUFFER_H */
diff --git a/usr.bin/ssh/canohost.c b/usr.bin/ssh/canohost.c
new file mode 100644
index 00000000000..a30fbde7058
--- /dev/null
+++ b/usr.bin/ssh/canohost.c
@@ -0,0 +1,237 @@
+/*
+
+canohost.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sun Jul 2 17:52:22 1995 ylo
+
+Functions for returning the canonical host name of the remote site.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: canohost.c,v 1.1 1999/09/26 20:53:34 deraadt Exp $");
+
+#include "packet.h"
+#include "xmalloc.h"
+#include "ssh.h"
+
+/* Return the canonical name of the host at the other end of the socket.
+ The caller should free the returned string with xfree. */
+
+char *get_remote_hostname(int socket)
+{
+ struct sockaddr_in from;
+ int fromlen, i;
+ struct hostent *hp;
+ char name[512];
+
+ /* Get IP address of client. */
+ fromlen = sizeof(from);
+ memset(&from, 0, sizeof(from));
+ if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
+ {
+ error("getpeername failed: %.100s", strerror(errno));
+ strcpy(name, "UNKNOWN");
+ goto check_ip_options;
+ }
+
+ /* Map the IP address to a host name. */
+ hp = gethostbyaddr((char *)&from.sin_addr, sizeof(struct in_addr),
+ from.sin_family);
+ if (hp)
+ {
+ /* Got host name, find canonic host name. */
+ if (strchr(hp->h_name, '.') != 0)
+ strncpy(name, hp->h_name, sizeof(name));
+ else if (hp->h_aliases != 0
+ && hp->h_aliases[0] != 0
+ && strchr(hp->h_aliases[0], '.') != 0)
+ strncpy(name, hp->h_aliases[0], sizeof(name));
+ else
+ strncpy(name, hp->h_name, sizeof(name));
+ name[sizeof(name) - 1] = '\0';
+
+ /* Convert it to all lowercase (which is expected by the rest of this
+ software). */
+ for (i = 0; name[i]; i++)
+ if (isupper(name[i]))
+ name[i] = tolower(name[i]);
+
+ /* Map it back to an IP address and check that the given address actually
+ is an address of this host. This is necessary because anyone with
+ access to a name server can define arbitrary names for an IP address.
+ Mapping from name to IP address can be trusted better (but can still
+ be fooled if the intruder has access to the name server of the
+ domain). */
+ hp = gethostbyname(name);
+ if (!hp)
+ {
+ log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
+ strcpy(name, inet_ntoa(from.sin_addr));
+ goto check_ip_options;
+ }
+ /* Look for the address from the list of addresses. */
+ for (i = 0; hp->h_addr_list[i]; i++)
+ if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
+ == 0)
+ break;
+ /* If we reached the end of the list, the address was not there. */
+ if (!hp->h_addr_list[i])
+ {
+ /* Address not found for the host name. */
+ log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
+ inet_ntoa(from.sin_addr), name);
+ strcpy(name, inet_ntoa(from.sin_addr));
+ goto check_ip_options;
+ }
+ /* Address was found for the host name. We accept the host name. */
+ }
+ else
+ {
+ /* Host name not found. Use ascii representation of the address. */
+ strcpy(name, inet_ntoa(from.sin_addr));
+ log("Could not reverse map address %.100s.", name);
+ }
+
+ check_ip_options:
+
+#ifdef IP_OPTIONS
+ /* If IP options are supported, make sure there are none (log and clear
+ them if any are found). Basically we are worried about source routing;
+ it can be used to pretend you are somebody (ip-address) you are not.
+ That itself may be "almost acceptable" under certain circumstances,
+ but rhosts autentication is useless if source routing is accepted.
+ Notice also that if we just dropped source routing here, the other
+ side could use IP spoofing to do rest of the interaction and could still
+ bypass security. So we exit here if we detect any IP options. */
+ {
+ unsigned char options[200], *ucp;
+ char text[1024], *cp;
+ int option_size, ipproto;
+ struct protoent *ip;
+
+ if ((ip = getprotobyname("ip")) != NULL)
+ ipproto = ip->p_proto;
+ else
+ ipproto = IPPROTO_IP;
+ option_size = sizeof(options);
+ if (getsockopt(0, ipproto, IP_OPTIONS, (char *)options,
+ &option_size) >= 0 && option_size != 0)
+ {
+ cp = text;
+ /* Note: "text" buffer must be at least 3x as big as options. */
+ for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
+ sprintf(cp, " %2.2x", *ucp);
+ log("Connection from %.100s with IP options:%.800s",
+ inet_ntoa(from.sin_addr), text);
+ packet_disconnect("Connection from %.100s with IP options:%.800s",
+ inet_ntoa(from.sin_addr), text);
+ }
+ }
+#endif
+
+ return xstrdup(name);
+}
+
+static char *canonical_host_name = NULL;
+static char *canonical_host_ip = NULL;
+
+/* Return the canonical name of the host in the other side of the current
+ connection. The host name is cached, so it is efficient to call this
+ several times. */
+
+const char *get_canonical_hostname()
+{
+ /* Check if we have previously retrieved this same name. */
+ if (canonical_host_name != NULL)
+ return canonical_host_name;
+
+ /* Get the real hostname if socket; otherwise return UNKNOWN. */
+ if (packet_get_connection_in() == packet_get_connection_out())
+ canonical_host_name = get_remote_hostname(packet_get_connection_in());
+ else
+ canonical_host_name = xstrdup("UNKNOWN");
+
+ return canonical_host_name;
+}
+
+/* Returns the IP-address of the remote host as a string. The returned
+ string need not be freed. */
+
+const char *get_remote_ipaddr()
+{
+ struct sockaddr_in from;
+ int fromlen, socket;
+
+ /* Check if we have previously retrieved this same name. */
+ if (canonical_host_ip != NULL)
+ return canonical_host_ip;
+
+ /* If not a socket, return UNKNOWN. */
+ if (packet_get_connection_in() != packet_get_connection_out())
+ {
+ canonical_host_ip = xstrdup("UNKNOWN");
+ return canonical_host_ip;
+ }
+
+ /* Get client socket. */
+ socket = packet_get_connection_in();
+
+ /* Get IP address of client. */
+ fromlen = sizeof(from);
+ memset(&from, 0, sizeof(from));
+ if (getpeername(socket, (struct sockaddr *)&from, &fromlen) < 0)
+ {
+ error("getpeername failed: %.100s", strerror(errno));
+ return NULL;
+ }
+
+ /* Get the IP address in ascii. */
+ canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));
+
+ /* Return ip address string. */
+ return canonical_host_ip;
+}
+
+/* Returns the port of the peer of the socket. */
+
+int get_peer_port(int sock)
+{
+ struct sockaddr_in from;
+ int fromlen;
+
+ /* Get IP address of client. */
+ fromlen = sizeof(from);
+ memset(&from, 0, sizeof(from));
+ if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0)
+ {
+ error("getpeername failed: %.100s", strerror(errno));
+ return 0;
+ }
+
+ /* Return port number. */
+ return ntohs(from.sin_port);
+}
+
+/* Returns the port number of the remote host. */
+
+int get_remote_port()
+{
+ int socket;
+
+ /* If the connection is not a socket, return 65535. This is intentionally
+ chosen to be an unprivileged port number. */
+ if (packet_get_connection_in() != packet_get_connection_out())
+ return 65535;
+
+ /* Get client socket. */
+ socket = packet_get_connection_in();
+
+ /* Get and return the peer port number. */
+ return get_peer_port(socket);
+}
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c
new file mode 100644
index 00000000000..c6b2e21a3b9
--- /dev/null
+++ b/usr.bin/ssh/channels.c
@@ -0,0 +1,1559 @@
+/*
+
+channels.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Fri Mar 24 16:35:24 1995 ylo
+
+This file contains functions for generic socket connection forwarding.
+There is also code for initiating connection forwarding for X11 connections,
+arbitrary tcp/ip connections, and the authentication agent connection.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: channels.c,v 1.1 1999/09/26 20:53:34 deraadt Exp $");
+
+#ifndef HAVE_GETHOSTNAME
+#include <sys/utsname.h>
+#endif
+#include "ssh.h"
+#include "packet.h"
+#include "xmalloc.h"
+#include "buffer.h"
+#include "authfd.h"
+#include "uidswap.h"
+
+/* Maximum number of fake X11 displays to try. */
+#define MAX_DISPLAYS 1000
+
+/* Definitions for channel types. */
+#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
+#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
+#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
+#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
+#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
+#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
+#define SSH_CHANNEL_AUTH_FD 6 /* authentication fd */
+#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
+#define SSH_CHANNEL_AUTH_SOCKET_FD 8 /* connection to auth socket */
+#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
+#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */
+#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */
+
+/* Data structure for channel data. This is iniailized in channel_allocate
+ and cleared in channel_free. */
+
+typedef struct
+{
+ int type;
+ int sock;
+ int remote_id;
+ Buffer input;
+ Buffer output;
+ char path[200]; /* path for unix domain sockets, or host name for forwards */
+ int host_port; /* port to connect for forwards */
+ int listening_port; /* port being listened for forwards */
+ char *remote_name;
+} Channel;
+
+/* Pointer to an array containing all allocated channels. The array is
+ dynamically extended as needed. */
+static Channel *channels = NULL;
+
+/* Size of the channel array. All slots of the array must always be
+ initialized (at least the type field); unused slots are marked with
+ type SSH_CHANNEL_FREE. */
+static int channels_alloc = 0;
+
+/* Maximum file descriptor value used in any of the channels. This is updated
+ in channel_allocate. */
+static int channel_max_fd_value = 0;
+
+/* These two variables are for authentication agent forwarding. */
+static int channel_forwarded_auth_fd = -1;
+static char *channel_forwarded_auth_socket_name = NULL;
+
+/* Saved X11 authentication protocol name. */
+char *x11_saved_proto = NULL;
+
+/* Saved X11 authentication data. This is the real data. */
+char *x11_saved_data = NULL;
+unsigned int x11_saved_data_len = 0;
+
+/* Fake X11 authentication data. This is what the server will be sending
+ us; we should replace any occurrences of this by the real data. */
+char *x11_fake_data = NULL;
+unsigned int x11_fake_data_len;
+
+/* Data structure for storing which hosts are permitted for forward requests.
+ The local sides of any remote forwards are stored in this array to prevent
+ a corrupt remote server from accessing arbitrary TCP/IP ports on our
+ local network (which might be behind a firewall). */
+typedef struct
+{
+ char *host; /* Host name. */
+ int port; /* Port number. */
+} ForwardPermission;
+
+/* List of all permitted host/port pairs to connect. */
+static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
+/* Number of permitted host/port pairs in the array. */
+static int num_permitted_opens = 0;
+/* If this is true, all opens are permitted. This is the case on the
+ server on which we have to trust the client anyway, and the user could
+ do anything after logging in anyway. */
+static int all_opens_permitted = 0;
+
+/* This is set to true if both sides support SSH_PROTOFLAG_HOST_IN_FWD_OPEN. */
+static int have_hostname_in_open = 0;
+
+/* Sets specific protocol options. */
+
+void channel_set_options(int hostname_in_open)
+{
+ have_hostname_in_open = hostname_in_open;
+}
+
+/* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
+ called by the server, because the user could connect to any port anyway,
+ and the server has no way to know but to trust the client anyway. */
+
+void channel_permit_all_opens()
+{
+ all_opens_permitted = 1;
+}
+
+/* Allocate a new channel object and set its type and socket.
+ This will cause remote_name to be freed. */
+
+int channel_allocate(int type, int sock, char *remote_name)
+{
+ int i, old_channels;
+
+ /* Update the maximum file descriptor value. */
+ if (sock > channel_max_fd_value)
+ channel_max_fd_value = sock;
+
+ /* Do initial allocation if this is the first call. */
+ if (channels_alloc == 0)
+ {
+ channels_alloc = 10;
+ channels = xmalloc(channels_alloc * sizeof(Channel));
+ for (i = 0; i < channels_alloc; i++)
+ channels[i].type = SSH_CHANNEL_FREE;
+
+ /* Kludge: arrange a call to channel_stop_listening if we terminate
+ with fatal(). */
+ fatal_add_cleanup((void (*)(void *))channel_stop_listening, NULL);
+ }
+
+ /* Try to find a free slot where to put the new channel. */
+ for (i = 0; i < channels_alloc; i++)
+ if (channels[i].type == SSH_CHANNEL_FREE)
+ {
+ /* Found a free slot. Initialize the fields and return its number. */
+ buffer_init(&channels[i].input);
+ buffer_init(&channels[i].output);
+ channels[i].type = type;
+ channels[i].sock = sock;
+ channels[i].remote_id = -1;
+ channels[i].remote_name = remote_name;
+ return i;
+ }
+
+ /* There are no free slots. Must expand the array. */
+ old_channels = channels_alloc;
+ channels_alloc += 10;
+ channels = xrealloc(channels, channels_alloc * sizeof(Channel));
+ for (i = old_channels; i < channels_alloc; i++)
+ channels[i].type = SSH_CHANNEL_FREE;
+
+ /* We know that the next one after the old maximum channel number is now
+ available. Initialize and return its number. */
+ buffer_init(&channels[old_channels].input);
+ buffer_init(&channels[old_channels].output);
+ channels[old_channels].type = type;
+ channels[old_channels].sock = sock;
+ channels[old_channels].remote_id = -1;
+ channels[old_channels].remote_name = remote_name;
+ return old_channels;
+}
+
+/* Free the channel and close its socket. */
+
+void channel_free(int channel)
+{
+ assert(channel >= 0 && channel < channels_alloc &&
+ channels[channel].type != SSH_CHANNEL_FREE);
+ shutdown(channels[channel].sock, 2);
+ close(channels[channel].sock);
+ buffer_free(&channels[channel].input);
+ buffer_free(&channels[channel].output);
+ channels[channel].type = SSH_CHANNEL_FREE;
+ if (channels[channel].remote_name)
+ {
+ xfree(channels[channel].remote_name);
+ channels[channel].remote_name = NULL;
+ }
+}
+
+/* This is called just before select() to add any bits relevant to
+ channels in the select bitmasks. */
+
+void channel_prepare_select(fd_set *readset, fd_set *writeset)
+{
+ int i;
+ Channel *ch;
+ unsigned char *ucp;
+ unsigned int proto_len, data_len;
+
+ for (i = 0; i < channels_alloc; i++)
+ {
+ ch = &channels[i];
+ redo:
+ switch (ch->type)
+ {
+ case SSH_CHANNEL_X11_LISTENER:
+ case SSH_CHANNEL_PORT_LISTENER:
+ case SSH_CHANNEL_AUTH_SOCKET:
+ case SSH_CHANNEL_AUTH_SOCKET_FD:
+ case SSH_CHANNEL_AUTH_FD:
+ FD_SET(ch->sock, readset);
+ break;
+
+ case SSH_CHANNEL_OPEN:
+ if (buffer_len(&ch->input) < 32768)
+ FD_SET(ch->sock, readset);
+ if (buffer_len(&ch->output) > 0)
+ FD_SET(ch->sock, writeset);
+ break;
+
+ case SSH_CHANNEL_INPUT_DRAINING:
+ if (buffer_len(&ch->input) == 0)
+ {
+ packet_start(SSH_MSG_CHANNEL_CLOSE);
+ packet_put_int(ch->remote_id);
+ packet_send();
+ ch->type = SSH_CHANNEL_CLOSED;
+ debug("Closing channel %d after input drain.", i);
+ break;
+ }
+ break;
+
+ case SSH_CHANNEL_OUTPUT_DRAINING:
+ if (buffer_len(&ch->output) == 0)
+ {
+ /* debug("Freeing channel %d after output drain.", i); */
+ channel_free(i);
+ break;
+ }
+ FD_SET(ch->sock, writeset);
+ break;
+
+ case SSH_CHANNEL_X11_OPEN:
+ /* This is a special state for X11 authentication spoofing. An
+ opened X11 connection (when authentication spoofing is being
+ done) remains in this state until the first packet has been
+ completely read. The authentication data in that packet is
+ then substituted by the real data if it matches the fake data,
+ and the channel is put into normal mode. */
+
+ /* Check if the fixed size part of the packet is in buffer. */
+ if (buffer_len(&ch->output) < 12)
+ break;
+
+ /* Parse the lengths of variable-length fields. */
+ ucp = (unsigned char *)buffer_ptr(&ch->output);
+ if (ucp[0] == 0x42)
+ { /* Byte order MSB first. */
+ proto_len = 256 * ucp[6] + ucp[7];
+ data_len = 256 * ucp[8] + ucp[9];
+ }
+ else
+ if (ucp[0] == 0x6c)
+ { /* Byte order LSB first. */
+ proto_len = ucp[6] + 256 * ucp[7];
+ data_len = ucp[8] + 256 * ucp[9];
+ }
+ else
+ {
+ debug("Initial X11 packet contains bad byte order byte: 0x%x",
+ ucp[0]);
+ ch->type = SSH_CHANNEL_OPEN;
+ goto reject;
+ }
+
+ /* Check if the whole packet is in buffer. */
+ if (buffer_len(&ch->output) <
+ 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))
+ break;
+
+ /* Check if authentication protocol matches. */
+ if (proto_len != strlen(x11_saved_proto) ||
+ memcmp(ucp + 12, x11_saved_proto, proto_len) != 0)
+ {
+ debug("X11 connection uses different authentication protocol.");
+ ch->type = SSH_CHANNEL_OPEN;
+ goto reject;
+ }
+
+ /* Check if authentication data matches our fake data. */
+ if (data_len != x11_fake_data_len ||
+ memcmp(ucp + 12 + ((proto_len + 3) & ~3),
+ x11_fake_data, x11_fake_data_len) != 0)
+ {
+ debug("X11 auth data does not match fake data.");
+ ch->type = SSH_CHANNEL_OPEN;
+ goto reject;
+ }
+
+ /* Received authentication protocol and data match our fake data.
+ Substitute the fake data with real data. */
+ assert(x11_fake_data_len == x11_saved_data_len);
+ memcpy(ucp + 12 + ((proto_len + 3) & ~3),
+ x11_saved_data, x11_saved_data_len);
+
+ /* Start normal processing for the channel. */
+ ch->type = SSH_CHANNEL_OPEN;
+ goto redo;
+
+ reject:
+ /* We have received an X11 connection that has bad authentication
+ information. */
+ log("X11 connection rejected because of wrong authentication.\r\n");
+ buffer_clear(&ch->input);
+ buffer_clear(&ch->output);
+ close(ch->sock);
+ ch->sock = -1;
+ ch->type = SSH_CHANNEL_CLOSED;
+ packet_start(SSH_MSG_CHANNEL_CLOSE);
+ packet_put_int(ch->remote_id);
+ packet_send();
+ break;
+
+ case SSH_CHANNEL_FREE:
+ default:
+ continue;
+ }
+ }
+}
+
+/* After select, perform any appropriate operations for channels which
+ have events pending. */
+
+void channel_after_select(fd_set *readset, fd_set *writeset)
+{
+ struct sockaddr addr;
+ int addrlen, newsock, i, newch, len, port;
+ Channel *ch;
+ char buf[16384], *remote_hostname;
+
+ /* Loop over all channels... */
+ for (i = 0; i < channels_alloc; i++)
+ {
+ ch = &channels[i];
+ switch (ch->type)
+ {
+ case SSH_CHANNEL_X11_LISTENER:
+ /* This is our fake X11 server socket. */
+ if (FD_ISSET(ch->sock, readset))
+ {
+ debug("X11 connection requested.");
+ addrlen = sizeof(addr);
+ newsock = accept(ch->sock, &addr, &addrlen);
+ if (newsock < 0)
+ {
+ error("accept: %.100s", strerror(errno));
+ break;
+ }
+ remote_hostname = get_remote_hostname(newsock);
+ sprintf(buf, "X11 connection from %.200s port %d",
+ remote_hostname, get_peer_port(newsock));
+ xfree(remote_hostname);
+ newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
+ xstrdup(buf));
+ packet_start(SSH_SMSG_X11_OPEN);
+ packet_put_int(newch);
+ if (have_hostname_in_open)
+ packet_put_string(buf, strlen(buf));
+ packet_send();
+ }
+ break;
+
+ case SSH_CHANNEL_PORT_LISTENER:
+ /* This socket is listening for connections to a forwarded TCP/IP
+ port. */
+ if (FD_ISSET(ch->sock, readset))
+ {
+ debug("Connection to port %d forwarding to %.100s:%d requested.",
+ ch->listening_port, ch->path, ch->host_port);
+ addrlen = sizeof(addr);
+ newsock = accept(ch->sock, &addr, &addrlen);
+ if (newsock < 0)
+ {
+ error("accept: %.100s", strerror(errno));
+ break;
+ }
+ remote_hostname = get_remote_hostname(newsock);
+ sprintf(buf, "port %d, connection from %.200s port %d",
+ ch->listening_port, remote_hostname,
+ get_peer_port(newsock));
+ xfree(remote_hostname);
+ newch = channel_allocate(SSH_CHANNEL_OPENING, newsock,
+ xstrdup(buf));
+ packet_start(SSH_MSG_PORT_OPEN);
+ packet_put_int(newch);
+ packet_put_string(ch->path, strlen(ch->path));
+ packet_put_int(ch->host_port);
+ if (have_hostname_in_open)
+ packet_put_string(buf, strlen(buf));
+ packet_send();
+ }
+ break;
+
+ case SSH_CHANNEL_AUTH_FD:
+ /* This is the authentication agent file descriptor. It is used to
+ obtain the real connection to the agent. */
+ case SSH_CHANNEL_AUTH_SOCKET_FD:
+ /* This is the temporary connection obtained by connecting the
+ authentication agent socket. */
+ if (FD_ISSET(ch->sock, readset))
+ {
+ len = recv(ch->sock, buf, sizeof(buf), 0);
+ if (len <= 0)
+ {
+ channel_free(i);
+ break;
+ }
+ if (len != 3 || (unsigned char)buf[0] != SSH_AUTHFD_CONNECT)
+ break; /* Ignore any messages of wrong length or type. */
+ port = 256 * (unsigned char)buf[1] + (unsigned char)buf[2];
+ packet_start(SSH_SMSG_AGENT_OPEN);
+ packet_put_int(port);
+ packet_send();
+ }
+ break;
+
+ case SSH_CHANNEL_AUTH_SOCKET:
+ /* This is the authentication agent socket listening for connections
+ from clients. */
+ if (FD_ISSET(ch->sock, readset))
+ {
+ len = sizeof(addr);
+ newsock = accept(ch->sock, &addr, &len);
+ if (newsock < 0)
+ error("Accept from authentication socket failed");
+ (void)channel_allocate(SSH_CHANNEL_AUTH_SOCKET_FD, newsock,
+ xstrdup("accepted auth socket"));
+ }
+ break;
+
+ case SSH_CHANNEL_OPEN:
+ /* This is an open two-way communication channel. It is not of
+ interest to us at this point what kind of data is being
+ transmitted. */
+ /* Read available incoming data and append it to buffer. */
+ if (FD_ISSET(ch->sock, readset))
+ {
+ len = read(ch->sock, buf, sizeof(buf));
+ if (len <= 0)
+ {
+ buffer_consume(&ch->output, buffer_len(&ch->output));
+ ch->type = SSH_CHANNEL_INPUT_DRAINING;
+ debug("Channel %d status set to input draining.", i);
+ break;
+ }
+ buffer_append(&ch->input, buf, len);
+ }
+ /* Send buffered output data to the socket. */
+ if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0)
+ {
+ len = write(ch->sock, buffer_ptr(&ch->output),
+ buffer_len(&ch->output));
+ if (len <= 0)
+ {
+ buffer_consume(&ch->output, buffer_len(&ch->output));
+ debug("Channel %d status set to input draining.", i);
+ ch->type = SSH_CHANNEL_INPUT_DRAINING;
+ break;
+ }
+ buffer_consume(&ch->output, len);
+ }
+ break;
+
+ case SSH_CHANNEL_OUTPUT_DRAINING:
+ /* Send buffered output data to the socket. */
+ if (FD_ISSET(ch->sock, writeset) && buffer_len(&ch->output) > 0)
+ {
+ len = write(ch->sock, buffer_ptr(&ch->output),
+ buffer_len(&ch->output));
+ if (len <= 0)
+ buffer_consume(&ch->output, buffer_len(&ch->output));
+ else
+ buffer_consume(&ch->output, len);
+ }
+ break;
+
+ case SSH_CHANNEL_X11_OPEN:
+ case SSH_CHANNEL_FREE:
+ default:
+ continue;
+ }
+ }
+}
+
+/* If there is data to send to the connection, send some of it now. */
+
+void channel_output_poll()
+{
+ int len, i;
+ Channel *ch;
+
+ for (i = 0; i < channels_alloc; i++)
+ {
+ ch = &channels[i];
+ /* We are only interested in channels that can have buffered incoming
+ data. */
+ if (ch->type != SSH_CHANNEL_OPEN &&
+ ch->type != SSH_CHANNEL_INPUT_DRAINING)
+ continue;
+
+ /* Get the amount of buffered data for this channel. */
+ len = buffer_len(&ch->input);
+ if (len > 0)
+ {
+ /* Send some data for the other side over the secure connection. */
+ if (packet_is_interactive())
+ {
+ if (len > 1024)
+ len = 512;
+ }
+ else
+ {
+ if (len > 16384)
+ len = 16384; /* Keep the packets at reasonable size. */
+ }
+ packet_start(SSH_MSG_CHANNEL_DATA);
+ packet_put_int(ch->remote_id);
+ packet_put_string(buffer_ptr(&ch->input), len);
+ packet_send();
+ buffer_consume(&ch->input, len);
+ }
+ }
+}
+
+/* This is called when a packet of type CHANNEL_DATA has just been received.
+ The message type has already been consumed, but channel number and data
+ is still there. */
+
+void channel_input_data(int payload_len)
+{
+ int channel;
+ char *data;
+ unsigned int data_len;
+
+ /* Get the channel number and verify it. */
+ channel = packet_get_int();
+ if (channel < 0 || channel >= channels_alloc ||
+ channels[channel].type == SSH_CHANNEL_FREE)
+ packet_disconnect("Received data for nonexistent channel %d.", channel);
+
+ /* Ignore any data for non-open channels (might happen on close) */
+ if (channels[channel].type != SSH_CHANNEL_OPEN &&
+ channels[channel].type != SSH_CHANNEL_X11_OPEN)
+ return;
+
+ /* Get the data. */
+ data = packet_get_string(&data_len);
+ packet_integrity_check(payload_len, 4 + 4+data_len, SSH_MSG_CHANNEL_DATA);
+ buffer_append(&channels[channel].output, data, data_len);
+ xfree(data);
+}
+
+/* Returns true if no channel has too much buffered data, and false if
+ one or more channel is overfull. */
+
+int channel_not_very_much_buffered_data()
+{
+ unsigned int i;
+ Channel *ch;
+
+ for (i = 0; i < channels_alloc; i++)
+ {
+ ch = &channels[i];
+ switch (channels[i].type)
+ {
+ case SSH_CHANNEL_X11_LISTENER:
+ case SSH_CHANNEL_PORT_LISTENER:
+ case SSH_CHANNEL_AUTH_SOCKET:
+ case SSH_CHANNEL_AUTH_SOCKET_FD:
+ case SSH_CHANNEL_AUTH_FD:
+ continue;
+ case SSH_CHANNEL_OPEN:
+ if (buffer_len(&ch->input) > 32768)
+ return 0;
+ if (buffer_len(&ch->output) > 32768)
+ return 0;
+ continue;
+ case SSH_CHANNEL_INPUT_DRAINING:
+ case SSH_CHANNEL_OUTPUT_DRAINING:
+ case SSH_CHANNEL_X11_OPEN:
+ case SSH_CHANNEL_FREE:
+ default:
+ continue;
+ }
+ }
+ return 1;
+}
+
+/* This is called after receiving CHANNEL_CLOSE. */
+
+void channel_input_close()
+{
+ int channel;
+
+ /* Get the channel number and verify it. */
+ channel = packet_get_int();
+ if (channel < 0 || channel >= channels_alloc ||
+ channels[channel].type == SSH_CHANNEL_FREE)
+ packet_disconnect("Received data for nonexistent channel %d.", channel);
+
+ /* Send a confirmation that we have closed the channel and no more data is
+ coming for it. */
+ packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
+ packet_put_int(channels[channel].remote_id);
+ packet_send();
+
+ /* If the channel is in closed state, we have sent a close request, and
+ the other side will eventually respond with a confirmation. Thus,
+ we cannot free the channel here, because then there would be no-one to
+ receive the confirmation. The channel gets freed when the confirmation
+ arrives. */
+ if (channels[channel].type != SSH_CHANNEL_CLOSED)
+ {
+ /* Not a closed channel - mark it as draining, which will cause it to
+ be freed later. */
+ buffer_consume(&channels[channel].input,
+ buffer_len(&channels[channel].input));
+ channels[channel].type = SSH_CHANNEL_OUTPUT_DRAINING;
+ /* debug("Setting status to output draining; output len = %d",
+ buffer_len(&channels[channel].output)); */
+ }
+}
+
+/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION. */
+
+void channel_input_close_confirmation()
+{
+ int channel;
+
+ /* Get the channel number and verify it. */
+ channel = packet_get_int();
+ if (channel < 0 || channel >= channels_alloc)
+ packet_disconnect("Received close confirmation for out-of-range channel %d.",
+ channel);
+ if (channels[channel].type != SSH_CHANNEL_CLOSED)
+ packet_disconnect("Received close confirmation for non-closed channel %d (type %d).",
+ channel, channels[channel].type);
+
+ /* Free the channel. */
+ channel_free(channel);
+}
+
+/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */
+
+void channel_input_open_confirmation()
+{
+ int channel, remote_channel;
+
+ /* Get the channel number and verify it. */
+ channel = packet_get_int();
+ if (channel < 0 || channel >= channels_alloc ||
+ channels[channel].type != SSH_CHANNEL_OPENING)
+ packet_disconnect("Received open confirmation for non-opening channel %d.",
+ channel);
+
+ /* Get remote side's id for this channel. */
+ remote_channel = packet_get_int();
+
+ /* Record the remote channel number and mark that the channel is now open. */
+ channels[channel].remote_id = remote_channel;
+ channels[channel].type = SSH_CHANNEL_OPEN;
+}
+
+/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
+
+void channel_input_open_failure()
+{
+ int channel;
+
+ /* Get the channel number and verify it. */
+ channel = packet_get_int();
+ if (channel < 0 || channel >= channels_alloc ||
+ channels[channel].type != SSH_CHANNEL_OPENING)
+ packet_disconnect("Received open failure for non-opening channel %d.",
+ channel);
+
+ /* Free the channel. This will also close the socket. */
+ channel_free(channel);
+}
+
+/* Stops listening for channels, and removes any unix domain sockets that
+ we might have. */
+
+void channel_stop_listening()
+{
+ int i;
+ for (i = 0; i < channels_alloc; i++)
+ {
+ switch (channels[i].type)
+ {
+ case SSH_CHANNEL_AUTH_SOCKET:
+ close(channels[i].sock);
+ remove(channels[i].path);
+ channel_free(i);
+ break;
+ case SSH_CHANNEL_PORT_LISTENER:
+ case SSH_CHANNEL_X11_LISTENER:
+ close(channels[i].sock);
+ channel_free(i);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+/* Closes the sockets of all channels. This is used to close extra file
+ descriptors after a fork. */
+
+void channel_close_all()
+{
+ int i;
+ for (i = 0; i < channels_alloc; i++)
+ {
+ if (channels[i].type != SSH_CHANNEL_FREE)
+ close(channels[i].sock);
+ }
+}
+
+/* Returns the maximum file descriptor number used by the channels. */
+
+int channel_max_fd()
+{
+ return channel_max_fd_value;
+}
+
+/* Returns true if any channel is still open. */
+
+int channel_still_open()
+{
+ unsigned int i;
+ for (i = 0; i < channels_alloc; i++)
+ switch (channels[i].type)
+ {
+ case SSH_CHANNEL_FREE:
+ case SSH_CHANNEL_X11_LISTENER:
+ case SSH_CHANNEL_PORT_LISTENER:
+ case SSH_CHANNEL_CLOSED:
+ case SSH_CHANNEL_AUTH_FD:
+ case SSH_CHANNEL_AUTH_SOCKET:
+ case SSH_CHANNEL_AUTH_SOCKET_FD:
+ continue;
+ case SSH_CHANNEL_OPENING:
+ case SSH_CHANNEL_OPEN:
+ case SSH_CHANNEL_X11_OPEN:
+ case SSH_CHANNEL_INPUT_DRAINING:
+ case SSH_CHANNEL_OUTPUT_DRAINING:
+ return 1;
+ default:
+ fatal("channel_still_open: bad channel type %d", channels[i].type);
+ /*NOTREACHED*/
+ }
+ return 0;
+}
+
+/* Returns a message describing the currently open forwarded
+ connections, suitable for sending to the client. The message
+ contains crlf pairs for newlines. */
+
+char *channel_open_message()
+{
+ Buffer buffer;
+ int i;
+ char buf[512], *cp;
+
+ buffer_init(&buffer);
+ sprintf(buf, "The following connections are open:\r\n");
+ buffer_append(&buffer, buf, strlen(buf));
+ for (i = 0; i < channels_alloc; i++)
+ switch (channels[i].type)
+ {
+ case SSH_CHANNEL_FREE:
+ case SSH_CHANNEL_X11_LISTENER:
+ case SSH_CHANNEL_PORT_LISTENER:
+ case SSH_CHANNEL_CLOSED:
+ case SSH_CHANNEL_AUTH_FD:
+ case SSH_CHANNEL_AUTH_SOCKET:
+ case SSH_CHANNEL_AUTH_SOCKET_FD:
+ continue;
+ case SSH_CHANNEL_OPENING:
+ case SSH_CHANNEL_OPEN:
+ case SSH_CHANNEL_X11_OPEN:
+ case SSH_CHANNEL_INPUT_DRAINING:
+ case SSH_CHANNEL_OUTPUT_DRAINING:
+ sprintf(buf, " %.300s\r\n", channels[i].remote_name);
+ buffer_append(&buffer, buf, strlen(buf));
+ continue;
+ default:
+ fatal("channel_still_open: bad channel type %d", channels[i].type);
+ /*NOTREACHED*/
+ }
+ buffer_append(&buffer, "\0", 1);
+ cp = xstrdup(buffer_ptr(&buffer));
+ buffer_free(&buffer);
+ return cp;
+}
+
+/* Initiate forwarding of connections to local port "port" through the secure
+ channel to host:port from remote side. */
+
+void channel_request_local_forwarding(int port, const char *host,
+ int host_port)
+{
+ int ch, sock;
+ struct sockaddr_in sin;
+
+ if (strlen(host) > sizeof(channels[0].path) - 1)
+ packet_disconnect("Forward host name too long.");
+
+ /* Create a port to listen for the host. */
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ packet_disconnect("socket: %.100s", strerror(errno));
+
+ /* Initialize socket address. */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ sin.sin_port = htons(port);
+
+ /* Bind the socket to the address. */
+ if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ packet_disconnect("bind: %.100s", strerror(errno));
+
+ /* Start listening for connections on the socket. */
+ if (listen(sock, 5) < 0)
+ packet_disconnect("listen: %.100s", strerror(errno));
+
+ /* Allocate a channel number for the socket. */
+ ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock,
+ xstrdup("port listener"));
+ strcpy(channels[ch].path, host); /* note: host name stored here */
+ channels[ch].host_port = host_port; /* port on host to connect to */
+ channels[ch].listening_port = port; /* port being listened */
+}
+
+/* Initiate forwarding of connections to port "port" on remote host through
+ the secure channel to host:port from local side. */
+
+void channel_request_remote_forwarding(int port, const char *host,
+ int remote_port)
+{
+ int payload_len;
+ /* Record locally that connection to this host/port is permitted. */
+ if (num_permitted_opens >= SSH_MAX_FORWARDS_PER_DIRECTION)
+ fatal("channel_request_remote_forwarding: too many forwards");
+ permitted_opens[num_permitted_opens].host = xstrdup(host);
+ permitted_opens[num_permitted_opens].port = remote_port;
+ num_permitted_opens++;
+
+ /* Send the forward request to the remote side. */
+ packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
+ packet_put_int(port);
+ packet_put_string(host, strlen(host));
+ packet_put_int(remote_port);
+ packet_send();
+ packet_write_wait();
+
+ /* Wait for response from the remote side. It will send a disconnect
+ message on failure, and we will never see it here. */
+ packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
+}
+
+/* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
+ listening for the port, and sends back a success reply (or disconnect
+ message if there was an error). This never returns if there was an
+ error. */
+
+void channel_input_port_forward_request(int is_root)
+{
+ int port, host_port;
+ char *hostname;
+
+ /* Get arguments from the packet. */
+ port = packet_get_int();
+ hostname = packet_get_string(NULL);
+ host_port = packet_get_int();
+
+ /* Port numbers are 16 bit quantities. */
+ if ((port & 0xffff) != port)
+ packet_disconnect("Requested forwarding of nonexistent port %d.", port);
+
+
+ /* Check that an unprivileged user is not trying to forward a privileged
+ port. */
+ if (port < 1024 && !is_root)
+ packet_disconnect("Requested forwarding of port %d but user is not root.",
+ port);
+
+ /* Initiate forwarding. */
+ channel_request_local_forwarding(port, hostname, host_port);
+
+ /* Free the argument string. */
+ xfree(hostname);
+}
+
+/* This is called after receiving PORT_OPEN message. This attempts to connect
+ to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION or
+ CHANNEL_OPEN_FAILURE. */
+
+void channel_input_port_open(int payload_len)
+{
+ int remote_channel, sock, newch, host_port, i;
+ struct sockaddr_in sin;
+ char *host, *originator_string;
+ struct hostent *hp;
+ int host_len, originator_len;
+
+ /* Get remote channel number. */
+ remote_channel = packet_get_int();
+
+ /* Get host name to connect to. */
+ host = packet_get_string(&host_len);
+
+ /* Get port to connect to. */
+ host_port = packet_get_int();
+
+ /* Get remote originator name. */
+ if (have_hostname_in_open)
+ originator_string = packet_get_string(&originator_len);
+ else
+ originator_string = xstrdup("unknown (remote did not supply name)");
+
+ packet_integrity_check(payload_len,
+ 4 + 4 + host_len + 4 + 4 + originator_len,
+ SSH_MSG_PORT_OPEN);
+
+ /* Check if opening that port is permitted. */
+ if (!all_opens_permitted)
+ {
+ /* Go trough all permitted ports. */
+ for (i = 0; i < num_permitted_opens; i++)
+ if (permitted_opens[i].port == host_port &&
+ strcmp(permitted_opens[i].host, host) == 0)
+ break;
+
+ /* Check if we found the requested port among those permitted. */
+ if (i >= num_permitted_opens)
+ {
+ /* The port is not permitted. */
+ log("Received request to connect to %.100s:%d, but the request was denied.",
+ host, host_port);
+ packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
+ packet_put_int(remote_channel);
+ packet_send();
+ }
+ }
+
+ memset(&sin, 0, sizeof(sin));
+#ifdef BROKEN_INET_ADDR
+ sin.sin_addr.s_addr = inet_network(host);
+#else /* BROKEN_INET_ADDR */
+ sin.sin_addr.s_addr = inet_addr(host);
+#endif /* BROKEN_INET_ADDR */
+ if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff)
+ {
+ /* It was a valid numeric host address. */
+ sin.sin_family = AF_INET;
+ }
+ else
+ {
+ /* Look up the host address from the name servers. */
+ hp = gethostbyname(host);
+ if (!hp)
+ {
+ error("%.100s: unknown host.", host);
+ goto fail;
+ }
+ if (!hp->h_addr_list[0])
+ {
+ error("%.100s: host has no IP address.", host);
+ goto fail;
+ }
+ sin.sin_family = hp->h_addrtype;
+ memcpy(&sin.sin_addr, hp->h_addr_list[0],
+ sizeof(sin.sin_addr));
+ }
+ sin.sin_port = htons(host_port);
+
+ /* Create the socket. */
+ sock = socket(sin.sin_family, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ error("socket: %.100s", strerror(errno));
+ goto fail;
+ }
+
+ /* Connect to the host/port. */
+ if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ {
+ error("connect %.100s:%d: %.100s", host, host_port,
+ strerror(errno));
+ close(sock);
+ goto fail;
+ }
+
+ /* Successful connection. */
+
+ /* Allocate a channel for this connection. */
+ newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string);
+ channels[newch].remote_id = remote_channel;
+
+ /* Send a confirmation to the remote host. */
+ packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
+ packet_put_int(remote_channel);
+ packet_put_int(newch);
+ packet_send();
+
+ /* Free the argument string. */
+ xfree(host);
+
+ return;
+
+ fail:
+ /* Free the argument string. */
+ xfree(host);
+
+ /* Send refusal to the remote host. */
+ packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
+ packet_put_int(remote_channel);
+ packet_send();
+}
+
+/* Creates an internet domain socket for listening for X11 connections.
+ Returns a suitable value for the DISPLAY variable, or NULL if an error
+ occurs. */
+
+char *x11_create_display_inet(int screen_number)
+{
+ int display_number, port, sock;
+ struct sockaddr_in sin;
+ char buf[512];
+#ifdef HAVE_GETHOSTNAME
+ char hostname[257];
+#else
+ struct utsname uts;
+#endif
+
+ for (display_number = 1; display_number < MAX_DISPLAYS; display_number++)
+ {
+ port = 6000 + display_number;
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ sin.sin_port = htons(port);
+
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ error("socket: %.100s", strerror(errno));
+ return NULL;
+ }
+
+ if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ {
+ debug("bind port %d: %.100s", port, strerror(errno));
+ shutdown(sock, 2);
+ close(sock);
+ continue;
+ }
+ break;
+ }
+ if (display_number >= MAX_DISPLAYS)
+ {
+ error("Failed to allocate internet-domain X11 display socket.");
+ return NULL;
+ }
+
+ /* Start listening for connections on the socket. */
+ if (listen(sock, 5) < 0)
+ {
+ error("listen: %.100s", strerror(errno));
+ shutdown(sock, 2);
+ close(sock);
+ return NULL;
+ }
+
+ /* Set up a suitable value for the DISPLAY variable. */
+#ifdef HPSUX_NONSTANDARD_X11_KLUDGE
+ /* HPSUX has some special shared memory stuff in their X server, which
+ appears to be enable if the host name matches that of the local machine.
+ However, it can be circumvented by using the IP address of the local
+ machine instead. */
+ if (gethostname(hostname, sizeof(hostname)) < 0)
+ fatal("gethostname: %.100s", strerror(errno));
+ {
+ struct hostent *hp;
+ struct in_addr addr;
+ hp = gethostbyname(hostname);
+ if (!hp->h_addr_list[0])
+ {
+ error("Could not server IP address for %.200d.", hostname);
+ packet_send_debug("Could not get server IP address for %.200d.",
+ hostname);
+ shutdown(sock, 2);
+ close(sock);
+ return NULL;
+ }
+ memcpy(&addr, hp->h_addr_list[0], sizeof(addr));
+ sprintf(buf, "%.100s:%d.%d", inet_ntoa(addr), display_number,
+ screen_number);
+ }
+#else /* HPSUX_NONSTANDARD_X11_KLUDGE */
+#ifdef HAVE_GETHOSTNAME
+ if (gethostname(hostname, sizeof(hostname)) < 0)
+ fatal("gethostname: %.100s", strerror(errno));
+ sprintf(buf, "%.400s:%d.%d", hostname, display_number, screen_number);
+#else /* HAVE_GETHOSTNAME */
+ if (uname(&uts) < 0)
+ fatal("uname: %s", strerror(errno));
+ sprintf(buf, "%.400s:%d.%d", uts.nodename, display_number, screen_number);
+#endif /* HAVE_GETHOSTNAME */
+#endif /* HPSUX_NONSTANDARD_X11_KLUDGE */
+
+ /* Allocate a channel for the socket. */
+ (void)channel_allocate(SSH_CHANNEL_X11_LISTENER, sock,
+ xstrdup("X11 inet listener"));
+
+ /* Return a suitable value for the DISPLAY environment variable. */
+ return xstrdup(buf);
+}
+
+#ifndef X_UNIX_PATH
+#define X_UNIX_PATH "/tmp/.X11-unix/X"
+#endif
+
+static
+int
+connect_local_xsocket(unsigned dnr)
+{
+ static const char *const x_sockets[] = {
+ X_UNIX_PATH "%u",
+ "/var/X/.X11-unix/X" "%u",
+ "/usr/spool/sockets/X11/" "%u",
+ NULL
+ };
+ int sock;
+ struct sockaddr_un addr;
+ const char *const *path;
+
+ for (path = x_sockets; *path; ++path)
+ {
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ error("socket: %.100s", strerror(errno));
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ sprintf(addr.sun_path, *path, dnr);
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)
+ return sock;
+ close(sock);
+ }
+ error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
+ return -1;
+}
+
+
+/* This is called when SSH_SMSG_X11_OPEN is received. The packet contains
+ the remote channel number. We should do whatever we want, and respond
+ with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */
+
+void x11_input_open(int payload_len)
+{
+ int remote_channel, display_number, sock, newch;
+ const char *display;
+ struct sockaddr_in sin;
+ char buf[1024], *cp, *remote_host;
+ struct hostent *hp;
+ int remote_len;
+
+ /* Get remote channel number. */
+ remote_channel = packet_get_int();
+
+ /* Get remote originator name. */
+ if (have_hostname_in_open)
+ remote_host = packet_get_string(&remote_len);
+ else
+ remote_host = xstrdup("unknown (remote did not supply name)");
+
+ debug("Received X11 open request.");
+ packet_integrity_check(payload_len, 4 + 4+remote_len, SSH_SMSG_X11_OPEN);
+
+ /* Try to open a socket for the local X server. */
+ display = getenv("DISPLAY");
+ if (!display)
+ {
+ error("DISPLAY not set.");
+ goto fail;
+ }
+
+ /* Now we decode the value of the DISPLAY variable and make a connection
+ to the real X server. */
+
+ /* Check if it is a unix domain socket. Unix domain displays are in one
+ of the following formats: unix:d[.s], :d[.s], ::d[.s] */
+ if (strncmp(display, "unix:", 5) == 0 ||
+ display[0] == ':')
+ {
+ /* Connect to the unix domain socket. */
+ if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1)
+ {
+ error("Could not parse display number from DISPLAY: %.100s",
+ display);
+ goto fail;
+ }
+ /* Create a socket. */
+ sock = connect_local_xsocket(display_number);
+ if (sock < 0)
+ goto fail;
+
+ /* OK, we now have a connection to the display. */
+ goto success;
+ }
+
+ /* Connect to an inet socket. The DISPLAY value is supposedly
+ hostname:d[.s], where hostname may also be numeric IP address. */
+ strncpy(buf, display, sizeof(buf));
+ buf[sizeof(buf) - 1] = 0;
+ cp = strchr(buf, ':');
+ if (!cp)
+ {
+ error("Could not find ':' in DISPLAY: %.100s", display);
+ goto fail;
+ }
+ *cp = 0;
+ /* buf now contains the host name. But first we parse the display number. */
+ if (sscanf(cp + 1, "%d", &display_number) != 1)
+ {
+ error("Could not parse display number from DISPLAY: %.100s",
+ display);
+ goto fail;
+ }
+
+ /* Try to parse the host name as a numeric IP address. */
+ memset(&sin, 0, sizeof(sin));
+#ifdef BROKEN_INET_ADDR
+ sin.sin_addr.s_addr = inet_network(buf);
+#else /* BROKEN_INET_ADDR */
+ sin.sin_addr.s_addr = inet_addr(buf);
+#endif /* BROKEN_INET_ADDR */
+ if ((sin.sin_addr.s_addr & 0xffffffff) != 0xffffffff)
+ {
+ /* It was a valid numeric host address. */
+ sin.sin_family = AF_INET;
+ }
+ else
+ {
+ /* Not a numeric IP address. */
+ /* Look up the host address from the name servers. */
+ hp = gethostbyname(buf);
+ if (!hp)
+ {
+ error("%.100s: unknown host.", buf);
+ goto fail;
+ }
+ if (!hp->h_addr_list[0])
+ {
+ error("%.100s: host has no IP address.", buf);
+ goto fail;
+ }
+ sin.sin_family = hp->h_addrtype;
+ memcpy(&sin.sin_addr, hp->h_addr_list[0],
+ sizeof(sin.sin_addr));
+ }
+ /* Set port number. */
+ sin.sin_port = htons(6000 + display_number);
+
+ /* Create a socket. */
+ sock = socket(sin.sin_family, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ error("socket: %.100s", strerror(errno));
+ goto fail;
+ }
+ /* Connect it to the display. */
+ if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ {
+ error("connect %.100s:%d: %.100s", buf, 6000 + display_number,
+ strerror(errno));
+ close(sock);
+ goto fail;
+ }
+
+ success:
+ /* We have successfully obtained a connection to the real X display. */
+
+ /* Allocate a channel for this connection. */
+ if (x11_saved_proto == NULL)
+ newch = channel_allocate(SSH_CHANNEL_OPEN, sock, remote_host);
+ else
+ newch = channel_allocate(SSH_CHANNEL_X11_OPEN, sock, remote_host);
+ channels[newch].remote_id = remote_channel;
+
+ /* Send a confirmation to the remote host. */
+ packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
+ packet_put_int(remote_channel);
+ packet_put_int(newch);
+ packet_send();
+
+ return;
+
+ fail:
+ /* Send refusal to the remote host. */
+ packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
+ packet_put_int(remote_channel);
+ packet_send();
+}
+
+/* Requests forwarding of X11 connections, generates fake authentication
+ data, and enables authentication spoofing. */
+
+void x11_request_forwarding_with_spoofing(RandomState *state,
+ const char *proto, const char *data)
+{
+ unsigned int data_len = (unsigned int)strlen(data) / 2;
+ unsigned int i, value;
+ char *new_data;
+ int screen_number;
+ const char *cp;
+
+ cp = getenv("DISPLAY");
+ if (cp)
+ cp = strchr(cp, ':');
+ if (cp)
+ cp = strchr(cp, '.');
+ if (cp)
+ screen_number = atoi(cp + 1);
+ else
+ screen_number = 0;
+
+ /* Save protocol name. */
+ x11_saved_proto = xstrdup(proto);
+
+ /* Extract real authentication data and generate fake data of the same
+ length. */
+ x11_saved_data = xmalloc(data_len);
+ x11_fake_data = xmalloc(data_len);
+ for (i = 0; i < data_len; i++)
+ {
+ if (sscanf(data + 2 * i, "%2x", &value) != 1)
+ fatal("x11_request_forwarding: bad authentication data: %.100s", data);
+ x11_saved_data[i] = value;
+ x11_fake_data[i] = random_get_byte(state);
+ }
+ x11_saved_data_len = data_len;
+ x11_fake_data_len = data_len;
+
+ /* Convert the fake data into hex. */
+ new_data = xmalloc(2 * data_len + 1);
+ for (i = 0; i < data_len; i++)
+ sprintf(new_data + 2 * i, "%02x", (unsigned char)x11_fake_data[i]);
+
+ /* Send the request packet. */
+ packet_start(SSH_CMSG_X11_REQUEST_FORWARDING);
+ packet_put_string(proto, strlen(proto));
+ packet_put_string(new_data, strlen(new_data));
+ packet_put_int(screen_number);
+ packet_send();
+ packet_write_wait();
+ xfree(new_data);
+}
+
+/* Sends a message to the server to request authentication fd forwarding. */
+
+void auth_request_forwarding()
+{
+ packet_start(SSH_CMSG_AGENT_REQUEST_FORWARDING);
+ packet_send();
+ packet_write_wait();
+}
+
+/* Returns the number of the file descriptor to pass to child programs as
+ the authentication fd. Returns -1 if there is no forwarded authentication
+ fd. */
+
+int auth_get_fd()
+{
+ return channel_forwarded_auth_fd;
+}
+
+/* Returns the name of the forwarded authentication socket. Returns NULL
+ if there is no forwarded authentication socket. The returned value
+ points to a static buffer. */
+
+char *auth_get_socket_name()
+{
+ return channel_forwarded_auth_socket_name;
+}
+
+/* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
+ This starts forwarding authentication requests. */
+
+void auth_input_request_forwarding(struct passwd *pw)
+{
+ int pfd = get_permanent_fd(pw->pw_shell);
+#ifdef HAVE_UMASK
+ mode_t savedumask;
+#endif /* HAVE_UMASK */
+
+ if (pfd < 0)
+ {
+ int sock, newch;
+ struct sockaddr_un sunaddr;
+
+ if (auth_get_socket_name() != NULL)
+ fatal("Protocol error: authentication forwarding requested twice.");
+
+ /* Allocate a buffer for the socket name, and format the name. */
+ channel_forwarded_auth_socket_name = xmalloc(100);
+ sprintf(channel_forwarded_auth_socket_name, SSH_AGENT_SOCKET,
+ (int)getpid());
+
+ /* Create the socket. */
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ packet_disconnect("socket: %.100s", strerror(errno));
+
+ /* Bind it to the name. */
+ memset(&sunaddr, 0, sizeof(sunaddr));
+ sunaddr.sun_family = AF_UNIX;
+ strncpy(sunaddr.sun_path, channel_forwarded_auth_socket_name,
+ sizeof(sunaddr.sun_path));
+
+#ifdef HAVE_UMASK
+ savedumask = umask(0077);
+#endif /* HAVE_UMASK */
+
+ /* Temporarily use a privileged uid. */
+ temporarily_use_uid(pw->pw_uid);
+
+ if (bind(sock, (struct sockaddr *)&sunaddr, AF_UNIX_SIZE(sunaddr)) < 0)
+ packet_disconnect("bind: %.100s", strerror(errno));
+
+ /* Restore the privileged uid. */
+ restore_uid();
+
+#ifdef HAVE_UMASK
+ umask(savedumask);
+#endif /* HAVE_UMASK */
+
+ /* Start listening on the socket. */
+ if (listen(sock, 5) < 0)
+ packet_disconnect("listen: %.100s", strerror(errno));
+
+ /* Allocate a channel for the authentication agent socket. */
+ newch = channel_allocate(SSH_CHANNEL_AUTH_SOCKET, sock,
+ xstrdup("auth socket"));
+ strcpy(channels[newch].path, channel_forwarded_auth_socket_name);
+ }
+ else
+ {
+ int sockets[2], i, cnt, newfd;
+ int *dups = xmalloc(sizeof (int) * (pfd + 1));
+
+ if (auth_get_fd() != -1)
+ fatal("Protocol error: authentication forwarding requested twice.");
+
+ /* Create a socket pair. */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
+ packet_disconnect("socketpair: %.100s", strerror(errno));
+
+ /* Dup some descriptors to get the authentication fd to pfd,
+ because some shells arbitrarily close descriptors below that.
+ Don't use dup2 because maybe some systems don't have it?? */
+ for (cnt = 0;; cnt++)
+ {
+ if ((dups[cnt] = dup(packet_get_connection_in())) < 0)
+ fatal("auth_input_request_forwarding: dup failed");
+ if (dups[cnt] == pfd)
+ break;
+ }
+ close(dups[cnt]);
+
+ /* Move the file descriptor we pass to children up high where
+ the shell won't close it. */
+ newfd = dup(sockets[1]);
+ if (newfd != pfd)
+ fatal ("auth_input_request_forwarding: dup didn't return %d.", pfd);
+ close(sockets[1]);
+ sockets[1] = newfd;
+ /* Close duped descriptors. */
+ for (i = 0; i < cnt; i++)
+ close(dups[i]);
+ free(dups);
+
+ /* Record the file descriptor to be passed to children. */
+ channel_forwarded_auth_fd = sockets[1];
+
+ /* Allcate a channel for the authentication fd. */
+ (void)channel_allocate(SSH_CHANNEL_AUTH_FD, sockets[0],
+ xstrdup("auth fd"));
+ }
+}
+
+/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
+
+void auth_input_open_request()
+{
+ int port, sock, newch;
+ char *dummyname;
+
+ /* Read the port number from the message. */
+ port = packet_get_int();
+
+ /* Get a connection to the local authentication agent (this may again get
+ forwarded). */
+ sock = ssh_get_authentication_connection_fd();
+
+ /* If we could not connect the agent, just return. This will cause the
+ client to timeout and fail. This should never happen unless the agent
+ dies, because authentication forwarding is only enabled if we have an
+ agent. */
+ if (sock < 0)
+ return;
+
+ debug("Forwarding authentication connection.");
+
+ /* Dummy host name. This will be freed when the channel is freed; it will
+ still be valid in the packet_put_string below since the channel cannot
+ yet be freed at that point. */
+ dummyname = xstrdup("authentication agent connection");
+
+ /* Allocate a channel for the new connection. */
+ newch = channel_allocate(SSH_CHANNEL_OPENING, sock, dummyname);
+
+ /* Fake a forwarding request. */
+ packet_start(SSH_MSG_PORT_OPEN);
+ packet_put_int(newch);
+ packet_put_string("localhost", strlen("localhost"));
+ packet_put_int(port);
+ if (have_hostname_in_open)
+ packet_put_string(dummyname, strlen(dummyname));
+ packet_send();
+}
diff --git a/usr.bin/ssh/check-fds.c b/usr.bin/ssh/check-fds.c
new file mode 100644
index 00000000000..20e8bf5c1b3
--- /dev/null
+++ b/usr.bin/ssh/check-fds.c
@@ -0,0 +1,43 @@
+/*
+
+check-fds.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Apr 8 00:25:04 1995 ylo
+
+*/
+
+#include <stdio.h>
+RCSID("$Id: check-fds.c,v 1.1 1999/09/26 20:53:34 deraadt Exp $");
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+int main(int ac, char **av)
+{
+ int i, dummy;
+ struct stat st;
+
+ for (i = 0; i < 1024; i++)
+ if (fcntl(i, F_GETFL, &dummy) >= 0)
+ {
+ printf("Descriptor %d is open.\n", i);
+ if (fstat(i, &st) < 0)
+ perror("fstat");
+ else
+ {
+ printf("st_mode 0x%x, st_dev 0x%x, st_rdev 0x%x, st_ino 0x%x, st_size 0x%lx\n",
+ st.st_mode, st.st_dev, st.st_rdev, st.st_ino,
+ (long)st.st_size);
+ if (ttyname(i))
+ printf("ttyname: %.100s\n", ttyname(i));
+ }
+ }
+ exit(0);
+}
+
diff --git a/usr.bin/ssh/cipher.c b/usr.bin/ssh/cipher.c
new file mode 100644
index 00000000000..4711d9afce3
--- /dev/null
+++ b/usr.bin/ssh/cipher.c
@@ -0,0 +1,418 @@
+/*
+
+cipher.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Apr 19 17:41:39 1995 ylo
+
+*/
+
+#include "includes.h"
+RCSID("$Id: cipher.c,v 1.1 1999/09/26 20:53:34 deraadt Exp $");
+
+#include "ssh.h"
+#include "cipher.h"
+
+/*
+ * What kind of tripple DES are these 2 routines?
+ *
+ * Why is there a redundant initialization vector?
+ *
+ * If only iv3 was used, then, this would till effect have been
+ * outer-cbc. However, there is also a private iv1 == iv2 which
+ * perhaps makes differential analysis easier. On the other hand, the
+ * private iv1 probably makes the CRC-32 attack ineffective. This is a
+ * result of that there is no longer any known iv1 to use when
+ * choosing the X block.
+ */
+void
+SSH_3CBC_ENCRYPT(des_key_schedule ks1,
+ des_key_schedule ks2, des_cblock *iv2,
+ des_key_schedule ks3, des_cblock *iv3,
+ void *dest, void *src,
+ unsigned int len)
+{
+ des_cblock iv1;
+
+ memcpy(&iv1, iv2, 8);
+
+ des_cbc_encrypt(src, dest, len, ks1, &iv1, DES_ENCRYPT);
+ memcpy(&iv1, dest + len - 8, 8);
+
+ des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_DECRYPT);
+ memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
+
+ des_cbc_encrypt(dest, dest, len, ks3, iv3, DES_ENCRYPT);
+ memcpy(iv3, dest + len - 8, 8);
+}
+
+void
+SSH_3CBC_DECRYPT(des_key_schedule ks1,
+ des_key_schedule ks2, des_cblock *iv2,
+ des_key_schedule ks3, des_cblock *iv3,
+ void *dest, void *src,
+ unsigned int len)
+{
+ des_cblock iv1;
+
+ memcpy(&iv1, iv2, 8);
+
+ des_cbc_encrypt(src, dest, len, ks3, iv3, DES_DECRYPT);
+ memcpy(iv3, src + len - 8, 8);
+
+ des_cbc_encrypt(dest, dest, len, ks2, iv2, DES_ENCRYPT);
+ memcpy(iv2, dest + len - 8, 8);
+
+ des_cbc_encrypt(dest, dest, len, ks1, &iv1, DES_DECRYPT);
+ /* memcpy(&iv1, iv2, 8); */ /* Note how iv1 == iv2 on entry and exit. */
+}
+
+#ifdef WITH_BLOWFISH
+/*
+ * SSH uses a variation on Blowfish, all bytes must be swapped before
+ * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
+ */
+static
+void
+swap_bytes(const unsigned char *src, unsigned char *dst_, int n)
+{
+ uint32 *dst = (uint32 *)dst_; /* dst must be properly aligned. */
+ union {
+ uint32 i;
+ char c[4];
+ } t;
+
+ /* assert((n & 7) == 0); */
+
+ /* Process 8 bytes every lap. */
+ for (n = n / 8; n > 0; n--)
+ {
+ t.c[3] = *src++;
+ t.c[2] = *src++;
+ t.c[1] = *src++;
+ t.c[0] = *src++;
+ *dst++ = t.i;
+
+ t.c[3] = *src++;
+ t.c[2] = *src++;
+ t.c[1] = *src++;
+ t.c[0] = *src++;
+ *dst++ = t.i;
+ }
+}
+#endif /* WITH_BLOWFISH */
+
+void (*cipher_attack_detected)(const char *fmt, ...) = fatal;
+
+static inline
+void
+detect_cbc_attack(const unsigned char *src,
+ unsigned int len)
+{
+ return;
+
+ log("CRC-32 CBC insertion attack detected");
+ cipher_attack_detected("CRC-32 CBC insertion attack detected");
+}
+
+#ifdef WITH_IDEA
+static inline
+void
+detect_cfb_attack(const unsigned char *src,
+ unsigned int len,
+ const unsigned char iv[8])
+{
+ return;
+
+ log("CRC-32 CFB insertion attack detected");
+ cipher_attack_detected("CRC-32 CFB insertion attack detected");
+}
+#endif /* WITH_IDEA */
+
+/* Names of all encryption algorithms. These must match the numbers defined
+ int cipher.h. */
+static char *cipher_names[] =
+{ "none",
+#ifdef WITH_IDEA
+ "idea",
+#else
+ "no idea",
+#endif
+#ifdef WITH_DES
+ "des",
+#else
+ "no des",
+#endif
+ "3des",
+ "no tss",
+#ifdef WITH_RC4
+ "rc4",
+#else
+ "no rc4",
+#endif
+#ifdef WITH_BLOWFISH
+ "blowfish"
+#else
+ "no blowfish"
+#endif
+};
+
+/* Returns a bit mask indicating which ciphers are supported by this
+ implementation. The bit mask has the corresponding bit set of each
+ supported cipher. */
+
+unsigned int cipher_mask()
+{
+ unsigned int mask = 0;
+ mask |= 1 << SSH_CIPHER_NONE;
+#ifdef WITH_IDEA
+ mask |= 1 << SSH_CIPHER_IDEA;
+#endif /* WITH_IDEA */
+#ifdef WITH_DES
+ mask |= 1 << SSH_CIPHER_DES;
+#endif
+ mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
+#ifdef WITH_RC4
+ mask |= 1 << SSH_CIPHER_RC4;
+#endif
+#ifdef WITH_BLOWFISH
+ mask |= 1 << SSH_CIPHER_BLOWFISH;
+#endif
+ return mask;
+}
+
+/* Returns the name of the cipher. */
+
+const char *cipher_name(int cipher)
+{
+ if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]))
+ fatal("cipher_name: bad cipher number: %d", cipher);
+ return cipher_names[cipher];
+}
+
+/* Parses the name of the cipher. Returns the number of the corresponding
+ cipher, or -1 on error. */
+
+int cipher_number(const char *name)
+{
+ int i;
+ for (i = 0; i < sizeof(cipher_names) / sizeof(cipher_names[0]); i++)
+ if (strcmp(cipher_names[i], name) == 0)
+ return i;
+ return -1;
+}
+
+/* Selects the cipher, and keys if by computing the MD5 checksum of the
+ passphrase and using the resulting 16 bytes as the key. */
+
+void cipher_set_key_string(CipherContext *context, int cipher,
+ const char *passphrase, int for_encryption)
+{
+ struct MD5Context md;
+ unsigned char digest[16];
+
+ MD5Init(&md);
+ MD5Update(&md, (const unsigned char *)passphrase, strlen(passphrase));
+ MD5Final(digest, &md);
+
+ cipher_set_key(context, cipher, digest, 16, for_encryption);
+
+ memset(digest, 0, sizeof(digest));
+ memset(&md, 0, sizeof(md));
+}
+
+/* Selects the cipher to use and sets the key. */
+
+void cipher_set_key(CipherContext *context, int cipher,
+ const unsigned char *key, int keylen, int for_encryption)
+{
+ unsigned char padded[32];
+
+ /* Set cipher type. */
+ context->type = cipher;
+
+ /* Get 32 bytes of key data. Pad if necessary. (So that code below does
+ not need to worry about key size). */
+ memset(padded, 0, sizeof(padded));
+ memcpy(padded, key, keylen < sizeof(padded) ? keylen : sizeof(padded));
+
+ /* Initialize the initialization vector. */
+ switch (cipher)
+ {
+ case SSH_CIPHER_NONE:
+ break;
+
+#ifdef WITH_IDEA
+ case SSH_CIPHER_IDEA:
+ if (keylen < 16)
+ error("Key length %d is insufficient for IDEA.", keylen);
+ idea_set_key(&context->u.idea.key, padded);
+ memset(context->u.idea.iv, 0, sizeof(context->u.idea.iv));
+ break;
+#endif /* WITH_IDEA */
+
+#ifdef WITH_DES
+ case SSH_CIPHER_DES:
+ /* Note: the least significant bit of each byte of key is parity,
+ and must be ignored by the implementation. 8 bytes of key are
+ used. */
+ if (keylen < 8)
+ error("Key length %d is insufficient for DES.", keylen);
+ des_set_key((void*)padded, context->u.des.key);
+ memset(context->u.des.iv, 0, sizeof(context->u.des.iv));
+ break;
+#endif /* WITH_DES */
+
+ case SSH_CIPHER_3DES:
+ /* Note: the least significant bit of each byte of key is parity,
+ and must be ignored by the implementation. 16 bytes of key are
+ used (first and last keys are the same). */
+ if (keylen < 16)
+ error("Key length %d is insufficient for 3DES.", keylen);
+ des_set_key((void*)padded, context->u.des3.key1);
+ des_set_key((void*)(padded + 8), context->u.des3.key2);
+ if (keylen <= 16)
+ des_set_key((void*)padded, context->u.des3.key3);
+ else
+ des_set_key((void*)(padded + 16), context->u.des3.key3);
+ memset(context->u.des3.iv2, 0, sizeof(context->u.des3.iv2));
+ memset(context->u.des3.iv3, 0, sizeof(context->u.des3.iv3));
+ break;
+
+#ifdef WITH_RC4
+ case SSH_CIPHER_RC4:
+ rc4_init(&context->u.rc4, key, keylen);
+ break;
+#endif /* WITH_RC4 */
+
+#ifdef WITH_BLOWFISH
+ case SSH_CIPHER_BLOWFISH:
+ BF_set_key(&context->u.bf.key, keylen, padded);
+ memset(context->u.bf.iv, 0, 8);
+ break;
+#endif /* WITH_BLOWFISH */
+
+ default:
+ fatal("cipher_set_key: unknown cipher: %d", cipher);
+ }
+ memset(padded, 0, sizeof(padded));
+}
+
+/* Encrypts data using the cipher. */
+
+void cipher_encrypt(CipherContext *context, unsigned char *dest,
+ const unsigned char *src, unsigned int len)
+{
+ assert((len & 7) == 0);
+
+ switch (context->type)
+ {
+ case SSH_CIPHER_NONE:
+ memcpy(dest, src, len);
+ break;
+
+#ifdef WITH_IDEA
+ case SSH_CIPHER_IDEA:
+ idea_cfb_encrypt(&context->u.idea.key, context->u.idea.iv,
+ dest, src, len);
+ break;
+#endif /* WITH_IDEA */
+
+#ifdef WITH_DES
+ case SSH_CIPHER_DES:
+ des_cbc_encrypt((void*)src, (void*)dest, len,
+ context->u.des.key, &context->u.des.iv, DES_ENCRYPT);
+ memcpy(context->u.des.iv, dest + len - 8, 8);
+ break;
+#endif /* WITH_DES */
+
+ case SSH_CIPHER_3DES:
+ SSH_3CBC_ENCRYPT(context->u.des3.key1,
+ context->u.des3.key2, &context->u.des3.iv2,
+ context->u.des3.key3, &context->u.des3.iv3,
+ dest, (void*)src, len);
+ break;
+
+#ifdef WITH_RC4
+ case SSH_CIPHER_RC4:
+ rc4_encrypt(&context->u.rc4, dest, src, len);
+ break;
+#endif /* WITH_RC4 */
+
+#ifdef WITH_BLOWFISH
+ case SSH_CIPHER_BLOWFISH:
+ swap_bytes(src, dest, len);
+ BF_cbc_encrypt(dest, dest, len,
+ &context->u.bf.key, context->u.bf.iv, BF_ENCRYPT);
+ swap_bytes(dest, dest, len);
+ break;
+#endif /* WITH_BLOWFISH */
+
+ default:
+ fatal("cipher_encrypt: unknown cipher: %d", context->type);
+ }
+}
+
+/* Decrypts data using the cipher. */
+
+void cipher_decrypt(CipherContext *context, unsigned char *dest,
+ const unsigned char *src, unsigned int len)
+{
+ assert((len & 7) == 0);
+
+ switch (context->type)
+ {
+ case SSH_CIPHER_NONE:
+ memcpy(dest, src, len);
+ break;
+
+#ifdef WITH_IDEA
+ case SSH_CIPHER_IDEA:
+ detect_cfb_attack(src, len, context->u.idea.iv);
+ idea_cfb_decrypt(&context->u.idea.key, context->u.idea.iv,
+ dest, src, len);
+ break;
+#endif /* WITH_IDEA */
+
+#ifdef WITH_DES
+ case SSH_CIPHER_DES:
+ detect_cbc_attack(src, len);
+ des_cbc_encrypt((void*)src, (void*)dest, len,
+ context->u.des.key, &context->u.des.iv, DES_DECRYPT);
+ memcpy(context->u.des.iv, src + len - 8, 8);
+ break;
+#endif /* WITH_DES */
+
+ case SSH_CIPHER_3DES:
+ /* CRC-32 attack? */
+ SSH_3CBC_DECRYPT(context->u.des3.key1,
+ context->u.des3.key2, &context->u.des3.iv2,
+ context->u.des3.key3, &context->u.des3.iv3,
+ dest, (void*)src, len);
+ break;
+
+#ifdef WITH_RC4
+ case SSH_CIPHER_RC4:
+ /* CRC-32 attack? */
+ rc4_decrypt(&context->u.rc4, dest, src, len);
+ break;
+#endif /* WITH_RC4 */
+
+#ifdef WITH_BLOWFISH
+ case SSH_CIPHER_BLOWFISH:
+ detect_cbc_attack(src, len);
+ swap_bytes(src, dest, len);
+ BF_cbc_encrypt((void*)dest, dest, len,
+ &context->u.bf.key, context->u.bf.iv, BF_DECRYPT);
+ swap_bytes(dest, dest, len);
+ break;
+#endif /* WITH_BLOWFISH */
+
+ default:
+ fatal("cipher_decrypt: unknown cipher: %d", context->type);
+ }
+}
diff --git a/usr.bin/ssh/cipher.h b/usr.bin/ssh/cipher.h
new file mode 100644
index 00000000000..3979006728d
--- /dev/null
+++ b/usr.bin/ssh/cipher.h
@@ -0,0 +1,109 @@
+/*
+
+cipher.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Apr 19 16:50:42 1995 ylo
+
+*/
+
+/* RCSID("$Id: cipher.h,v 1.1 1999/09/26 20:53:34 deraadt Exp $"); */
+
+#ifndef CIPHER_H
+#define CIPHER_H
+
+#ifdef WITH_IDEA
+#include "idea.h"
+#endif /* WITH_IDEA */
+#include "des.h"
+#ifdef WITH_RC4
+#include "rc4.h"
+#endif
+#ifdef WITH_BLOWFISH
+#include "blowfish.h"
+#endif
+
+/* Cipher types. New types can be added, but old types should not be removed
+ for compatibility. The maximum allowed value is 31. */
+#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
+#define SSH_CIPHER_NONE 0 /* no encryption */
+#define SSH_CIPHER_IDEA 1 /* IDEA CFB */
+#define SSH_CIPHER_DES 2 /* DES CBC */
+#define SSH_CIPHER_3DES 3 /* 3DES CBC */
+#define SSH_CIPHER_TSS 4 /* TRI's Simple Stream encryption CBC */
+#define SSH_CIPHER_RC4 5 /* Alleged RC4 */
+#define SSH_CIPHER_BLOWFISH 6
+
+typedef struct {
+ unsigned int type;
+ union {
+#ifdef WITH_IDEA
+ struct {
+ IDEAContext key;
+ unsigned char iv[8];
+ } idea;
+#endif /* WITH_IDEA */
+#ifdef WITH_DES
+ struct {
+ des_key_schedule key;
+ des_cblock iv;
+ } des;
+#endif /* WITH_DES */
+ struct {
+ des_key_schedule key1;
+ des_key_schedule key2;
+ des_cblock iv2;
+ des_key_schedule key3;
+ des_cblock iv3;
+ } des3;
+#ifdef WITH_RC4
+ RC4Context rc4;
+#endif
+#ifdef WITH_BLOWFISH
+ struct {
+ struct bf_key_st key;
+ unsigned char iv[8];
+ } bf;
+#endif /* WITH_BLOWFISH */
+ } u;
+} CipherContext;
+
+/* Returns a bit mask indicating which ciphers are supported by this
+ implementation. The bit mask has the corresponding bit set of each
+ supported cipher. */
+unsigned int cipher_mask();
+
+/* Returns the name of the cipher. */
+const char *cipher_name(int cipher);
+
+/* Parses the name of the cipher. Returns the number of the corresponding
+ cipher, or -1 on error. */
+int cipher_number(const char *name);
+
+/* Selects the cipher to use and sets the key. If for_encryption is true,
+ the key is setup for encryption; otherwise it is setup for decryption. */
+void cipher_set_key(CipherContext *context, int cipher,
+ const unsigned char *key, int keylen, int for_encryption);
+
+/* Sets key for the cipher by computing the MD5 checksum of the passphrase,
+ and using the resulting 16 bytes as the key. */
+void cipher_set_key_string(CipherContext *context, int cipher,
+ const char *passphrase, int for_encryption);
+
+/* Encrypts data using the cipher. */
+void cipher_encrypt(CipherContext *context, unsigned char *dest,
+ const unsigned char *src, unsigned int len);
+
+/* Decrypts data using the cipher. */
+void cipher_decrypt(CipherContext *context, unsigned char *dest,
+ const unsigned char *src, unsigned int len);
+
+/* If and CRC-32 attack is detected this function is called. Defaults
+ * to fatal, changed to packet_disconnect in sshd and ssh. */
+extern void (*cipher_attack_detected)(const char *fmt, ...);
+
+#endif /* CIPHER_H */
diff --git a/usr.bin/ssh/clientloop.c b/usr.bin/ssh/clientloop.c
new file mode 100644
index 00000000000..6813f2cee3e
--- /dev/null
+++ b/usr.bin/ssh/clientloop.c
@@ -0,0 +1,973 @@
+/*
+
+clientloop.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+
+Created: Sat Sep 23 12:23:57 1995 ylo
+
+The main loop for the interactive session (client side).
+
+*/
+
+#include "includes.h"
+RCSID("$Id: clientloop.c,v 1.1 1999/09/26 20:53:34 deraadt Exp $");
+
+#include "xmalloc.h"
+#include "randoms.h"
+#include "ssh.h"
+#include "packet.h"
+#include "buffer.h"
+#include "authfd.h"
+
+/* Flag indicating whether quiet mode is on. */
+extern int quiet_flag;
+
+/* Flag indicating that stdin should be redirected from /dev/null. */
+extern int stdin_null_flag;
+
+/* Name of the host we are connecting to. This is the name given on the
+ command line, or the HostName specified for the user-supplied name
+ in a configuration file. */
+extern char *host;
+
+#ifdef SIGWINCH
+/* Flag to indicate that we have received a window change signal which has
+ not yet been processed. This will cause a message indicating the new
+ window size to be sent to the server a little later. This is volatile
+ because this is updated in a signal handler. */
+static volatile int received_window_change_signal = 0;
+#endif /* SIGWINCH */
+
+/* Terminal modes, as saved by enter_raw_mode. */
+#ifdef USING_TERMIOS
+static struct termios saved_tio;
+#endif
+#ifdef USING_SGTTY
+static struct sgttyb saved_tio;
+#endif
+
+/* Flag indicating whether we are in raw mode. This is used by enter_raw_mode
+ and leave_raw_mode. */
+static int in_raw_mode = 0;
+
+/* Flag indicating whether the user\'s terminal is in non-blocking mode. */
+static int in_non_blocking_mode = 0;
+
+/* Common data for the client loop code. */
+static int escape_pending; /* Last character was the escape character */
+static int last_was_cr; /* Last character was a newline. */
+static int exit_status; /* Used to store the exit status of the command. */
+static int stdin_eof; /* EOF has been encountered on standard error. */
+static Buffer stdin_buffer; /* Buffer for stdin data. */
+static Buffer stdout_buffer; /* Buffer for stdout data. */
+static Buffer stderr_buffer; /* Buffer for stderr data. */
+static unsigned int buffer_high; /* Soft max buffer size. */
+static int max_fd; /* Maximum file descriptor number in select(). */
+static int connection_in; /* Connection to server (input). */
+static int connection_out; /* Connection to server (output). */
+static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
+static int quit_pending; /* Set to non-zero to quit the client loop. */
+static int escape_char; /* Escape character. */
+
+/* Returns the user\'s terminal to normal mode if it had been put in raw
+ mode. */
+
+void leave_raw_mode()
+{
+ if (!in_raw_mode)
+ return;
+ in_raw_mode = 0;
+#ifdef USING_TERMIOS
+ if (tcsetattr(fileno(stdin), TCSADRAIN, &saved_tio) < 0)
+ perror("tcsetattr");
+#endif /* USING_TERMIOS */
+#ifdef USING_SGTTY
+ if (ioctl(fileno(stdin), TIOCSETP, &saved_tio) < 0)
+ perror("ioctl(stdin, TIOCSETP, ...)");
+#endif /* USING_SGTTY */
+
+ fatal_remove_cleanup((void (*)(void *))leave_raw_mode, NULL);
+}
+
+/* Puts the user\'s terminal in raw mode. */
+
+void enter_raw_mode()
+{
+#ifdef USING_TERMIOS
+ struct termios tio;
+
+ if (tcgetattr(fileno(stdin), &tio) < 0)
+ perror("tcgetattr");
+ saved_tio = tio;
+ tio.c_iflag |= IGNPAR;
+ tio.c_iflag &= ~(ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF);
+ tio.c_lflag &= ~(ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHONL);
+#ifdef IEXTEN
+ tio.c_lflag &= ~IEXTEN;
+#endif /* IEXTEN */
+ tio.c_oflag &= ~OPOST;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ if (tcsetattr(fileno(stdin), TCSADRAIN, &tio) < 0)
+ perror("tcsetattr");
+ in_raw_mode = 1;
+#endif /* USING_TERMIOS */
+#ifdef USING_SGTTY
+ struct sgttyb tio;
+
+ if (ioctl(fileno(stdin), TIOCGETP, &tio) < 0)
+ perror("ioctl(stdin, TIOCGETP, ...)");
+ saved_tio = tio;
+ tio.sg_flags &= ~(CBREAK | ECHO | CRMOD | LCASE | TANDEM);
+ tio.sg_flags |= (RAW | ANYP);
+ if (ioctl(fileno(stdin), TIOCSETP, &tio) < 0)
+ perror("ioctl(stdin, TIOCSETP, ...)");
+ in_raw_mode = 1;
+#endif /* USING_SGTTY */
+
+ fatal_add_cleanup((void (*)(void *))leave_raw_mode, NULL);
+}
+
+/* Puts stdin terminal in non-blocking mode. */
+
+/* Restores stdin to blocking mode. */
+
+void leave_non_blocking()
+{
+ if (in_non_blocking_mode)
+ {
+ (void)fcntl(fileno(stdin), F_SETFL, 0);
+ in_non_blocking_mode = 0;
+ fatal_remove_cleanup((void (*)(void *))leave_non_blocking, NULL);
+ }
+}
+
+void enter_non_blocking()
+{
+ in_non_blocking_mode = 1;
+#if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN)
+ (void)fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
+#else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+ (void)fcntl(fileno(stdin), F_SETFL, O_NDELAY);
+#endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+ fatal_add_cleanup((void (*)(void *))leave_non_blocking, NULL);
+}
+
+#ifdef SIGWINCH
+/* Signal handler for the window change signal (SIGWINCH). This just
+ sets a flag indicating that the window has changed. */
+
+RETSIGTYPE window_change_handler(int sig)
+{
+ received_window_change_signal = 1;
+ signal(SIGWINCH, window_change_handler);
+}
+#endif /* SIGWINCH */
+
+/* Signal handler for signals that cause the program to terminate. These
+ signals must be trapped to restore terminal modes. */
+
+RETSIGTYPE signal_handler(int sig)
+{
+ if (in_raw_mode)
+ leave_raw_mode();
+ if (in_non_blocking_mode)
+ leave_non_blocking();
+ channel_stop_listening();
+ packet_close();
+ fatal("Killed by signal %d.", sig);
+}
+
+/* Returns current time in seconds from Jan 1, 1970 with the maximum available
+ resolution. */
+
+double get_current_time()
+{
+#ifdef HAVE_GETTIMEOFDAY
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+#else /* HAVE_GETTIMEOFDAY */
+ return (double)time(NULL);
+#endif /* HAVE_GETTIMEOFDAY */
+}
+
+/* This is called when the interactive is entered. This checks if there
+ is an EOF coming on stdin. We must check this explicitly, as select()
+ does not appear to wake up when redirecting from /dev/null. */
+
+void client_check_initial_eof_on_stdin()
+{
+ int len;
+ char buf[1];
+
+ /* If standard input is to be "redirected from /dev/null", we simply
+ mark that we have seen an EOF and send an EOF message to the server.
+ Otherwise, we try to read a single character; it appears that for some
+ files, such /dev/null, select() never wakes up for read for this
+ descriptor, which means that we never get EOF. This way we will get
+ the EOF if stdin comes from /dev/null or similar. */
+ if (stdin_null_flag)
+ {
+ /* Fake EOF on stdin. */
+ debug("Sending eof.");
+ stdin_eof = 1;
+ packet_start(SSH_CMSG_EOF);
+ packet_send();
+ }
+ else
+ {
+ /* Enter non-blocking mode for stdin. */
+ enter_non_blocking();
+
+ /* Check for immediate EOF on stdin. */
+ len = read(fileno(stdin), buf, 1);
+ if (len == 0)
+ {
+ /* EOF. Record that we have seen it and send EOF to server. */
+ debug("Sending eof.");
+ stdin_eof = 1;
+ packet_start(SSH_CMSG_EOF);
+ packet_send();
+ }
+ else
+ if (len > 0)
+ {
+ /* Got data. We must store the data in the buffer, and also
+ process it as an escape character if appropriate. */
+ if ((unsigned char)buf[0] == escape_char)
+ escape_pending = 1;
+ else
+ {
+ buffer_append(&stdin_buffer, buf, 1);
+ stdin_bytes += 1;
+ }
+ }
+
+ /* Leave non-blocking mode. */
+ leave_non_blocking();
+ }
+}
+
+/* Get packets from the connection input buffer, and process them as long
+ as there are packets available. */
+
+void client_process_buffered_input_packets()
+{
+ int type;
+ char *data;
+ unsigned int data_len;
+ int payload_len;
+
+ /* Process any buffered packets from the server. */
+ while (!quit_pending && (type = packet_read_poll(&payload_len)) != SSH_MSG_NONE)
+ {
+ switch (type)
+ {
+
+ case SSH_SMSG_STDOUT_DATA:
+ data = packet_get_string(&data_len);
+ packet_integrity_check(payload_len, 4 + data_len, type);
+ buffer_append(&stdout_buffer, data, data_len);
+ stdout_bytes += data_len;
+ memset(data, 0, data_len);
+ xfree(data);
+ break;
+
+ case SSH_SMSG_STDERR_DATA:
+ data = packet_get_string(&data_len);
+ packet_integrity_check(payload_len, 4 + data_len, type);
+ buffer_append(&stderr_buffer, data, data_len);
+ stdout_bytes += data_len;
+ memset(data, 0, data_len);
+ xfree(data);
+ break;
+
+ case SSH_SMSG_EXITSTATUS:
+ packet_integrity_check(payload_len, 4, type);
+ exit_status = packet_get_int();
+ /* Acknowledge the exit. */
+ packet_start(SSH_CMSG_EXIT_CONFIRMATION);
+ packet_send();
+ /* Must wait for packet to be sent since we are exiting the
+ loop. */
+ packet_write_wait();
+ /* Flag that we want to exit. */
+ quit_pending = 1;
+ break;
+
+ case SSH_SMSG_X11_OPEN:
+ x11_input_open(payload_len);
+ break;
+
+ case SSH_MSG_PORT_OPEN:
+ channel_input_port_open(payload_len);
+ break;
+
+ case SSH_SMSG_AGENT_OPEN:
+ packet_integrity_check(payload_len, 4, type);
+ auth_input_open_request();
+ break;
+
+ case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
+ packet_integrity_check(payload_len, 4 + 4, type);
+ channel_input_open_confirmation();
+ break;
+
+ case SSH_MSG_CHANNEL_OPEN_FAILURE:
+ packet_integrity_check(payload_len, 4, type);
+ channel_input_open_failure();
+ break;
+
+ case SSH_MSG_CHANNEL_DATA:
+ channel_input_data(payload_len);
+ break;
+
+ case SSH_MSG_CHANNEL_CLOSE:
+ packet_integrity_check(payload_len, 4, type);
+ channel_input_close();
+ break;
+
+ case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
+ packet_integrity_check(payload_len, 4, type);
+ channel_input_close_confirmation();
+ break;
+
+ default:
+ /* Any unknown packets received during the actual session
+ cause the session to terminate. This is intended to make
+ debugging easier since no confirmations are sent. Any
+ compatible protocol extensions must be negotiated during
+ the preparatory phase. */
+ packet_disconnect("Protocol error during session: type %d",
+ type);
+ }
+ }
+}
+
+/* Make packets from buffered stdin data, and buffer them for sending to
+ the connection. */
+
+void client_make_packets_from_stdin_data()
+{
+ unsigned int len;
+
+ /* Send buffered stdin data to the server. */
+ while (buffer_len(&stdin_buffer) > 0 &&
+ packet_not_very_much_data_to_write())
+ {
+ len = buffer_len(&stdin_buffer);
+ if (len > 32768)
+ len = 32768; /* Keep the packets at reasonable size. */
+ packet_start(SSH_CMSG_STDIN_DATA);
+ packet_put_string(buffer_ptr(&stdin_buffer), len);
+ packet_send();
+ buffer_consume(&stdin_buffer, len);
+ /* If we have a pending EOF, send it now. */
+ if (stdin_eof && buffer_len(&stdin_buffer) == 0)
+ {
+ packet_start(SSH_CMSG_EOF);
+ packet_send();
+ }
+ }
+}
+
+/* Checks if the client window has changed, and sends a packet about it to
+ the server if so. The actual change is detected elsewhere (by a software
+ interrupt on Unix); this just checks the flag and sends a message if
+ appropriate. */
+
+void client_check_window_change()
+{
+#ifdef SIGWINCH
+ /* Send possible window change message to the server. */
+ if (received_window_change_signal)
+ {
+ struct winsize ws;
+
+ /* Clear the window change indicator. */
+ received_window_change_signal = 0;
+
+ /* Read new window size. */
+ if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) >= 0)
+ {
+ /* Successful, send the packet now. */
+ packet_start(SSH_CMSG_WINDOW_SIZE);
+ packet_put_int(ws.ws_row);
+ packet_put_int(ws.ws_col);
+ packet_put_int(ws.ws_xpixel);
+ packet_put_int(ws.ws_ypixel);
+ packet_send();
+ }
+ }
+#endif /* SIGWINCH */
+}
+
+/* Waits until the client can do something (some data becomes available on
+ one of the file descriptors). */
+
+void client_wait_until_can_do_something(fd_set *readset, fd_set *writeset)
+{
+ /* Initialize select masks. */
+ FD_ZERO(readset);
+
+ /* Read from the connection, unless our buffers are full. */
+ if (buffer_len(&stdout_buffer) < buffer_high &&
+ buffer_len(&stderr_buffer) < buffer_high &&
+ channel_not_very_much_buffered_data())
+ FD_SET(connection_in, readset);
+
+ /* Read from stdin, unless we have seen EOF or have very much buffered
+ data to send to the server. */
+ if (!stdin_eof && packet_not_very_much_data_to_write())
+ FD_SET(fileno(stdin), readset);
+
+ FD_ZERO(writeset);
+
+ /* Add any selections by the channel mechanism. */
+ channel_prepare_select(readset, writeset);
+
+ /* Select server connection if have data to write to the server. */
+ if (packet_have_data_to_write())
+ FD_SET(connection_out, writeset);
+
+ /* Select stdout if have data in buffer. */
+ if (buffer_len(&stdout_buffer) > 0)
+ FD_SET(fileno(stdout), writeset);
+
+ /* Select stderr if have data in buffer. */
+ if (buffer_len(&stderr_buffer) > 0)
+ FD_SET(fileno(stderr), writeset);
+
+ /* Update maximum file descriptor number, if appropriate. */
+ if (channel_max_fd() > max_fd)
+ max_fd = channel_max_fd();
+
+ /* Wait for something to happen. This will suspend the process until
+ some selected descriptor can be read, written, or has some other
+ event pending. Note: if you want to implement SSH_MSG_IGNORE
+ messages to fool traffic analysis, this might be the place to do
+ it: just have a random timeout for the select, and send a random
+ SSH_MSG_IGNORE packet when the timeout expires. */
+ if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0)
+ {
+ char buf[100];
+ /* Some systems fail to clear these automatically. */
+ FD_ZERO(readset);
+ FD_ZERO(writeset);
+ if (errno == EINTR)
+ return;
+ /* Note: we might still have data in the buffers. */
+ sprintf(buf, "select: %.100s\r\n", strerror(errno));
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ stderr_bytes += strlen(buf);
+ quit_pending = 1;
+ }
+}
+
+void client_suspend_self()
+{
+#ifdef SIGWINCH
+ struct winsize oldws, newws;
+#endif /* SIGWINCH */
+
+ /* Flush stdout and stderr buffers. */
+ if (buffer_len(&stdout_buffer) > 0)
+ write(fileno(stdout),
+ buffer_ptr(&stdout_buffer),
+ buffer_len(&stdout_buffer));
+ if (buffer_len(&stderr_buffer) > 0)
+ write(fileno(stderr),
+ buffer_ptr(&stderr_buffer),
+ buffer_len(&stderr_buffer));
+
+ /* Leave raw mode. */
+ leave_raw_mode();
+
+ /* Free (and clear) the buffer to reduce the
+ amount of data that gets written to swap. */
+ buffer_free(&stdin_buffer);
+ buffer_free(&stdout_buffer);
+ buffer_free(&stderr_buffer);
+
+#ifdef SIGWINCH
+ /* Save old window size. */
+ ioctl(fileno(stdin), TIOCGWINSZ, &oldws);
+#endif /* SIGWINCH */
+
+ /* Send the suspend signal to the program
+ itself. */
+ kill(getpid(), SIGTSTP);
+
+#ifdef SIGWINCH
+ /* Check if the window size has changed. */
+ if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 &&
+ (oldws.ws_row != newws.ws_row || oldws.ws_col != newws.ws_col ||
+ oldws.ws_xpixel != newws.ws_xpixel ||
+ oldws.ws_ypixel != newws.ws_ypixel))
+ received_window_change_signal = 1;
+#endif /* SIGWINCH */
+
+ /* OK, we have been continued by the user.
+ Reinitialize buffers. */
+ buffer_init(&stdin_buffer);
+ buffer_init(&stdout_buffer);
+ buffer_init(&stderr_buffer);
+
+ /* Re-enter raw mode. */
+ enter_raw_mode();
+}
+
+void client_process_input(fd_set *readset)
+{
+ int len, pid;
+ char buf[8192], *s;
+
+ /* Read input from the server, and add any such data to the buffer of the
+ packet subsystem. */
+ if (FD_ISSET(connection_in, readset))
+ {
+ /* Read as much as possible. */
+ len = read(connection_in, buf, sizeof(buf));
+ if (len == 0)
+ {
+ /* Received EOF. The remote host has closed the connection. */
+ sprintf(buf, "Connection to %.300s closed by remote host.\r\n",
+ host);
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ stderr_bytes += strlen(buf);
+ quit_pending = 1;
+ return;
+ }
+
+ /* There is a kernel bug on Solaris that causes select to sometimes
+ wake up even though there is no data available. */
+ if (len < 0 && errno == EAGAIN)
+ len = 0;
+
+ if (len < 0)
+ {
+ /* An error has encountered. Perhaps there is a network
+ problem. */
+ sprintf(buf, "Read from remote host %.300s: %.100s\r\n",
+ host, strerror(errno));
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ stderr_bytes += strlen(buf);
+ quit_pending = 1;
+ return;
+ }
+ packet_process_incoming(buf, len);
+ }
+
+ /* Read input from stdin. */
+ if (FD_ISSET(fileno(stdin), readset))
+ {
+ /* Read as much as possible. */
+ len = read(fileno(stdin), buf, sizeof(buf));
+ if (len <= 0)
+ {
+ /* Received EOF or error. They are treated similarly,
+ except that an error message is printed if it was
+ an error condition. */
+ if (len < 0)
+ {
+ sprintf(buf, "read: %.100s\r\n", strerror(errno));
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ stderr_bytes += strlen(buf);
+ }
+ /* Mark that we have seen EOF. */
+ stdin_eof = 1;
+ /* Send an EOF message to the server unless there is data
+ in the buffer. If there is data in the buffer, no message
+ will be sent now. Code elsewhere will send the EOF
+ when the buffer becomes empty if stdin_eof is set. */
+ if (buffer_len(&stdin_buffer) == 0)
+ {
+ packet_start(SSH_CMSG_EOF);
+ packet_send();
+ }
+ }
+ else
+ if (escape_char == -1)
+ {
+ /* Normal successful read, and no escape character. Just
+ append the data to buffer. */
+ buffer_append(&stdin_buffer, buf, len);
+ stdin_bytes += len;
+ }
+ else
+ {
+ /* Normal, successful read. But we have an escape character
+ and have to process the characters one by one. */
+ unsigned int i;
+ for (i = 0; i < len; i++)
+ {
+ unsigned char ch;
+ /* Get one character at a time. */
+ ch = buf[i];
+
+ /* Check if we have a pending escape character. */
+ if (escape_pending)
+ {
+ /* We have previously seen an escape character. */
+ /* Clear the flag now. */
+ escape_pending = 0;
+ /* Process the escaped character. */
+ switch (ch)
+ {
+ case '.':
+ /* Terminate the connection. */
+ sprintf(buf, "%c.\r\n", escape_char);
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ stderr_bytes += strlen(buf);
+ quit_pending = 1;
+ return;
+
+ case 'Z' - 64:
+ /* Suspend the program. */
+ /* Print a message to that effect to the user. */
+ sprintf(buf, "%c^Z\r\n", escape_char);
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ stderr_bytes += strlen(buf);
+
+ /* Restore terminal modes and suspend. */
+ client_suspend_self();
+
+ /* We have been continued. */
+ continue;
+
+ case '&':
+ /* Detach the program (continue to serve connections,
+ but put in background and no more new
+ connections). */
+ if (!stdin_eof)
+ {
+ /* Sending SSH_CMSG_EOF alone does not always
+ appear to be enough. So we try to send an
+ EOF character first. */
+ packet_start(SSH_CMSG_STDIN_DATA);
+ packet_put_string("\004", 1);
+ packet_send();
+ /* Close stdin. */
+ stdin_eof = 1;
+ if (buffer_len(&stdin_buffer) == 0)
+ {
+ packet_start(SSH_CMSG_EOF);
+ packet_send();
+ }
+ }
+ /* Restore tty modes. */
+ leave_raw_mode();
+
+ /* Stop listening for new connections. */
+ channel_stop_listening();
+
+ printf("%c& [backgrounded]\n", escape_char);
+
+ /* Fork into background. */
+ pid = fork();
+ if (pid < 0)
+ {
+ error("fork: %.100s", strerror(errno));
+ continue;
+ }
+ if (pid != 0)
+ { /* This is the parent. */
+ /* The parent just exits. */
+ exit(0);
+ }
+
+ /* The child continues serving connections. */
+ continue;
+
+ case '?':
+ sprintf(buf, "%c?\r\n\
+Supported escape sequences:\r\n\
+~. - terminate connection\r\n\
+~^Z - suspend ssh\r\n\
+~# - list forwarded connections\r\n\
+~& - background ssh (when waiting for connections to terminate)\r\n\
+~? - this message\r\n\
+~~ - send the escape character by typing it twice\r\n\
+(Note that escapes are only recognized immediately after newline.)\r\n",
+ escape_char);
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ continue;
+
+ case '#':
+ sprintf(buf, "%c#\r\n", escape_char);
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ s = channel_open_message();
+ buffer_append(&stderr_buffer, s, strlen(s));
+ xfree(s);
+ continue;
+
+ default:
+ if (ch != escape_char)
+ {
+ /* Escape character followed by non-special
+ character. Append both to the input
+ buffer. */
+ buf[0] = escape_char;
+ buf[1] = ch;
+ buffer_append(&stdin_buffer, buf, 2);
+ stdin_bytes += 2;
+ continue;
+ }
+ /* Note that escape character typed twice falls through
+ here; the latter gets processed as a normal
+ character below. */
+ break;
+ }
+ }
+ else
+ {
+ /* The previous character was not an escape char.
+ Check if this is an escape. */
+ if (last_was_cr && ch == escape_char)
+ {
+ /* It is. Set the flag and continue to next
+ character. */
+ escape_pending = 1;
+ continue;
+ }
+ }
+
+ /* Normal character. Record whether it was a newline,
+ and append it to the buffer. */
+ last_was_cr = (ch == '\r' || ch == '\n');
+ buf[0] = ch;
+ buffer_append(&stdin_buffer, buf, 1);
+ stdin_bytes += 1;
+ continue;
+ }
+ }
+ }
+}
+
+void client_process_output(fd_set *writeset)
+{
+ int len;
+ char buf[100];
+
+ /* Write buffered output to stdout. */
+ if (FD_ISSET(fileno(stdout), writeset))
+ {
+ /* Write as much data as possible. */
+ len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
+ buffer_len(&stdout_buffer));
+ if (len <= 0)
+ {
+ if (errno == EAGAIN)
+ len = 0;
+ else
+ {
+ /* An error or EOF was encountered. Put an error message
+ to stderr buffer. */
+ sprintf(buf, "write stdout: %.50s\r\n", strerror(errno));
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ stderr_bytes += strlen(buf);
+ quit_pending = 1;
+ return;
+ }
+ }
+ /* Consume printed data from the buffer. */
+ buffer_consume(&stdout_buffer, len);
+ }
+
+ /* Write buffered output to stderr. */
+ if (FD_ISSET(fileno(stderr), writeset))
+ {
+ /* Write as much data as possible. */
+ len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
+ buffer_len(&stderr_buffer));
+ if (len <= 0)
+ if (errno == EAGAIN)
+ len = 0;
+ else
+ {
+ /* EOF or error, but can't even print error message. */
+ quit_pending = 1;
+ return;
+ }
+ /* Consume printed characters from the buffer. */
+ buffer_consume(&stderr_buffer, len);
+ }
+}
+
+/* Implements the interactive session with the server. This is called
+ after the user has been authenticated, and a command has been
+ started on the remote host. If escape_char != -1, it is the character
+ used as an escape character for terminating or suspending the
+ session. */
+
+int client_loop(int have_pty, int escape_char_arg)
+{
+ double start_time, total_time;
+ int len;
+ char buf[100];
+
+ debug("Entering interactive session.");
+
+ start_time = get_current_time();
+
+ /* Initialize variables. */
+ escape_pending = 0;
+ last_was_cr = 1;
+ exit_status = -1;
+ stdin_eof = 0;
+ buffer_high = 64 * 1024;
+ connection_in = packet_get_connection_in();
+ connection_out = packet_get_connection_out();
+ max_fd = connection_in;
+ if (connection_out > max_fd)
+ max_fd = connection_out;
+ stdin_bytes = 0;
+ stdout_bytes = 0;
+ stderr_bytes = 0;
+ quit_pending = 0;
+ escape_char = escape_char_arg;
+
+ /* Initialize buffers. */
+ buffer_init(&stdin_buffer);
+ buffer_init(&stdout_buffer);
+ buffer_init(&stderr_buffer);
+
+ /* Set signal handlers to restore non-blocking mode. */
+ signal(SIGINT, signal_handler);
+ signal(SIGQUIT, signal_handler);
+ signal(SIGTERM, signal_handler);
+ signal(SIGPIPE, SIG_IGN);
+#ifdef SIGWINCH
+ if (have_pty)
+ signal(SIGWINCH, window_change_handler);
+#endif /* SIGWINCH */
+
+ /* Enter raw mode if have a pseudo terminal. */
+ if (have_pty)
+ enter_raw_mode();
+
+ /* Check if we should immediately send of on stdin. */
+ client_check_initial_eof_on_stdin();
+
+ /* Main loop of the client for the interactive session mode. */
+ while (!quit_pending)
+ {
+ fd_set readset, writeset;
+
+ /* Precess buffered packets sent by the server. */
+ client_process_buffered_input_packets();
+
+ /* Make packets of buffered stdin data, and buffer them for sending
+ to the server. */
+ client_make_packets_from_stdin_data();
+
+ /* Make packets from buffered channel data, and buffer them for sending
+ to the server. */
+ if (packet_not_very_much_data_to_write())
+ channel_output_poll();
+
+ /* Check if the window size has changed, and buffer a message about
+ it to the server if so. */
+ client_check_window_change();
+
+ if (quit_pending)
+ break;
+
+ /* Wait until we have something to do (something becomes available
+ on one of the descriptors). */
+ client_wait_until_can_do_something(&readset, &writeset);
+
+ if (quit_pending)
+ break;
+
+ /* Do channel operations. */
+ channel_after_select(&readset, &writeset);
+
+ /* Process input from the connection and from stdin. Buffer any data
+ that is available. */
+ client_process_input(&readset);
+
+ /* Process output to stdout and stderr. Output to the connection
+ is processed elsewhere (above). */
+ client_process_output(&writeset);
+
+ /* Send as much buffered packet data as possible to the sender. */
+ if (FD_ISSET(connection_out, &writeset))
+ packet_write_poll();
+ }
+
+ /* Terminate the session. */
+
+#ifdef SIGWINCH
+ /* Stop watching for window change. */
+ if (have_pty)
+ signal(SIGWINCH, SIG_DFL);
+#endif /* SIGWINCH */
+
+ /* Stop listening for connections. */
+ channel_stop_listening();
+
+ /* In interactive mode (with pseudo tty) display a message indicating that
+ the connection has been closed. */
+ if (have_pty && !quiet_flag)
+ {
+ sprintf(buf, "Connection to %.64s closed.\r\n", host);
+ buffer_append(&stderr_buffer, buf, strlen(buf));
+ stderr_bytes += strlen(buf);
+ }
+
+ /* Output any buffered data for stdout. */
+ while (buffer_len(&stdout_buffer) > 0)
+ {
+ len = write(fileno(stdout), buffer_ptr(&stdout_buffer),
+ buffer_len(&stdout_buffer));
+ if (len <= 0)
+ {
+ error("Write failed flushing stdout buffer.");
+ break;
+ }
+ buffer_consume(&stdout_buffer, len);
+ }
+
+ /* Output any buffered data for stderr. */
+ while (buffer_len(&stderr_buffer) > 0)
+ {
+ len = write(fileno(stderr), buffer_ptr(&stderr_buffer),
+ buffer_len(&stderr_buffer));
+ if (len <= 0)
+ {
+ error("Write failed flushing stderr buffer.");
+ break;
+ }
+ buffer_consume(&stderr_buffer, len);
+ }
+
+ /* Leave raw mode. */
+ if (have_pty)
+ leave_raw_mode();
+
+ /* Clear and free any buffers. */
+ memset(buf, 0, sizeof(buf));
+ buffer_free(&stdin_buffer);
+ buffer_free(&stdout_buffer);
+ buffer_free(&stderr_buffer);
+
+ /* Report bytes transferred, and transfer rates. */
+ total_time = get_current_time() - start_time;
+ debug("Transferred: stdin %lu, stdout %lu, stderr %lu bytes in %.1f seconds",
+ stdin_bytes, stdout_bytes, stderr_bytes, total_time);
+ if (total_time > 0)
+ debug("Bytes per second: stdin %.1f, stdout %.1f, stderr %.1f",
+ stdin_bytes / total_time, stdout_bytes / total_time,
+ stderr_bytes / total_time);
+
+ /* Return the exit status of the program. */
+ debug("Exit status %d", exit_status);
+ return exit_status;
+}
diff --git a/usr.bin/ssh/compress.c b/usr.bin/ssh/compress.c
new file mode 100644
index 00000000000..a6e2f0d4ae0
--- /dev/null
+++ b/usr.bin/ssh/compress.c
@@ -0,0 +1,160 @@
+/*
+
+compress.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Oct 25 22:12:46 1995 ylo
+
+Interface to packet compression for ssh.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: compress.c,v 1.1 1999/09/26 20:53:34 deraadt Exp $");
+
+#include "ssh.h"
+#include "buffer.h"
+#include "zlib.h"
+
+static z_stream incoming_stream;
+static z_stream outgoing_stream;
+
+/* Initializes compression; level is compression level from 1 to 9 (as in
+ gzip). */
+
+void buffer_compress_init(int level)
+{
+ debug("Enabling compression at level %d.", level);
+ if (level < 1 || level > 9)
+ fatal("Bad compression level %d.", level);
+ inflateInit(&incoming_stream);
+ deflateInit(&outgoing_stream, level);
+}
+
+/* Frees any data structures allocated for compression. */
+
+void buffer_compress_uninit()
+{
+ debug("compress outgoing: raw data %lu, compressed %lu, factor %.2f",
+ outgoing_stream.total_in, outgoing_stream.total_out,
+ outgoing_stream.total_in == 0 ? 0.0 :
+ (double)outgoing_stream.total_out / outgoing_stream.total_in);
+ debug("compress incoming: raw data %lu, compressed %lu, factor %.2f",
+ incoming_stream.total_out, incoming_stream.total_in,
+ incoming_stream.total_out == 0 ? 0.0 :
+ (double)incoming_stream.total_in / incoming_stream.total_out);
+ inflateEnd(&incoming_stream);
+ deflateEnd(&outgoing_stream);
+}
+
+/* Compresses the contents of input_buffer into output_buffer. All
+ packets compressed using this function will form a single
+ compressed data stream; however, data will be flushed at the end of
+ every call so that each output_buffer can be decompressed
+ independently (but in the appropriate order since they together
+ form a single compression stream) by the receiver. This appends
+ the compressed data to the output buffer. */
+
+void buffer_compress(Buffer *input_buffer, Buffer *output_buffer)
+{
+ char buf[4096];
+ int status;
+
+ /* This case is not handled below. */
+ if (buffer_len(input_buffer) == 0)
+ return;
+
+ /* Input is the contents of the input buffer. */
+ outgoing_stream.next_in = buffer_ptr(input_buffer);
+ outgoing_stream.avail_in = buffer_len(input_buffer);
+
+ /* Loop compressing until deflate() returns with avail_out != 0. */
+ do
+ {
+ /* Set up fixed-size output buffer. */
+ outgoing_stream.next_out = buf;
+ outgoing_stream.avail_out = sizeof(buf);
+
+ /* Compress as much data into the buffer as possible. */
+ status = deflate(&outgoing_stream, Z_PARTIAL_FLUSH);
+ switch (status)
+ {
+ case Z_OK:
+ /* Append compressed data to output_buffer. */
+ buffer_append(output_buffer, buf,
+ sizeof(buf) - outgoing_stream.avail_out);
+ break;
+ case Z_STREAM_END:
+ fatal("buffer_compress: deflate returned Z_STREAM_END");
+ /*NOTREACHED*/
+ case Z_STREAM_ERROR:
+ fatal("buffer_compress: deflate returned Z_STREAM_ERROR");
+ /*NOTREACHED*/
+ case Z_BUF_ERROR:
+ fatal("buffer_compress: deflate returned Z_BUF_ERROR");
+ /*NOTREACHED*/
+ default:
+ fatal("buffer_compress: deflate returned %d", status);
+ /*NOTREACHED*/
+ }
+ }
+ while (outgoing_stream.avail_out == 0);
+}
+
+/* Uncompresses the contents of input_buffer into output_buffer. All
+ packets uncompressed using this function will form a single
+ compressed data stream; however, data will be flushed at the end of
+ every call so that each output_buffer. This must be called for the
+ same size units that the buffer_compress was called, and in the
+ same order that buffers compressed with that. This appends the
+ uncompressed data to the output buffer. */
+
+void buffer_uncompress(Buffer *input_buffer, Buffer *output_buffer)
+{
+ char buf[4096];
+ int status;
+
+ incoming_stream.next_in = buffer_ptr(input_buffer);
+ incoming_stream.avail_in = buffer_len(input_buffer);
+
+ incoming_stream.next_out = buf;
+ incoming_stream.avail_out = sizeof(buf);
+
+ for (;;)
+ {
+ status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
+ switch (status)
+ {
+ case Z_OK:
+ buffer_append(output_buffer, buf,
+ sizeof(buf) - incoming_stream.avail_out);
+ incoming_stream.next_out = buf;
+ incoming_stream.avail_out = sizeof(buf);
+ break;
+ case Z_STREAM_END:
+ fatal("buffer_uncompress: inflate returned Z_STREAM_END");
+ /*NOTREACHED*/
+ case Z_DATA_ERROR:
+ fatal("buffer_uncompress: inflate returned Z_DATA_ERROR");
+ /*NOTREACHED*/
+ case Z_STREAM_ERROR:
+ fatal("buffer_uncompress: inflate returned Z_STREAM_ERROR");
+ /*NOTREACHED*/
+ case Z_BUF_ERROR:
+ /* Comments in zlib.h say that we should keep calling inflate()
+ until we get an error. This appears to be the error that we
+ get. */
+ return;
+ case Z_MEM_ERROR:
+ fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");
+ /*NOTREACHED*/
+ default:
+ fatal("buffer_uncompress: inflate returned %d", status);
+ }
+ }
+}
+
diff --git a/usr.bin/ssh/compress.h b/usr.bin/ssh/compress.h
new file mode 100644
index 00000000000..c46e2ea7025
--- /dev/null
+++ b/usr.bin/ssh/compress.h
@@ -0,0 +1,46 @@
+/*
+
+compress.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Oct 25 22:12:46 1995 ylo
+
+Interface to packet compression for ssh.
+
+*/
+
+/* RCSID("$Id: compress.h,v 1.1 1999/09/26 20:53:34 deraadt Exp $"); */
+
+#ifndef COMPRESS_H
+#define COMPRESS_H
+
+/* Initializes compression; level is compression level from 1 to 9 (as in
+ gzip). */
+void buffer_compress_init(int level);
+
+/* Frees any data structures allocated by buffer_compress_init. */
+void buffer_compress_uninit();
+
+/* Compresses the contents of input_buffer into output_buffer. All
+ packets compressed using this function will form a single
+ compressed data stream; however, data will be flushed at the end of
+ every call so that each output_buffer can be decompressed
+ independently (but in the appropriate order since they together
+ form a single compression stream) by the receiver. This appends
+ the compressed data to the output buffer. */
+void buffer_compress(Buffer *input_buffer, Buffer *output_buffer);
+
+/* Uncompresses the contents of input_buffer into output_buffer. All
+ packets uncompressed using this function will form a single
+ compressed data stream; however, data will be flushed at the end of
+ every call so that each output_buffer. This must be called for the
+ same size units that the buffer_compress was called, and in the
+ same order that buffers compressed with that. This appends the
+ uncompressed data to the output buffer. */
+void buffer_uncompress(Buffer *input_buffer, Buffer *output_buffer);
+
+#endif /* COMPRESS_H */
diff --git a/usr.bin/ssh/config.cache b/usr.bin/ssh/config.cache
new file mode 100644
index 00000000000..3e1490d3a6b
--- /dev/null
+++ b/usr.bin/ssh/config.cache
@@ -0,0 +1,102 @@
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+ac_cv_c_bigendian=${ac_cv_c_bigendian=no}
+ac_cv_c_const=${ac_cv_c_const=yes}
+ac_cv_c_inline=${ac_cv_c_inline=inline}
+ac_cv_func__getpty=${ac_cv_func__getpty=no}
+ac_cv_func_clock=${ac_cv_func_clock=yes}
+ac_cv_func_fchmod=${ac_cv_func_fchmod=yes}
+ac_cv_func_getdtablesize=${ac_cv_func_getdtablesize=yes}
+ac_cv_func_gethostname=${ac_cv_func_gethostname=yes}
+ac_cv_func_getrusage=${ac_cv_func_getrusage=yes}
+ac_cv_func_gettimeofday=${ac_cv_func_gettimeofday=yes}
+ac_cv_func_initgroups=${ac_cv_func_initgroups=yes}
+ac_cv_func_innetgr=${ac_cv_func_innetgr=yes}
+ac_cv_func_memcpy=${ac_cv_func_memcpy=yes}
+ac_cv_func_memmove=${ac_cv_func_memmove=yes}
+ac_cv_func_openpty=${ac_cv_func_openpty=no}
+ac_cv_func_popen=${ac_cv_func_popen=yes}
+ac_cv_func_putenv=${ac_cv_func_putenv=yes}
+ac_cv_func_random=${ac_cv_func_random=yes}
+ac_cv_func_remove=${ac_cv_func_remove=yes}
+ac_cv_func_seteuid=${ac_cv_func_seteuid=yes}
+ac_cv_func_setlogin=${ac_cv_func_setlogin=yes}
+ac_cv_func_setluid=${ac_cv_func_setluid=no}
+ac_cv_func_setrlimit=${ac_cv_func_setrlimit=yes}
+ac_cv_func_setsid=${ac_cv_func_setsid=yes}
+ac_cv_func_socketpair=${ac_cv_func_socketpair=yes}
+ac_cv_func_strchr=${ac_cv_func_strchr=yes}
+ac_cv_func_strerror=${ac_cv_func_strerror=yes}
+ac_cv_func_times=${ac_cv_func_times=yes}
+ac_cv_func_ulimit=${ac_cv_func_ulimit=no}
+ac_cv_func_umask=${ac_cv_func_umask=yes}
+ac_cv_func_vhangup=${ac_cv_func_vhangup=no}
+ac_cv_func_vsnprintf=${ac_cv_func_vsnprintf=yes}
+ac_cv_header_dirent_dirent_h=${ac_cv_header_dirent_dirent_h=yes}
+ac_cv_header_gmp_h=${ac_cv_header_gmp_h=yes}
+ac_cv_header_krb_h=${ac_cv_header_krb_h=no}
+ac_cv_header_lastlog_h=${ac_cv_header_lastlog_h=no}
+ac_cv_header_netinet_in_systm_h=${ac_cv_header_netinet_in_systm_h=yes}
+ac_cv_header_paths_h=${ac_cv_header_paths_h=yes}
+ac_cv_header_rusage_h=${ac_cv_header_rusage_h=no}
+ac_cv_header_sgtty_h=${ac_cv_header_sgtty_h=yes}
+ac_cv_header_stat_broken=${ac_cv_header_stat_broken=no}
+ac_cv_header_stdc=${ac_cv_header_stdc=yes}
+ac_cv_header_sys_filio_h=${ac_cv_header_sys_filio_h=yes}
+ac_cv_header_sys_ioctl_h=${ac_cv_header_sys_ioctl_h=yes}
+ac_cv_header_sys_select_h=${ac_cv_header_sys_select_h=yes}
+ac_cv_header_sys_time_h=${ac_cv_header_sys_time_h=yes}
+ac_cv_header_sys_wait_h=${ac_cv_header_sys_wait_h=yes}
+ac_cv_header_termios_h=${ac_cv_header_termios_h=yes}
+ac_cv_header_time=${ac_cv_header_time=yes}
+ac_cv_header_ulimit_h=${ac_cv_header_ulimit_h=no}
+ac_cv_header_unistd_h=${ac_cv_header_unistd_h=yes}
+ac_cv_header_usersec_h=${ac_cv_header_usersec_h=no}
+ac_cv_header_utime_h=${ac_cv_header_utime_h=yes}
+ac_cv_header_utmp_h=${ac_cv_header_utmp_h=yes}
+ac_cv_header_utmpx_h=${ac_cv_header_utmpx_h=no}
+ac_cv_header_zlib_h=${ac_cv_header_zlib_h=yes}
+ac_cv_lib_c_crypt=${ac_cv_lib_c_crypt=yes}
+ac_cv_lib_des_main=${ac_cv_lib_des_main=yes}
+ac_cv_lib_dir_opendir=${ac_cv_lib_dir_opendir=no}
+ac_cv_lib_gmp_main=${ac_cv_lib_gmp_main=yes}
+ac_cv_lib_krb_main=${ac_cv_lib_krb_main=yes}
+ac_cv_lib_nsl_main=${ac_cv_lib_nsl_main=no}
+ac_cv_lib_socket_socket=${ac_cv_lib_socket_socket=no}
+ac_cv_lib_sun_getpwnam=${ac_cv_lib_sun_getpwnam=no}
+ac_cv_lib_util_login=${ac_cv_lib_util_login=yes}
+ac_cv_lib_z_main=${ac_cv_lib_z_main=yes}
+ac_cv_path_RSH_PATH=${ac_cv_path_RSH_PATH=/usr/bin/rsh}
+ac_cv_path_WISH=${ac_cv_path_WISH=/usr/bin/true}
+ac_cv_path_XAUTH_PATH=${ac_cv_path_XAUTH_PATH=/usr/X11R6/bin/xauth}
+ac_cv_path_install=${ac_cv_path_install='/usr/bin/install -c'}
+ac_cv_prog_CC=${ac_cv_prog_CC=gcc}
+ac_cv_prog_CPP=${ac_cv_prog_CPP='gcc -E'}
+ac_cv_prog_LN_S=${ac_cv_prog_LN_S='ln -s'}
+ac_cv_prog_MAKEDEP=${ac_cv_prog_MAKEDEP=makedepend}
+ac_cv_prog_RANLIB=${ac_cv_prog_RANLIB=ranlib}
+ac_cv_prog_cc_cross=${ac_cv_prog_cc_cross=no}
+ac_cv_prog_cc_g=${ac_cv_prog_cc_g=yes}
+ac_cv_prog_cc_works=${ac_cv_prog_cc_works=yes}
+ac_cv_prog_gcc=${ac_cv_prog_gcc=yes}
+ac_cv_sizeof_int=${ac_cv_sizeof_int=4}
+ac_cv_sizeof_long=${ac_cv_sizeof_long=4}
+ac_cv_sizeof_short=${ac_cv_sizeof_short=2}
+ac_cv_struct_st_blksize=${ac_cv_struct_st_blksize=yes}
+ac_cv_type_mode_t=${ac_cv_type_mode_t=yes}
+ac_cv_type_off_t=${ac_cv_type_off_t=yes}
+ac_cv_type_signal=${ac_cv_type_signal=void}
+ac_cv_type_size_t=${ac_cv_type_size_t=yes}
+ac_cv_type_uid_t=${ac_cv_type_uid_t=yes}
diff --git a/usr.bin/ssh/config.guess b/usr.bin/ssh/config.guess
new file mode 100644
index 00000000000..72f934d4003
--- /dev/null
+++ b/usr.bin/ssh/config.guess
@@ -0,0 +1,1012 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998, 1999 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Written by Per Bothner <bothner@cygnus.com>.
+# The master version of this file is at the FSF in /home/gd/gnu/lib.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit system type (host/target name).
+#
+# Only a few systems have been added to this list; please add others
+# (but try to keep the structure clean).
+#
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 8/24/94.)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ cat <<EOF >dummy.s
+ .globl main
+ .ent main
+main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than generic posix subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname
+ # instead of the specific alpha model.
+ echo alpha-pc-interix
+ exit 0;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-cbm-sysv4
+ exit 0;;
+ amiga:NetBSD:*:*)
+ echo m68k-cbm-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ arc64:OpenBSD:*:*)
+ echo mips64el-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hkmips:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mips-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ arm32:NetBSD:*:*)
+ echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ SR2?01:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:NetBSD:*:*)
+ echo m68k-atari-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:NetBSD:*:*)
+ echo m68k-sun-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3*:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:NetBSD:*:*)
+ echo m68k-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ sed 's/^ //' << EOF >dummy.c
+ int main (argc, argv) int argc; char **argv; {
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy \
+ && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \
+ -o ${TARGET_BINARY_INTERFACE}x = x ] ; then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i?86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ sed 's/^ //' << EOF >dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:4)
+ if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=4.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ *9??*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9] )
+
+ sed 's/^ //' << EOF >dummy.c
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (${CC-cc} dummy.c -o dummy 2>/dev/null ) && HP_ARCH=`./dummy`
+ rm -f dummy.c dummy
+ esac
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ sed 's/^ //' << EOF >dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i?86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ hppa*:OpenBSD:*:*)
+ echo hppa-unknown-openbsd
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*X-MP:*:*:*)
+ echo xmp-cray-unicos
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE}
+ exit 0 ;;
+ CRAY-2:*:*:*)
+ echo cray2-cray-unicos
+ exit 0 ;;
+ F300:UNIX_System_V:*:*)
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ F301:UNIX_System_V:*:*)
+ echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'`
+ exit 0 ;;
+ hp3[0-9][05]:NetBSD:*:*)
+ echo m68k-hp-netbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ if test -x /usr/bin/objformat -a "elf" = "`/usr/bin/objformat`"; then
+ echo ${UNAME_MACHINE}-unknown-freebsdelf
+ else
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
+ fi
+ exit 0 ;;
+ *:NetBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin32
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than generic posix subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # change UNAME_MACHINE based on the output of uname instead of
+ # i386?
+ echo i386-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin32
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ *:Linux:*:*)
+ # uname on the ARM produces all sorts of strangeness, and we need to
+ # filter it out.
+ case "$UNAME_MACHINE" in
+ armv*) UNAME_MACHINE=$UNAME_MACHINE ;;
+ arm* | sa110*) UNAME_MACHINE="arm" ;;
+ esac
+
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us.
+ ld_help_string=`ld --help 2>&1`
+ ld_supported_emulations=`echo $ld_help_string \
+ | sed -ne '/supported emulations:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported emulations: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_emulations" in
+ i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;;
+ i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;;
+ sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ armlinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;;
+ elf32ppc | elf32ppclinux)
+ # Determine Lib Version
+ cat >dummy.c <<EOF
+#include <features.h>
+#if defined(__GLIBC__)
+extern char __libc_version[];
+extern char __libc_release[];
+#endif
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#if defined(__GLIBC__)
+ printf("%s %s\n", __libc_version, __libc_release);
+#else
+ printf("unkown\n");
+#endif
+ return 0;
+}
+EOF
+ LIBC=""
+ ${CC-cc} dummy.c -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy | grep 1\.99 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="libc1"
+ fi
+ fi
+ rm -f dummy.c dummy
+ echo powerpc-unknown-linux-gnu${LIBC} ; exit 0 ;;
+ esac
+
+ if test "${UNAME_MACHINE}" = "alpha" ; then
+ sed 's/^ //' <<EOF >dummy.s
+ .globl main
+ .ent main
+ main:
+ .frame \$30,0,\$26,0
+ .prologue 0
+ .long 0x47e03d80 # implver $0
+ lda \$2,259
+ .long 0x47e20c21 # amask $2,$1
+ srl \$1,8,\$2
+ sll \$2,2,\$2
+ sll \$0,3,\$0
+ addl \$1,\$0,\$0
+ addl \$2,\$0,\$0
+ ret \$31,(\$26),1
+ .end main
+EOF
+ LIBC=""
+ ${CC-cc} dummy.s -o dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./dummy
+ case "$?" in
+ 7)
+ UNAME_MACHINE="alpha"
+ ;;
+ 15)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 14)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 10)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 16)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ esac
+
+ objdump --private-headers dummy | \
+ grep ld.so.1 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="libc1"
+ fi
+ fi
+ rm -f dummy.s dummy
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0
+ elif test "${UNAME_MACHINE}" = "mips" ; then
+ cat >dummy.c <<EOF
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __MIPSEB__
+ printf ("%s-unknown-linux-gnu\n", argv[1]);
+#endif
+#ifdef __MIPSEL__
+ printf ("%sel-unknown-linux-gnu\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ else
+ # Either a pre-BFD a.out linker (linux-gnuoldld)
+ # or one that does not give us useful --help.
+ # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout.
+ # If ld does not provide *any* "supported emulations:"
+ # that means it is gnuoldld.
+ echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
+ test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0
+
+ case "${UNAME_MACHINE}" in
+ i?86)
+ VENDOR=pc;
+ ;;
+ *)
+ VENDOR=unknown;
+ ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ cat >dummy.c <<EOF
+#include <features.h>
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#ifdef __ELF__
+# ifdef __GLIBC__
+# if __GLIBC__ >= 2
+ printf ("%s-${VENDOR}-linux-gnu\n", argv[1]);
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+# else
+ printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]);
+# endif
+#else
+ printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
+ rm -f dummy.c dummy
+ fi ;;
+# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
+# are messed up and put the nodename in both sysname and nodename.
+ i?86:DYNIX/ptx:4*:*)
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i?86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*)
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ i?86:*:5:7*)
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+# 5.0.4c returns "Pent II". 5.0.5 returns PentII
+ (/bin/uname -X|egrep '^Machine.*Pent.*II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}${UNAME_VERSION}-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ i?86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|egrep '^Machine.*PentII' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pent II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ pc:*:*:*)
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i?86:LynxOS:2.*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:*:6*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+cat >dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+ printf ("vax-dec-bsd\n"); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
+rm -f dummy.c dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+#echo '(Unable to guess system type)' 1>&2
+
+exit 1
diff --git a/usr.bin/ssh/config.h b/usr.bin/ssh/config.h
new file mode 100644
index 00000000000..e4d202f9122
--- /dev/null
+++ b/usr.bin/ssh/config.h
@@ -0,0 +1,443 @@
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+/*
+
+acconfig.h - template used by autoheader to create config.h.in
+config.h.in - used by autoconf to create config.h
+config.h - created by autoconf; contains defines generated by autoconf
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>
+
+*/
+
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
+
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define if your struct stat has st_blksize. */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef mode_t */
+
+/* Define if your C compiler doesn't accept -c and -o together. */
+/* #undef NO_MINUS_C_MINUS_O */
+
+/* Define if your Fortran 77 compiler doesn't accept -c and -o together. */
+/* #undef F77_NO_MINUS_C_MINUS_O */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to the type of arg1 for select(). */
+/* #undef SELECT_TYPE_ARG1 */
+
+/* Define to the type of args 2, 3 and 4 for select(). */
+/* #undef SELECT_TYPE_ARG234 */
+
+/* Define to the type of arg5 for select(). */
+/* #undef SELECT_TYPE_ARG5 */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+/* Define if your processor stores words with the most significant
+ byte first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define if you have SYSV-style /dev/ptmx and /dev/pts/. */
+/* #undef HAVE_DEV_PTMX */
+
+/* Define if you have /dev/pts and /dev/ptc devices (as in AIX). */
+/* #undef HAVE_DEV_PTS_AND_PTC */
+
+/* Define if you have shadow passwords in /etc/security/passwd (AIX style). */
+/* #undef HAVE_ETC_SECURITY_PASSWD */
+
+/* Define if you have shadow passwords in /etc/security/passwd.adjunct
+ (SunOS style). */
+/* #undef HAVE_ETC_SECURITY_PASSWD_ADJUNCT */
+
+
+/* Define if you have OSF1 C2 security installed on the system */
+/* #undef HAVE_OSF1_C2_SECURITY */
+
+/* Define if you have shadow passwords in /etc/shadow (Solaris style). */
+/* #undef HAVE_ETC_SHADOW */
+
+/* Define if you have system login defaults in /etc/default/login. */
+/* #undef HAVE_ETC_DEFAULT_LOGIN */
+
+/* Define if utmp structure has host field. */
+#define HAVE_HOST_IN_UTMP 1
+
+/* Define if utmp structure has addr field. */
+/* #undef HAVE_ADDR_IN_UTMP */
+
+/* Define if utmp structure has id field. */
+/* #undef HAVE_ID_IN_UTMP */
+
+/* Define if utmp structure has name field. */
+#define HAVE_NAME_IN_UTMP 1
+
+/* Define if utmp structure has pid field. */
+/* #undef HAVE_PID_IN_UTMP */
+
+/* Define if utmpx structure has ut_session. */
+/* #undef HAVE_UT_SESSION */
+
+/* Define if utmpx structure has ut_syslen. */
+/* #undef HAVE_UT_SYSLEN */
+
+/* Define if /var/adm/lastlog or whatever it is called is a directory
+ (e.g. SGI IRIX). */
+/* #undef LASTLOG_IS_DIR */
+
+/* Define to use RSAREF. */
+/* #undef RSAREF */
+
+/* Define to use SSL. */
+#define DO_SSL 1
+
+/* Define this to be the path of the rsh program to support executing rsh. */
+#define RSH_PATH "/usr/bin/rsh"
+
+/* Define this to be the path of the xauth program. */
+#define XAUTH_PATH "/usr/X11R6/bin/xauth"
+
+/* Default path for utmp. Determined by configure. */
+#define SSH_UTMP "/var/run/utmp"
+
+/* Default path for wtmp. Determined by configure. */
+#define SSH_WTMP "/var/log/wtmp"
+
+/* Default path for lastlog. Determined by configure. */
+#define SSH_LASTLOG "/var/log/lastlog"
+
+/* This is defined if we found a lastlog file. The presence of lastlog.h
+ alone is not a sufficient indicator (at least newer BSD systems have
+ lastlog but no lastlog.h. */
+#define HAVE_LASTLOG 1
+
+/* Define this if libutil.a contains BSD 4.4 compatible login(), logout(),
+ and logwtmp() calls. */
+#define HAVE_LIBUTIL_LOGIN 1
+
+/* Location of system mail spool directory. */
+#define MAIL_SPOOL_DIRECTORY "/var/mail"
+
+/* Defined if mail goes to $HOME/newmail instead of a global mail spool. */
+/* #undef HAVE_TILDE_NEWMAIL */
+
+/* Define this to be the default user path if you don't like the default.
+ See the --with-path=<path> configure option. */
+/* #undef DEFAULT_PATH */
+
+/* Define this if O_NONBLOCK does not work on your system (e.g., Ultrix). */
+/* #undef O_NONBLOCK_BROKEN */
+
+/* Define this if sys/syslog.h needs to be included in addition to syslog.h.
+ This is the case on some Ultrix versions. */
+/* #undef NEED_SYS_SYSLOG_H */
+
+/* Define this to include IDEA encryption. */
+/* #undef WITH_IDEA */
+
+/* Define this to include RC4 encryption. */
+/* #undef WITH_RC4 */
+
+/* Define this to include Blowfish encryption. */
+#define WITH_BLOWFISH 1
+
+/* Define this to include libwrap (tcp_wrappers) support. */
+/* #undef LIBWRAP */
+
+/* This is defined to pw_encrypt on Linux when using John Faugh's shadow
+ password implementation. */
+/* #undef crypt */
+
+/* This is defined on 386BSD to preted we are on FreeBSD. */
+/* #undef __FreeBSD__ */
+
+/* If defines, this overrides "tty" as the terminal group. */
+/* #undef TTY_GROUP */
+
+/* Define this if you want to support Security Dynammics SecurID
+ cards. */
+/* #undef HAVE_SECURID */
+
+/* Define this if you are using HPSUX. HPUX uses non-standard shared
+ memory communication for X, which seems to be enabled by the display name
+ matching that of the local host. This circumvents it by using the IP
+ address instead of the host name in DISPLAY. */
+/* #undef HPSUX_NONSTANDARD_X11_KLUDGE */
+
+/* Define this if inet_network should be used instead of inet_addr. This is
+ the case on DGUX 5.4. */
+/* #undef BROKEN_INET_ADDR */
+
+/* Define this if your system does not like sizeof(struct sockaddr_un) as the
+ size argument in bind and connect calls for unix domain sockets. */
+/* #undef USE_STRLEN_FOR_AF_UNIX */
+
+/* Define this to use pipes instead of socketpairs for communicating with the
+ client program. Socketpairs do not seem to work on all systems. */
+#define USE_PIPES 1
+
+/* Define this if speed_t is defined in stdtypes.h or otherwise gets included
+ into ttymodes.c from system headers. */
+/* #undef SPEED_T_IN_STDTYPES_H */
+
+/* Define this if compiling with SOCKS (the firewall traversal library).
+ Also, you must define connect, getsockname, bind, accept, listen, and
+ select to their R-versions. */
+/* #undef SOCKS */
+/* #undef connect */
+/* #undef getsockname */
+/* #undef bind */
+/* #undef accept */
+/* #undef listen */
+/* #undef select */
+
+/* Define these if on SCO Unix. */
+/* #undef HAVE_SCO_ETC_SHADOW */
+/* #undef SCO */
+
+/* Define this if you want to compile in Kerberos V4 support.
+ This can be done at configure time with the --with-krb4 argument. */
+/* #undef KRB4 */
+
+/* Define this if you want to compile in AFS support.
+ This can be done at configure time with the --with-afs argument. */
+/* #undef AFS */
+
+/* Define this if you want to enable nonstandard krb4 TGT forwarding. */
+/* #undef KERBEROS_TGT_PASSING */
+
+/* Define this if you want to add optional compression support. */
+#define WITH_ZLIB 1
+
+/* The number of bytes in a int. */
+#define SIZEOF_INT 4
+
+/* The number of bytes in a long. */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in a short. */
+#define SIZEOF_SHORT 2
+
+/* Define if you have the _getpty function. */
+/* #undef HAVE__GETPTY */
+
+/* Define if you have the clock function. */
+#define HAVE_CLOCK 1
+
+/* Define if you have the fchmod function. */
+#define HAVE_FCHMOD 1
+
+/* Define if you have the getdtablesize function. */
+#define HAVE_GETDTABLESIZE 1
+
+/* Define if you have the gethostname function. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the getrusage function. */
+#define HAVE_GETRUSAGE 1
+
+/* Define if you have the gettimeofday function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if you have the initgroups function. */
+#define HAVE_INITGROUPS 1
+
+/* Define if you have the innetgr function. */
+#define HAVE_INNETGR 1
+
+/* Define if you have the memcpy function. */
+#define HAVE_MEMCPY 1
+
+/* Define if you have the memmove function. */
+#define HAVE_MEMMOVE 1
+
+/* Define if you have the openpty function. */
+/* #undef HAVE_OPENPTY */
+
+/* Define if you have the popen function. */
+#define HAVE_POPEN 1
+
+/* Define if you have the putenv function. */
+#define HAVE_PUTENV 1
+
+/* Define if you have the random function. */
+#define HAVE_RANDOM 1
+
+/* Define if you have the remove function. */
+#define HAVE_REMOVE 1
+
+/* Define if you have the seteuid function. */
+#define HAVE_SETEUID 1
+
+/* Define if you have the setlogin function. */
+#define HAVE_SETLOGIN 1
+
+/* Define if you have the setluid function. */
+/* #undef HAVE_SETLUID */
+
+/* Define if you have the setrlimit function. */
+#define HAVE_SETRLIMIT 1
+
+/* Define if you have the setsid function. */
+#define HAVE_SETSID 1
+
+/* Define if you have the socketpair function. */
+#define HAVE_SOCKETPAIR 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the times function. */
+#define HAVE_TIMES 1
+
+/* Define if you have the ulimit function. */
+/* #undef HAVE_ULIMIT */
+
+/* Define if you have the umask function. */
+#define HAVE_UMASK 1
+
+/* Define if you have the vhangup function. */
+/* #undef HAVE_VHANGUP */
+
+/* Define if you have the vsnprintf function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <gmp.h> header file. */
+#define HAVE_GMP_H 1
+
+/* Define if you have the <krb.h> header file. */
+/* #undef HAVE_KRB_H */
+
+/* Define if you have the <lastlog.h> header file. */
+/* #undef HAVE_LASTLOG_H */
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define if you have the <rusage.h> header file. */
+/* #undef HAVE_RUSAGE_H */
+
+/* Define if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define if you have the <ulimit.h> header file. */
+/* #undef HAVE_ULIMIT_H */
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define if you have the <usersec.h> header file. */
+/* #undef HAVE_USERSEC_H */
+
+/* Define if you have the <utime.h> header file. */
+#define HAVE_UTIME_H 1
+
+/* Define if you have the <utmp.h> header file. */
+#define HAVE_UTMP_H 1
+
+/* Define if you have the <utmpx.h> header file. */
+/* #undef HAVE_UTMPX_H */
+
+/* Define if you have the <zlib.h> header file. */
+#define HAVE_ZLIB_H 1
+
+/* Define if you have the crypt library (-lcrypt). */
+/* #undef HAVE_LIBCRYPT */
+
+/* Define if you have the des library (-ldes). */
+#define HAVE_LIBDES 1
+
+/* Define if you have the gen library (-lgen). */
+/* #undef HAVE_LIBGEN */
+
+/* Define if you have the gmp library (-lgmp). */
+#define HAVE_LIBGMP 1
+
+/* Define if you have the krb library (-lkrb). */
+#define HAVE_LIBKRB 1
+
+/* Define if you have the nsl library (-lnsl). */
+/* #undef HAVE_LIBNSL */
+
+/* Define if you have the s library (-ls). */
+/* #undef HAVE_LIBS */
+
+/* Define if you have the security library (-lsecurity). */
+/* #undef HAVE_LIBSECURITY */
+
+/* Define if you have the socket library (-lsocket). */
+/* #undef HAVE_LIBSOCKET */
+
+/* Define if you have the sun library (-lsun). */
+/* #undef HAVE_LIBSUN */
+
+/* Define if you have the z library (-lz). */
+#define HAVE_LIBZ 1
diff --git a/usr.bin/ssh/config.h.in b/usr.bin/ssh/config.h.in
new file mode 100644
index 00000000000..215a96e7cd9
--- /dev/null
+++ b/usr.bin/ssh/config.h.in
@@ -0,0 +1,442 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+/*
+
+acconfig.h - template used by autoheader to create config.h.in
+config.h.in - used by autoconf to create config.h
+config.h - created by autoconf; contains defines generated by autoconf
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>
+
+*/
+
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
+
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define if your struct stat has st_blksize. */
+#undef HAVE_ST_BLKSIZE
+
+/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define as __inline if that's what the C compiler calls it. */
+#undef inline
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef mode_t
+
+/* Define if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
+/* Define if your Fortran 77 compiler doesn't accept -c and -o together. */
+#undef F77_NO_MINUS_C_MINUS_O
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+#undef off_t
+
+/* Define as the return type of signal handlers (int or void). */
+#undef RETSIGTYPE
+
+/* Define to the type of arg1 for select(). */
+#undef SELECT_TYPE_ARG1
+
+/* Define to the type of args 2, 3 and 4 for select(). */
+#undef SELECT_TYPE_ARG234
+
+/* Define to the type of arg5 for select(). */
+#undef SELECT_TYPE_ARG5
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+#undef STAT_MACROS_BROKEN
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+/* Define if your processor stores words with the most significant
+ byte first (like Motorola and SPARC, unlike Intel and VAX). */
+#undef WORDS_BIGENDIAN
+
+/* Define if you have SYSV-style /dev/ptmx and /dev/pts/. */
+#undef HAVE_DEV_PTMX
+
+/* Define if you have /dev/pts and /dev/ptc devices (as in AIX). */
+#undef HAVE_DEV_PTS_AND_PTC
+
+/* Define if you have shadow passwords in /etc/security/passwd (AIX style). */
+#undef HAVE_ETC_SECURITY_PASSWD
+
+/* Define if you have shadow passwords in /etc/security/passwd.adjunct
+ (SunOS style). */
+#undef HAVE_ETC_SECURITY_PASSWD_ADJUNCT
+
+
+/* Define if you have OSF1 C2 security installed on the system */
+#undef HAVE_OSF1_C2_SECURITY
+
+/* Define if you have shadow passwords in /etc/shadow (Solaris style). */
+#undef HAVE_ETC_SHADOW
+
+/* Define if you have system login defaults in /etc/default/login. */
+#undef HAVE_ETC_DEFAULT_LOGIN
+
+/* Define if utmp structure has host field. */
+#undef HAVE_HOST_IN_UTMP
+
+/* Define if utmp structure has addr field. */
+#undef HAVE_ADDR_IN_UTMP
+
+/* Define if utmp structure has id field. */
+#undef HAVE_ID_IN_UTMP
+
+/* Define if utmp structure has name field. */
+#undef HAVE_NAME_IN_UTMP
+
+/* Define if utmp structure has pid field. */
+#undef HAVE_PID_IN_UTMP
+
+/* Define if utmpx structure has ut_session. */
+#undef HAVE_UT_SESSION
+
+/* Define if utmpx structure has ut_syslen. */
+#undef HAVE_UT_SYSLEN
+
+/* Define if /var/adm/lastlog or whatever it is called is a directory
+ (e.g. SGI IRIX). */
+#undef LASTLOG_IS_DIR
+
+/* Define to use RSAREF. */
+#undef RSAREF
+
+/* Define to use SSL. */
+#undef DO_SSL
+
+/* Define this to be the path of the rsh program to support executing rsh. */
+#undef RSH_PATH
+
+/* Define this to be the path of the xauth program. */
+#undef XAUTH_PATH
+
+/* Default path for utmp. Determined by configure. */
+#undef SSH_UTMP
+
+/* Default path for wtmp. Determined by configure. */
+#undef SSH_WTMP
+
+/* Default path for lastlog. Determined by configure. */
+#undef SSH_LASTLOG
+
+/* This is defined if we found a lastlog file. The presence of lastlog.h
+ alone is not a sufficient indicator (at least newer BSD systems have
+ lastlog but no lastlog.h. */
+#undef HAVE_LASTLOG
+
+/* Define this if libutil.a contains BSD 4.4 compatible login(), logout(),
+ and logwtmp() calls. */
+#undef HAVE_LIBUTIL_LOGIN
+
+/* Location of system mail spool directory. */
+#undef MAIL_SPOOL_DIRECTORY
+
+/* Defined if mail goes to $HOME/newmail instead of a global mail spool. */
+#undef HAVE_TILDE_NEWMAIL
+
+/* Define this to be the default user path if you don't like the default.
+ See the --with-path=<path> configure option. */
+#undef DEFAULT_PATH
+
+/* Define this if O_NONBLOCK does not work on your system (e.g., Ultrix). */
+#undef O_NONBLOCK_BROKEN
+
+/* Define this if sys/syslog.h needs to be included in addition to syslog.h.
+ This is the case on some Ultrix versions. */
+#undef NEED_SYS_SYSLOG_H
+
+/* Define this to include IDEA encryption. */
+#undef WITH_IDEA
+
+/* Define this to include RC4 encryption. */
+#undef WITH_RC4
+
+/* Define this to include Blowfish encryption. */
+#undef WITH_BLOWFISH
+
+/* Define this to include libwrap (tcp_wrappers) support. */
+#undef LIBWRAP
+
+/* This is defined to pw_encrypt on Linux when using John Faugh's shadow
+ password implementation. */
+#undef crypt
+
+/* This is defined on 386BSD to preted we are on FreeBSD. */
+#undef __FreeBSD__
+
+/* If defines, this overrides "tty" as the terminal group. */
+#undef TTY_GROUP
+
+/* Define this if you want to support Security Dynammics SecurID
+ cards. */
+#undef HAVE_SECURID
+
+/* Define this if you are using HPSUX. HPUX uses non-standard shared
+ memory communication for X, which seems to be enabled by the display name
+ matching that of the local host. This circumvents it by using the IP
+ address instead of the host name in DISPLAY. */
+#undef HPSUX_NONSTANDARD_X11_KLUDGE
+
+/* Define this if inet_network should be used instead of inet_addr. This is
+ the case on DGUX 5.4. */
+#undef BROKEN_INET_ADDR
+
+/* Define this if your system does not like sizeof(struct sockaddr_un) as the
+ size argument in bind and connect calls for unix domain sockets. */
+#undef USE_STRLEN_FOR_AF_UNIX
+
+/* Define this to use pipes instead of socketpairs for communicating with the
+ client program. Socketpairs do not seem to work on all systems. */
+#undef USE_PIPES
+
+/* Define this if speed_t is defined in stdtypes.h or otherwise gets included
+ into ttymodes.c from system headers. */
+#undef SPEED_T_IN_STDTYPES_H
+
+/* Define this if compiling with SOCKS (the firewall traversal library).
+ Also, you must define connect, getsockname, bind, accept, listen, and
+ select to their R-versions. */
+#undef SOCKS
+#undef connect
+#undef getsockname
+#undef bind
+#undef accept
+#undef listen
+#undef select
+
+/* Define these if on SCO Unix. */
+#undef HAVE_SCO_ETC_SHADOW
+#undef SCO
+
+/* Define this if you want to compile in Kerberos V4 support.
+ This can be done at configure time with the --with-krb4 argument. */
+#undef KRB4
+
+/* Define this if you want to compile in AFS support.
+ This can be done at configure time with the --with-afs argument. */
+#undef AFS
+
+/* Define this if you want to enable nonstandard krb4 TGT forwarding. */
+#undef KERBEROS_TGT_PASSING
+
+/* Define this if you want to add optional compression support. */
+#undef WITH_ZLIB
+
+/* The number of bytes in a int. */
+#undef SIZEOF_INT
+
+/* The number of bytes in a long. */
+#undef SIZEOF_LONG
+
+/* The number of bytes in a short. */
+#undef SIZEOF_SHORT
+
+/* Define if you have the _getpty function. */
+#undef HAVE__GETPTY
+
+/* Define if you have the clock function. */
+#undef HAVE_CLOCK
+
+/* Define if you have the fchmod function. */
+#undef HAVE_FCHMOD
+
+/* Define if you have the getdtablesize function. */
+#undef HAVE_GETDTABLESIZE
+
+/* Define if you have the gethostname function. */
+#undef HAVE_GETHOSTNAME
+
+/* Define if you have the getrusage function. */
+#undef HAVE_GETRUSAGE
+
+/* Define if you have the gettimeofday function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if you have the initgroups function. */
+#undef HAVE_INITGROUPS
+
+/* Define if you have the innetgr function. */
+#undef HAVE_INNETGR
+
+/* Define if you have the memcpy function. */
+#undef HAVE_MEMCPY
+
+/* Define if you have the memmove function. */
+#undef HAVE_MEMMOVE
+
+/* Define if you have the openpty function. */
+#undef HAVE_OPENPTY
+
+/* Define if you have the popen function. */
+#undef HAVE_POPEN
+
+/* Define if you have the putenv function. */
+#undef HAVE_PUTENV
+
+/* Define if you have the random function. */
+#undef HAVE_RANDOM
+
+/* Define if you have the remove function. */
+#undef HAVE_REMOVE
+
+/* Define if you have the seteuid function. */
+#undef HAVE_SETEUID
+
+/* Define if you have the setlogin function. */
+#undef HAVE_SETLOGIN
+
+/* Define if you have the setluid function. */
+#undef HAVE_SETLUID
+
+/* Define if you have the setrlimit function. */
+#undef HAVE_SETRLIMIT
+
+/* Define if you have the setsid function. */
+#undef HAVE_SETSID
+
+/* Define if you have the socketpair function. */
+#undef HAVE_SOCKETPAIR
+
+/* Define if you have the strchr function. */
+#undef HAVE_STRCHR
+
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the times function. */
+#undef HAVE_TIMES
+
+/* Define if you have the ulimit function. */
+#undef HAVE_ULIMIT
+
+/* Define if you have the umask function. */
+#undef HAVE_UMASK
+
+/* Define if you have the vhangup function. */
+#undef HAVE_VHANGUP
+
+/* Define if you have the vsnprintf function. */
+#undef HAVE_VSNPRINTF
+
+/* Define if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
+/* Define if you have the <gmp.h> header file. */
+#undef HAVE_GMP_H
+
+/* Define if you have the <krb.h> header file. */
+#undef HAVE_KRB_H
+
+/* Define if you have the <lastlog.h> header file. */
+#undef HAVE_LASTLOG_H
+
+/* Define if you have the <ndir.h> header file. */
+#undef HAVE_NDIR_H
+
+/* Define if you have the <netinet/in_systm.h> header file. */
+#undef HAVE_NETINET_IN_SYSTM_H
+
+/* Define if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define if you have the <rusage.h> header file. */
+#undef HAVE_RUSAGE_H
+
+/* Define if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define if you have the <sys/dir.h> header file. */
+#undef HAVE_SYS_DIR_H
+
+/* Define if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define if you have the <sys/ndir.h> header file. */
+#undef HAVE_SYS_NDIR_H
+
+/* Define if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define if you have the <ulimit.h> header file. */
+#undef HAVE_ULIMIT_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the <usersec.h> header file. */
+#undef HAVE_USERSEC_H
+
+/* Define if you have the <utime.h> header file. */
+#undef HAVE_UTIME_H
+
+/* Define if you have the <utmp.h> header file. */
+#undef HAVE_UTMP_H
+
+/* Define if you have the <utmpx.h> header file. */
+#undef HAVE_UTMPX_H
+
+/* Define if you have the <zlib.h> header file. */
+#undef HAVE_ZLIB_H
+
+/* Define if you have the crypt library (-lcrypt). */
+#undef HAVE_LIBCRYPT
+
+/* Define if you have the des library (-ldes). */
+#undef HAVE_LIBDES
+
+/* Define if you have the gen library (-lgen). */
+#undef HAVE_LIBGEN
+
+/* Define if you have the gmp library (-lgmp). */
+#undef HAVE_LIBGMP
+
+/* Define if you have the krb library (-lkrb). */
+#undef HAVE_LIBKRB
+
+/* Define if you have the nsl library (-lnsl). */
+#undef HAVE_LIBNSL
+
+/* Define if you have the s library (-ls). */
+#undef HAVE_LIBS
+
+/* Define if you have the security library (-lsecurity). */
+#undef HAVE_LIBSECURITY
+
+/* Define if you have the socket library (-lsocket). */
+#undef HAVE_LIBSOCKET
+
+/* Define if you have the sun library (-lsun). */
+#undef HAVE_LIBSUN
+
+/* Define if you have the z library (-lz). */
+#undef HAVE_LIBZ
diff --git a/usr.bin/ssh/config.log b/usr.bin/ssh/config.log
new file mode 100644
index 00000000000..b318101a081
--- /dev/null
+++ b/usr.bin/ssh/config.log
@@ -0,0 +1,420 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+configure:593: checking host system type
+configure:617: checking for gcc
+configure:730: checking whether the C compiler (gcc ) works
+configure:746: gcc -o conftest conftest.c 1>&5
+configure:772: checking whether the C compiler (gcc ) is a cross-compiler
+configure:777: checking whether we are using GNU C
+configure:786: gcc -E conftest.c
+configure:805: checking whether gcc accepts -g
+configure:837: checking how to run the C preprocessor
+configure:858: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1332: checking that the compiler works
+configure:1341: gcc -o conftest -g -O2 conftest.c 1>&5
+configure:1358: checking if the compiler understands -pipe
+configure:1369: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:1397: checking for vhangup
+configure:1425: gcc -pipe -o conftest -g -O2 conftest.c 1>&5
+configure:1419: Undefined symbol `_vhangup' referenced from text segment
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 1402 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char vhangup(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char vhangup();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_vhangup) || defined (__stub___vhangup)
+choke me
+#else
+vhangup();
+#endif
+
+; return 0; }
+configure:1455: checking for setsid
+configure:1483: gcc -pipe -o conftest -g -O2 conftest.c 1>&5
+configure:1510: checking where to find mandatory GMP library
+configure:1535: checking for gmp.h
+configure:1545: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1577: checking for main in -lgmp
+configure:1592: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1636: checking for _getpty
+configure:1664: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1658: Undefined symbol `__getpty' referenced from text segment
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 1641 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char _getpty(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char _getpty();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub__getpty) || defined (__stub____getpty)
+choke me
+#else
+_getpty();
+#endif
+
+; return 0; }
+configure:1636: checking for clock
+configure:1664: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1636: checking for fchmod
+configure:1664: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1636: checking for getdtablesize
+configure:1664: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1636: checking for gethostname
+configure:1664: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1636: checking for getrusage
+configure:1664: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1691: checking for gettimeofday
+configure:1719: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1691: checking for initgroups
+configure:1719: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1691: checking for innetgr
+configure:1719: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1691: checking for memcpy
+configure:1719: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1703: warning: conflicting types for built-in function `memcpy'
+configure:1691: checking for openpty
+configure:1719: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1713: Undefined symbol `_openpty' referenced from text segment
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 1696 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char openpty(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char openpty();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_openpty) || defined (__stub___openpty)
+choke me
+#else
+openpty();
+#endif
+
+; return 0; }
+configure:1691: checking for popen
+configure:1719: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1691: checking for seteuid
+configure:1719: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1746: checking for setlogin
+configure:1774: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1746: checking for setluid
+configure:1774: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1768: Undefined symbol `_setluid' referenced from text segment
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 1751 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char setluid(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char setluid();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_setluid) || defined (__stub___setluid)
+choke me
+#else
+setluid();
+#endif
+
+; return 0; }
+configure:1746: checking for setrlimit
+configure:1774: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1746: checking for strchr
+configure:1774: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1746: checking for times
+configure:1774: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1746: checking for ulimit
+configure:1774: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1768: Undefined symbol `_ulimit' referenced from text segment
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 1751 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char ulimit(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char ulimit();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_ulimit) || defined (__stub___ulimit)
+choke me
+#else
+ulimit();
+#endif
+
+; return 0; }
+configure:1746: checking for umask
+configure:1774: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1746: checking for vsnprintf
+configure:1774: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1800: checking return type of signal handlers
+configure:1822: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:1841: checking for ANSI C header files
+configure:1854: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:1921: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:1945: checking for size_t
+configure:1978: checking for uid_t in sys/types.h
+configure:2012: checking for off_t
+configure:2045: checking for mode_t
+configure:2078: checking for st_blksize in struct stat
+configure:2091: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:2113: checking for working const
+configure:2167: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:2188: checking for inline
+configure:2202: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:2228: checking whether byte ordering is bigendian
+configure:2246: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:2261: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure: In function `main':
+configure:2256: syntax error before `big'
+configure: failed program was:
+#line 2250 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+; return 0; }
+configure:2318: checking size of long
+configure:2337: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:2357: checking size of int
+configure:2376: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:2396: checking size of short
+configure:2415: gcc -pipe -o conftest -g -O2 conftest.c -lgmp 1>&5
+configure:2440: checking for termios.h
+configure:2450: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2479: checking for ANSI C header files
+configure:2583: checking for sys/wait.h that is POSIX.1 compatible
+configure:2604: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:2628: checking for unistd.h
+configure:2638: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2628: checking for rusage.h
+configure:2638: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2634: rusage.h: No such file or directory
+configure: failed program was:
+#line 2633 "configure"
+#include "confdefs.h"
+#include <rusage.h>
+configure:2628: checking for sys/time.h
+configure:2638: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2628: checking for lastlog.h
+configure:2638: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2634: lastlog.h: No such file or directory
+configure: failed program was:
+#line 2633 "configure"
+#include "confdefs.h"
+#include <lastlog.h>
+configure:2628: checking for utmp.h
+configure:2638: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2628: checking for utmpx.h
+configure:2638: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2634: utmpx.h: No such file or directory
+configure: failed program was:
+#line 2633 "configure"
+#include "confdefs.h"
+#include <utmpx.h>
+configure:2668: checking for sgtty.h
+configure:2678: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2668: checking for sys/select.h
+configure:2678: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2668: checking for sys/ioctl.h
+configure:2678: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2668: checking for sys/filio.h
+configure:2678: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2708: checking for paths.h
+configure:2718: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2708: checking for usersec.h
+configure:2718: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2714: usersec.h: No such file or directory
+configure: failed program was:
+#line 2713 "configure"
+#include "confdefs.h"
+#include <usersec.h>
+configure:2708: checking for utime.h
+configure:2718: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2708: checking for netinet/in_systm.h
+configure:2718: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2708: checking for ulimit.h
+configure:2718: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:2714: ulimit.h: No such file or directory
+configure: failed program was:
+#line 2713 "configure"
+#include "confdefs.h"
+#include <ulimit.h>
+configure:2745: checking whether time.h and sys/time.h may both be included
+configure:2759: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:2784: checking for dirent.h that defines DIR
+configure:2797: gcc -pipe -c -g -O2 conftest.c 1>&5
+configure:2822: checking for opendir in -ldir
+configure:2841: gcc -pipe -o conftest -g -O2 conftest.c -ldir -lgmp 1>&5
+ld: -ldir: no match
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 2830 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+configure:2905: checking whether stat file-mode macros are broken
+configure:3038: utmpx.h: No such file or directory
+configure:3053: utmpx.h: No such file or directory
+configure:3068: checking for crypt in -lc
+configure:3087: gcc -pipe -o conftest -g -O2 conftest.c -lc -lgmp 1>&5
+configure:3155: checking for main in -lnsl
+configure:3170: gcc -pipe -o conftest -g -O2 conftest.c -lnsl -lgmp 1>&5
+ld: -lnsl: no match
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 3163 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+configure:3199: checking for socket in -lsocket
+configure:3218: gcc -pipe -o conftest -g -O2 conftest.c -lsocket -lgmp 1>&5
+ld: -lsocket: no match
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 3207 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+configure:3248: checking for getpwnam in -lsun
+configure:3267: gcc -pipe -o conftest -g -O2 conftest.c -lsun -lgmp 1>&5
+ld: -lsun: no match
+collect2: ld returned 1 exit status
+configure: failed program was:
+#line 3256 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getpwnam();
+
+int main() {
+getpwnam()
+; return 0; }
+configure:3296: checking for login in -lutil
+configure:3315: gcc -pipe -o conftest -g -O2 conftest.c -lutil -lgmp 1>&5
+configure:3341: checking for main in -ldes
+configure:3356: gcc -pipe -o conftest -g -O2 conftest.c -ldes -lgmp -lutil 1>&5
+configure:3387: checking for strerror
+configure:3415: gcc -pipe -o conftest -g -O2 conftest.c -ldes -lgmp -lutil 1>&5
+configure:3387: checking for memmove
+configure:3415: gcc -pipe -o conftest -g -O2 conftest.c -ldes -lgmp -lutil 1>&5
+configure:3387: checking for remove
+configure:3415: gcc -pipe -o conftest -g -O2 conftest.c -ldes -lgmp -lutil 1>&5
+configure:3387: checking for random
+configure:3415: gcc -pipe -o conftest -g -O2 conftest.c -ldes -lgmp -lutil 1>&5
+configure:3387: checking for putenv
+configure:3415: gcc -pipe -o conftest -g -O2 conftest.c -ldes -lgmp -lutil 1>&5
+configure:3387: checking for socketpair
+configure:3415: gcc -pipe -o conftest -g -O2 conftest.c -ldes -lgmp -lutil 1>&5
+configure:3443: checking whether ln -s works
+configure:3475: checking for a BSD compatible install
+configure:3531: checking for ranlib
+configure:3566: checking for makedepend
+configure:3601: checking for wish8.0
+configure:3601: checking for wish
+configure:3601: checking for wishx
+configure:3601: checking for wish4.1
+configure:3601: checking for true
+configure:3643: checking for xauth
+configure:3683: checking for pseudo ttys
+configure:3705: checking for /etc/default/login
+configure:3718: checking for shadow passwords
+configure:3743: checking location of mail spool files
+configure:3764: checking location of utmp
+configure:3800: checking location of wtmp
+configure:3834: checking location of lastlog
+configure:3889: checking whether /var/log/lastlog is a directory
+configure:3902: checking whether to include the IDEA encryption algorithm
+configure:3926: checking whether to include the RC4 encryption algorithm
+configure:3950: checking whether to include the Blowfish encryption algorithm
+configure:3982: checking whether to use rsaref
+configure:4008: checking whether to use ssl
+configure:4032: checking whether to use rsh
+configure:4102: checking for remsh
+configure:4102: checking for rsh
+configure:4147: checking default path
+configure:4170: checking etcdir
+configure:4195: checking whether to support SecurID
+configure:4238: checking whether to include compression support
+configure:4262: checking for zlib.h
+configure:4272: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:4303: checking for main in -lz
+configure:4318: gcc -pipe -o conftest -g -O2 conftest.c -lz -lcrypto -ldes -lgmp -lutil 1>&5
+configure:4361: checking whether to use Kerberos v4
+configure:4530: checking for krb.h
+configure:4540: gcc -E conftest.c >/dev/null 2>conftest.out
+configure:4536: krb.h: No such file or directory
+configure: failed program was:
+#line 4535 "configure"
+#include "confdefs.h"
+#include <krb.h>
+configure:4567: checking for main in -lkrb
+configure:4582: gcc -pipe -o conftest -g -O2 conftest.c -lkrb -lz -lcrypto -ldes -lgmp -lutil 1>&5
+configure:4717: checking whether to use AFS
+configure:4749: checking whether to use libwrap
+configure:4815: checking whether to support SOCKS
+configure:4884: checking where to put sshd.pid
diff --git a/usr.bin/ssh/config.sample b/usr.bin/ssh/config.sample
new file mode 100644
index 00000000000..34daeee5630
--- /dev/null
+++ b/usr.bin/ssh/config.sample
@@ -0,0 +1,62 @@
+# This is a sample per-user ssh configuration file. This file could be
+# the user's .ssh/config.
+
+# Configuration data is parsed as follows:
+# 1. command line options
+# 2. user-specific file
+# 3. system-wide file
+# Any configuration value is only changed the first time it is set.
+# Thus, host-specific definitions should be at the beginning of the
+# configuration file, and defaults at the end.
+
+# System defaults will be used for anything not explicitly specified
+# in this file.
+
+Host fake
+ HostName sparc.ngs.fi
+ UseRsh yes
+
+Host pooh
+ HostName pooh.tky.hut.fi
+
+Host shadows.cs.hut.fi shadows
+ RhostsAuthentication yes
+ KeepAlive no
+ RemoteForward 30000 olari.clinet.fi:23
+ LocalForward 30001 lk-hp-13.hut.fi:23
+ IdentityFile ~/.identityfiles/shadows
+
+Host ngs.fi *.ngs.fi
+ RhostsAuthentication no
+ FallBackToRsh no
+ PasswordAuthentication no
+ IdentityFile ~/.identityfiles/ngs
+ KeepAlive no
+ Compression yes
+ CompressionLevel 9
+
+Host *.fr
+ UseRsh yes
+
+Host *.su
+ FallBackToRsh yes
+ Cipher none
+ PasswordAuthentication no
+ ForwardAgent no
+
+Host *.com *.edu *.gov *.mil *.org *.de *.uk
+ Cipher 3des
+ ForwardAgent no
+
+# Defaults for various options
+Host *
+ ForwardAgent yes
+ ForwardX11 yes
+ RhostsAuthentication yes
+ PasswordAuthentication yes
+ RSAAuthentication yes
+ FallBackToRsh no
+ UseRsh no
+ IdentityFile ~/.ssh/identity
+ Port 22
+ Cipher idea
diff --git a/usr.bin/ssh/config.status b/usr.bin/ssh/config.status
new file mode 100644
index 00000000000..63dfa66413e
--- /dev/null
+++ b/usr.bin/ssh/config.status
@@ -0,0 +1,536 @@
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host cvs.openbsd.org:
+#
+# ./configure --with-ssl
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: ./config.status [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running ${CONFIG_SHELL-/bin/sh} ./configure --with-ssl --no-create --no-recursion"
+ exec ${CONFIG_SHELL-/bin/sh} ./configure --with-ssl --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "./config.status generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "$ac_cs_usage"; exit 0 ;;
+ *) echo "$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=.
+ac_given_INSTALL="/usr/bin/install -c"
+
+trap 'rm -fr Makefile sshd.8 ssh.1 config.h conftest*; exit 1' 1 2 15
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\&%]/\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
+/^[ ]*VPATH[ ]*=[^:]*$/d
+
+s%@SHELL@%/bin/sh%g
+s%@CFLAGS@%-g -O2%g
+s%@CPPFLAGS@%%g
+s%@CXXFLAGS@%%g
+s%@FFLAGS@%%g
+s%@DEFS@%-DHAVE_CONFIG_H%g
+s%@LDFLAGS@%%g
+s%@LIBS@%-lkrb -lz -lcrypto -ldes -lgmp -lutil%g
+s%@exec_prefix@%${prefix}%g
+s%@prefix@%/usr/local%g
+s%@program_transform_name@%s,x,x,%g
+s%@bindir@%${exec_prefix}/bin%g
+s%@sbindir@%${exec_prefix}/sbin%g
+s%@libexecdir@%${exec_prefix}/libexec%g
+s%@datadir@%${prefix}/share%g
+s%@sysconfdir@%${prefix}/etc%g
+s%@sharedstatedir@%${prefix}/com%g
+s%@localstatedir@%${prefix}/var%g
+s%@libdir@%${exec_prefix}/lib%g
+s%@includedir@%${prefix}/include%g
+s%@oldincludedir@%/usr/include%g
+s%@infodir@%${prefix}/info%g
+s%@mandir@%${prefix}/man%g
+s%@host@%i386-unknown-openbsd2.5%g
+s%@host_alias@%i386-unknown-openbsd2.5%g
+s%@host_cpu@%i386%g
+s%@host_vendor@%unknown%g
+s%@host_os@%openbsd2.5%g
+s%@CC@%gcc -pipe%g
+s%@CPP@%gcc -E%g
+s%@GMPINCS@%%g
+s%@GMPLIBS@%-lgmp%g
+s%@LIBOBJS@%%g
+s%@LN_S@%ln -s%g
+s%@INSTALL_PROGRAM@%${INSTALL}%g
+s%@INSTALL_SCRIPT@%${INSTALL_PROGRAM}%g
+s%@INSTALL_DATA@%${INSTALL} -m 644%g
+s%@RANLIB@%ranlib%g
+s%@MAKEDEP@%makedepend%g
+s%@WISH@%/usr/local/bin/wish%g
+s%@XAUTH_PATH@%/usr/X11R6/bin/xauth%g
+s%@RSH_PATH@%/usr/bin/rsh%g
+s%@KRB4_AUTH@%%g
+s%@KRB4_ROOT@%%g
+s%@KRB4_INCS@%%g
+s%@KRB4_LIBS@%%g
+s%@RADIX@%%g
+s%@ETCDIR@%/etc%g
+s%@PIDDIR@%/var/run%g
+s%@RSAREFDEP@%%g
+s%@CONFOBJS@% bf_skey.o bf_enc.o compress.o%g
+
+CEOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+
+CONFIG_FILES=${CONFIG_FILES-"Makefile sshd.8 ssh.1"}
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+ CONFIG_HEADERS="config.h"
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}USE_PIPES${ac_dB}USE_PIPES${ac_dC}1${ac_dD}
+${ac_uA}USE_PIPES${ac_uB}USE_PIPES${ac_uC}1${ac_uD}
+${ac_eA}USE_PIPES${ac_eB}USE_PIPES${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SETSID${ac_dB}HAVE_SETSID${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SETSID${ac_uB}HAVE_SETSID${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SETSID${ac_eB}HAVE_SETSID${ac_eC}1${ac_eD}
+${ac_dA}HAVE_GMP_H${ac_dB}HAVE_GMP_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_GMP_H${ac_uB}HAVE_GMP_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_GMP_H${ac_eB}HAVE_GMP_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_LIBGMP${ac_dB}HAVE_LIBGMP${ac_dC}1${ac_dD}
+${ac_uA}HAVE_LIBGMP${ac_uB}HAVE_LIBGMP${ac_uC}1${ac_uD}
+${ac_eA}HAVE_LIBGMP${ac_eB}HAVE_LIBGMP${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_CLOCK${ac_dB}HAVE_CLOCK${ac_dC}1${ac_dD}
+${ac_uA}HAVE_CLOCK${ac_uB}HAVE_CLOCK${ac_uC}1${ac_uD}
+${ac_eA}HAVE_CLOCK${ac_eB}HAVE_CLOCK${ac_eC}1${ac_eD}
+${ac_dA}HAVE_FCHMOD${ac_dB}HAVE_FCHMOD${ac_dC}1${ac_dD}
+${ac_uA}HAVE_FCHMOD${ac_uB}HAVE_FCHMOD${ac_uC}1${ac_uD}
+${ac_eA}HAVE_FCHMOD${ac_eB}HAVE_FCHMOD${ac_eC}1${ac_eD}
+${ac_dA}HAVE_GETDTABLESIZE${ac_dB}HAVE_GETDTABLESIZE${ac_dC}1${ac_dD}
+${ac_uA}HAVE_GETDTABLESIZE${ac_uB}HAVE_GETDTABLESIZE${ac_uC}1${ac_uD}
+${ac_eA}HAVE_GETDTABLESIZE${ac_eB}HAVE_GETDTABLESIZE${ac_eC}1${ac_eD}
+${ac_dA}HAVE_GETHOSTNAME${ac_dB}HAVE_GETHOSTNAME${ac_dC}1${ac_dD}
+${ac_uA}HAVE_GETHOSTNAME${ac_uB}HAVE_GETHOSTNAME${ac_uC}1${ac_uD}
+${ac_eA}HAVE_GETHOSTNAME${ac_eB}HAVE_GETHOSTNAME${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_GETRUSAGE${ac_dB}HAVE_GETRUSAGE${ac_dC}1${ac_dD}
+${ac_uA}HAVE_GETRUSAGE${ac_uB}HAVE_GETRUSAGE${ac_uC}1${ac_uD}
+${ac_eA}HAVE_GETRUSAGE${ac_eB}HAVE_GETRUSAGE${ac_eC}1${ac_eD}
+${ac_dA}HAVE_GETTIMEOFDAY${ac_dB}HAVE_GETTIMEOFDAY${ac_dC}1${ac_dD}
+${ac_uA}HAVE_GETTIMEOFDAY${ac_uB}HAVE_GETTIMEOFDAY${ac_uC}1${ac_uD}
+${ac_eA}HAVE_GETTIMEOFDAY${ac_eB}HAVE_GETTIMEOFDAY${ac_eC}1${ac_eD}
+${ac_dA}HAVE_INITGROUPS${ac_dB}HAVE_INITGROUPS${ac_dC}1${ac_dD}
+${ac_uA}HAVE_INITGROUPS${ac_uB}HAVE_INITGROUPS${ac_uC}1${ac_uD}
+${ac_eA}HAVE_INITGROUPS${ac_eB}HAVE_INITGROUPS${ac_eC}1${ac_eD}
+${ac_dA}HAVE_INNETGR${ac_dB}HAVE_INNETGR${ac_dC}1${ac_dD}
+${ac_uA}HAVE_INNETGR${ac_uB}HAVE_INNETGR${ac_uC}1${ac_uD}
+${ac_eA}HAVE_INNETGR${ac_eB}HAVE_INNETGR${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_MEMCPY${ac_dB}HAVE_MEMCPY${ac_dC}1${ac_dD}
+${ac_uA}HAVE_MEMCPY${ac_uB}HAVE_MEMCPY${ac_uC}1${ac_uD}
+${ac_eA}HAVE_MEMCPY${ac_eB}HAVE_MEMCPY${ac_eC}1${ac_eD}
+${ac_dA}HAVE_POPEN${ac_dB}HAVE_POPEN${ac_dC}1${ac_dD}
+${ac_uA}HAVE_POPEN${ac_uB}HAVE_POPEN${ac_uC}1${ac_uD}
+${ac_eA}HAVE_POPEN${ac_eB}HAVE_POPEN${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SETEUID${ac_dB}HAVE_SETEUID${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SETEUID${ac_uB}HAVE_SETEUID${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SETEUID${ac_eB}HAVE_SETEUID${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SETLOGIN${ac_dB}HAVE_SETLOGIN${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SETLOGIN${ac_uB}HAVE_SETLOGIN${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SETLOGIN${ac_eB}HAVE_SETLOGIN${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_SETRLIMIT${ac_dB}HAVE_SETRLIMIT${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SETRLIMIT${ac_uB}HAVE_SETRLIMIT${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SETRLIMIT${ac_eB}HAVE_SETRLIMIT${ac_eC}1${ac_eD}
+${ac_dA}HAVE_STRCHR${ac_dB}HAVE_STRCHR${ac_dC}1${ac_dD}
+${ac_uA}HAVE_STRCHR${ac_uB}HAVE_STRCHR${ac_uC}1${ac_uD}
+${ac_eA}HAVE_STRCHR${ac_eB}HAVE_STRCHR${ac_eC}1${ac_eD}
+${ac_dA}HAVE_TIMES${ac_dB}HAVE_TIMES${ac_dC}1${ac_dD}
+${ac_uA}HAVE_TIMES${ac_uB}HAVE_TIMES${ac_uC}1${ac_uD}
+${ac_eA}HAVE_TIMES${ac_eB}HAVE_TIMES${ac_eC}1${ac_eD}
+${ac_dA}HAVE_UMASK${ac_dB}HAVE_UMASK${ac_dC}1${ac_dD}
+${ac_uA}HAVE_UMASK${ac_uB}HAVE_UMASK${ac_uC}1${ac_uD}
+${ac_eA}HAVE_UMASK${ac_eB}HAVE_UMASK${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_VSNPRINTF${ac_dB}HAVE_VSNPRINTF${ac_dC}1${ac_dD}
+${ac_uA}HAVE_VSNPRINTF${ac_uB}HAVE_VSNPRINTF${ac_uC}1${ac_uD}
+${ac_eA}HAVE_VSNPRINTF${ac_eB}HAVE_VSNPRINTF${ac_eC}1${ac_eD}
+${ac_dA}RETSIGTYPE${ac_dB}RETSIGTYPE${ac_dC}void${ac_dD}
+${ac_uA}RETSIGTYPE${ac_uB}RETSIGTYPE${ac_uC}void${ac_uD}
+${ac_eA}RETSIGTYPE${ac_eB}RETSIGTYPE${ac_eC}void${ac_eD}
+${ac_dA}STDC_HEADERS${ac_dB}STDC_HEADERS${ac_dC}1${ac_dD}
+${ac_uA}STDC_HEADERS${ac_uB}STDC_HEADERS${ac_uC}1${ac_uD}
+${ac_eA}STDC_HEADERS${ac_eB}STDC_HEADERS${ac_eC}1${ac_eD}
+${ac_dA}HAVE_ST_BLKSIZE${ac_dB}HAVE_ST_BLKSIZE${ac_dC}1${ac_dD}
+${ac_uA}HAVE_ST_BLKSIZE${ac_uB}HAVE_ST_BLKSIZE${ac_uC}1${ac_uD}
+${ac_eA}HAVE_ST_BLKSIZE${ac_eB}HAVE_ST_BLKSIZE${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}SIZEOF_LONG${ac_dB}SIZEOF_LONG${ac_dC}4${ac_dD}
+${ac_uA}SIZEOF_LONG${ac_uB}SIZEOF_LONG${ac_uC}4${ac_uD}
+${ac_eA}SIZEOF_LONG${ac_eB}SIZEOF_LONG${ac_eC}4${ac_eD}
+${ac_dA}SIZEOF_INT${ac_dB}SIZEOF_INT${ac_dC}4${ac_dD}
+${ac_uA}SIZEOF_INT${ac_uB}SIZEOF_INT${ac_uC}4${ac_uD}
+${ac_eA}SIZEOF_INT${ac_eB}SIZEOF_INT${ac_eC}4${ac_eD}
+${ac_dA}SIZEOF_SHORT${ac_dB}SIZEOF_SHORT${ac_dC}2${ac_dD}
+${ac_uA}SIZEOF_SHORT${ac_uB}SIZEOF_SHORT${ac_uC}2${ac_uD}
+${ac_eA}SIZEOF_SHORT${ac_eB}SIZEOF_SHORT${ac_eC}2${ac_eD}
+${ac_dA}HAVE_TERMIOS_H${ac_dB}HAVE_TERMIOS_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_TERMIOS_H${ac_uB}HAVE_TERMIOS_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_TERMIOS_H${ac_eB}HAVE_TERMIOS_H${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}STDC_HEADERS${ac_dB}STDC_HEADERS${ac_dC}1${ac_dD}
+${ac_uA}STDC_HEADERS${ac_uB}STDC_HEADERS${ac_uC}1${ac_uD}
+${ac_eA}STDC_HEADERS${ac_eB}STDC_HEADERS${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SYS_WAIT_H${ac_dB}HAVE_SYS_WAIT_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SYS_WAIT_H${ac_uB}HAVE_SYS_WAIT_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SYS_WAIT_H${ac_eB}HAVE_SYS_WAIT_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_UNISTD_H${ac_dB}HAVE_UNISTD_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_UNISTD_H${ac_uB}HAVE_UNISTD_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_UNISTD_H${ac_eB}HAVE_UNISTD_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SYS_TIME_H${ac_dB}HAVE_SYS_TIME_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SYS_TIME_H${ac_uB}HAVE_SYS_TIME_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SYS_TIME_H${ac_eB}HAVE_SYS_TIME_H${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_UTMP_H${ac_dB}HAVE_UTMP_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_UTMP_H${ac_uB}HAVE_UTMP_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_UTMP_H${ac_eB}HAVE_UTMP_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SGTTY_H${ac_dB}HAVE_SGTTY_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SGTTY_H${ac_uB}HAVE_SGTTY_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SGTTY_H${ac_eB}HAVE_SGTTY_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SYS_SELECT_H${ac_dB}HAVE_SYS_SELECT_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SYS_SELECT_H${ac_uB}HAVE_SYS_SELECT_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SYS_SELECT_H${ac_eB}HAVE_SYS_SELECT_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SYS_IOCTL_H${ac_dB}HAVE_SYS_IOCTL_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SYS_IOCTL_H${ac_uB}HAVE_SYS_IOCTL_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SYS_IOCTL_H${ac_eB}HAVE_SYS_IOCTL_H${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_SYS_FILIO_H${ac_dB}HAVE_SYS_FILIO_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SYS_FILIO_H${ac_uB}HAVE_SYS_FILIO_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SYS_FILIO_H${ac_eB}HAVE_SYS_FILIO_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_PATHS_H${ac_dB}HAVE_PATHS_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_PATHS_H${ac_uB}HAVE_PATHS_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_PATHS_H${ac_eB}HAVE_PATHS_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_UTIME_H${ac_dB}HAVE_UTIME_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_UTIME_H${ac_uB}HAVE_UTIME_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_UTIME_H${ac_eB}HAVE_UTIME_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_NETINET_IN_SYSTM_H${ac_dB}HAVE_NETINET_IN_SYSTM_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_NETINET_IN_SYSTM_H${ac_uB}HAVE_NETINET_IN_SYSTM_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_NETINET_IN_SYSTM_H${ac_eB}HAVE_NETINET_IN_SYSTM_H${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}TIME_WITH_SYS_TIME${ac_dB}TIME_WITH_SYS_TIME${ac_dC}1${ac_dD}
+${ac_uA}TIME_WITH_SYS_TIME${ac_uB}TIME_WITH_SYS_TIME${ac_uC}1${ac_uD}
+${ac_eA}TIME_WITH_SYS_TIME${ac_eB}TIME_WITH_SYS_TIME${ac_eC}1${ac_eD}
+${ac_dA}HAVE_DIRENT_H${ac_dB}HAVE_DIRENT_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_DIRENT_H${ac_uB}HAVE_DIRENT_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_DIRENT_H${ac_eB}HAVE_DIRENT_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_NAME_IN_UTMP${ac_dB}HAVE_NAME_IN_UTMP${ac_dC}1${ac_dD}
+${ac_uA}HAVE_NAME_IN_UTMP${ac_uB}HAVE_NAME_IN_UTMP${ac_uC}1${ac_uD}
+${ac_eA}HAVE_NAME_IN_UTMP${ac_eB}HAVE_NAME_IN_UTMP${ac_eC}1${ac_eD}
+${ac_dA}HAVE_HOST_IN_UTMP${ac_dB}HAVE_HOST_IN_UTMP${ac_dC}1${ac_dD}
+${ac_uA}HAVE_HOST_IN_UTMP${ac_uB}HAVE_HOST_IN_UTMP${ac_uC}1${ac_uD}
+${ac_eA}HAVE_HOST_IN_UTMP${ac_eB}HAVE_HOST_IN_UTMP${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_LIBUTIL_LOGIN${ac_dB}HAVE_LIBUTIL_LOGIN${ac_dC}1${ac_dD}
+${ac_uA}HAVE_LIBUTIL_LOGIN${ac_uB}HAVE_LIBUTIL_LOGIN${ac_uC}1${ac_uD}
+${ac_eA}HAVE_LIBUTIL_LOGIN${ac_eB}HAVE_LIBUTIL_LOGIN${ac_eC}1${ac_eD}
+${ac_dA}HAVE_LIBDES${ac_dB}HAVE_LIBDES${ac_dC}1${ac_dD}
+${ac_uA}HAVE_LIBDES${ac_uB}HAVE_LIBDES${ac_uC}1${ac_uD}
+${ac_eA}HAVE_LIBDES${ac_eB}HAVE_LIBDES${ac_eC}1${ac_eD}
+${ac_dA}HAVE_STRERROR${ac_dB}HAVE_STRERROR${ac_dC}1${ac_dD}
+${ac_uA}HAVE_STRERROR${ac_uB}HAVE_STRERROR${ac_uC}1${ac_uD}
+${ac_eA}HAVE_STRERROR${ac_eB}HAVE_STRERROR${ac_eC}1${ac_eD}
+${ac_dA}HAVE_MEMMOVE${ac_dB}HAVE_MEMMOVE${ac_dC}1${ac_dD}
+${ac_uA}HAVE_MEMMOVE${ac_uB}HAVE_MEMMOVE${ac_uC}1${ac_uD}
+${ac_eA}HAVE_MEMMOVE${ac_eB}HAVE_MEMMOVE${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_REMOVE${ac_dB}HAVE_REMOVE${ac_dC}1${ac_dD}
+${ac_uA}HAVE_REMOVE${ac_uB}HAVE_REMOVE${ac_uC}1${ac_uD}
+${ac_eA}HAVE_REMOVE${ac_eB}HAVE_REMOVE${ac_eC}1${ac_eD}
+${ac_dA}HAVE_RANDOM${ac_dB}HAVE_RANDOM${ac_dC}1${ac_dD}
+${ac_uA}HAVE_RANDOM${ac_uB}HAVE_RANDOM${ac_uC}1${ac_uD}
+${ac_eA}HAVE_RANDOM${ac_eB}HAVE_RANDOM${ac_eC}1${ac_eD}
+${ac_dA}HAVE_PUTENV${ac_dB}HAVE_PUTENV${ac_dC}1${ac_dD}
+${ac_uA}HAVE_PUTENV${ac_uB}HAVE_PUTENV${ac_uC}1${ac_uD}
+${ac_eA}HAVE_PUTENV${ac_eB}HAVE_PUTENV${ac_eC}1${ac_eD}
+${ac_dA}HAVE_SOCKETPAIR${ac_dB}HAVE_SOCKETPAIR${ac_dC}1${ac_dD}
+${ac_uA}HAVE_SOCKETPAIR${ac_uB}HAVE_SOCKETPAIR${ac_uC}1${ac_uD}
+${ac_eA}HAVE_SOCKETPAIR${ac_eB}HAVE_SOCKETPAIR${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}XAUTH_PATH${ac_dB}XAUTH_PATH${ac_dC}"/usr/X11R6/bin/xauth"${ac_dD}
+${ac_uA}XAUTH_PATH${ac_uB}XAUTH_PATH${ac_uC}"/usr/X11R6/bin/xauth"${ac_uD}
+${ac_eA}XAUTH_PATH${ac_eB}XAUTH_PATH${ac_eC}"/usr/X11R6/bin/xauth"${ac_eD}
+${ac_dA}MAIL_SPOOL_DIRECTORY${ac_dB}MAIL_SPOOL_DIRECTORY${ac_dC}"/var/mail"${ac_dD}
+${ac_uA}MAIL_SPOOL_DIRECTORY${ac_uB}MAIL_SPOOL_DIRECTORY${ac_uC}"/var/mail"${ac_uD}
+${ac_eA}MAIL_SPOOL_DIRECTORY${ac_eB}MAIL_SPOOL_DIRECTORY${ac_eC}"/var/mail"${ac_eD}
+${ac_dA}SSH_UTMP${ac_dB}SSH_UTMP${ac_dC}"/var/run/utmp"${ac_dD}
+${ac_uA}SSH_UTMP${ac_uB}SSH_UTMP${ac_uC}"/var/run/utmp"${ac_uD}
+${ac_eA}SSH_UTMP${ac_eB}SSH_UTMP${ac_eC}"/var/run/utmp"${ac_eD}
+${ac_dA}SSH_WTMP${ac_dB}SSH_WTMP${ac_dC}"/var/log/wtmp"${ac_dD}
+${ac_uA}SSH_WTMP${ac_uB}SSH_WTMP${ac_uC}"/var/log/wtmp"${ac_uD}
+${ac_eA}SSH_WTMP${ac_eB}SSH_WTMP${ac_eC}"/var/log/wtmp"${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}SSH_LASTLOG${ac_dB}SSH_LASTLOG${ac_dC}"/var/log/lastlog"${ac_dD}
+${ac_uA}SSH_LASTLOG${ac_uB}SSH_LASTLOG${ac_uC}"/var/log/lastlog"${ac_uD}
+${ac_eA}SSH_LASTLOG${ac_eB}SSH_LASTLOG${ac_eC}"/var/log/lastlog"${ac_eD}
+${ac_dA}HAVE_LASTLOG${ac_dB}HAVE_LASTLOG${ac_dC}1${ac_dD}
+${ac_uA}HAVE_LASTLOG${ac_uB}HAVE_LASTLOG${ac_uC}1${ac_uD}
+${ac_eA}HAVE_LASTLOG${ac_eB}HAVE_LASTLOG${ac_eC}1${ac_eD}
+${ac_dA}WITH_BLOWFISH${ac_dB}WITH_BLOWFISH${ac_dC}1${ac_dD}
+${ac_uA}WITH_BLOWFISH${ac_uB}WITH_BLOWFISH${ac_uC}1${ac_uD}
+${ac_eA}WITH_BLOWFISH${ac_eB}WITH_BLOWFISH${ac_eC}1${ac_eD}
+${ac_dA}DO_SSL${ac_dB}DO_SSL${ac_dC}1${ac_dD}
+${ac_uA}DO_SSL${ac_uB}DO_SSL${ac_uC}1${ac_uD}
+${ac_eA}DO_SSL${ac_eB}DO_SSL${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}RSH_PATH${ac_dB}RSH_PATH${ac_dC}"/usr/bin/rsh"${ac_dD}
+${ac_uA}RSH_PATH${ac_uB}RSH_PATH${ac_uC}"/usr/bin/rsh"${ac_uD}
+${ac_eA}RSH_PATH${ac_eB}RSH_PATH${ac_eC}"/usr/bin/rsh"${ac_eD}
+${ac_dA}HAVE_ZLIB_H${ac_dB}HAVE_ZLIB_H${ac_dC}1${ac_dD}
+${ac_uA}HAVE_ZLIB_H${ac_uB}HAVE_ZLIB_H${ac_uC}1${ac_uD}
+${ac_eA}HAVE_ZLIB_H${ac_eB}HAVE_ZLIB_H${ac_eC}1${ac_eD}
+${ac_dA}HAVE_LIBZ${ac_dB}HAVE_LIBZ${ac_dC}1${ac_dD}
+${ac_uA}HAVE_LIBZ${ac_uB}HAVE_LIBZ${ac_uC}1${ac_uD}
+${ac_eA}HAVE_LIBZ${ac_eB}HAVE_LIBZ${ac_eC}1${ac_eD}
+${ac_dA}WITH_ZLIB${ac_dB}WITH_ZLIB${ac_dC}1${ac_dD}
+${ac_uA}WITH_ZLIB${ac_uB}WITH_ZLIB${ac_uC}1${ac_uD}
+${ac_eA}WITH_ZLIB${ac_eB}WITH_ZLIB${ac_eC}1${ac_eD}
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ cat > conftest.frag <<CEOF
+${ac_dA}HAVE_LIBKRB${ac_dB}HAVE_LIBKRB${ac_dC}1${ac_dD}
+${ac_uA}HAVE_LIBKRB${ac_uB}HAVE_LIBKRB${ac_uC}1${ac_uD}
+${ac_eA}HAVE_LIBKRB${ac_eB}HAVE_LIBKRB${ac_eC}1${ac_eD}
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+
+
+exit 0
diff --git a/usr.bin/ssh/config.sub b/usr.bin/ssh/config.sub
new file mode 100644
index 00000000000..567459eb1f5
--- /dev/null
+++ b/usr.bin/ssh/config.sub
@@ -0,0 +1,1238 @@
+#! /bin/sh
+# Configuration validation subroutine script, version 1.1.
+# Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc.
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+if [ x$1 = x ]
+then
+ echo Configuration name missing. 1>&2
+ echo "Usage: $0 CPU-MFR-OPSYS" 1>&2
+ echo "or $0 ALIAS" 1>&2
+ echo where ALIAS is a recognized configuration type. 1>&2
+ exit 1
+fi
+
+# First pass through any local machine types.
+case $1 in
+ *local*)
+ echo $1
+ exit 0
+ ;;
+ *)
+ ;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ linux-gnu*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond ) # EGCS LOCAL
+ os=
+ basic_machine=$1
+ ;;
+ -scout) # EGCS LOCAL
+ ;;
+ -wrs) # EGCS LOCAL
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
+ | arme[lb] | pyramid | mn10200 | mn10300 \
+ | tron | a29k | 580 | i960 | h8300 \
+ | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+ | alpha | alphaev5 | alphaev56 | alphapca56 | alphaev6 \
+ | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
+ | 1750a | dsp16xx | pdp11 \
+ | mips64 | mipsel | mips64el | mips64orion | mips64orionel \
+ | mipstx39 | mipstx39el \
+ | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m88110 | m680[012346]0 | m683?2 | m68360 | m5200 | z8k | v70 \
+ | h8500 | w65) # EGCS LOCAL
+ ;;
+ thumb)
+ basic_machine=$basic_machine-unknown
+ ;;
+ mips64vr4300 | mips64vr4300el) # EGCS LOCAL jsmith/vr4300
+ basic_machine=$basic_machine-unknown
+ ;;
+ mips64vr4100 | mips64vr4100el) # EGCS LOCAL jsmith/vr4100
+ basic_machine=$basic_machine-unknown
+ ;;
+ mips64vr5000 | mips64vr5000el) # EGCS LOCAL ian/vr5000
+ basic_machine=$basic_machine-unknown
+ ;;
+ mips16)
+ basic_machine=$basic_machine-unknown
+ ;;
+ d10v)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i[34567]86)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
+ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
+ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
+ | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
+ | xmp-* | ymp-* \
+ | hppa-* | hppa1.0-* | hppa1.1-* \
+ | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
+ | alpha-* | alphaev5-* | alphaev56-* | alphapca56-* \
+ | alphaev6-* | we32k-* | cydra-* | ns16k-* | pn-* | np1-* \
+ | xps100-* | clipper-* | orion-* \
+ | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
+ | sparc64-* | sparcv9-* | sparc86x-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-* \
+ | mipstx39-* | mipstx39el-* \
+ | f301-* | arm*-*)
+ ;;
+ m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | h8500-* | d10v-*) # EGCS LOCAL
+ ;;
+ thumb-*) # EGCS LOCAL angela/thumb
+ ;;
+ v850-*) # EGCS LOCAL
+ ;;
+ d30v-*) # EGCS LOCAL
+ ;;
+ mips64vr4300-* | mips64vr4300el-*) # EGCS LOCAL jsmith/vr4300
+ ;;
+ mips64vr4100-* | mips64vr4100el-*) # EGCS LOCAL jsmith/vr4100
+ ;;
+ mips16-*) # EGCS LOCAL krk/mips16
+ ;;
+ tic30-*) # EGCS LOCAL ian/tic30
+ ;;
+ c30-*) # EGCS LOCAL ian/tic30
+ basic_machine=tic30-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd) # EGCS LOCAL
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif) # EGCS LOCAL
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k) # EGCS LOCAL
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-cbm
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-cbm
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-cbm
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd) # EGCS LOCAL
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ cray2)
+ basic_machine=cray2-cray
+ os=-unicos
+ ;;
+ [ctj]90-cray)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE) # EGCS LOCAL
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray) # EGCS LOCAL
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms) # EGCS LOCAL
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ w89k-*) # EGCS LOCAL
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ op50n-*) # EGCS LOCAL
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ op60c-*) # EGCS LOCAL
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ hppro) # EGCS LOCAL
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9] )
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9] )
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9] )
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | \
+ hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893 )
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679] )
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf) # EGCS LOCAL
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i[34567]86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i[34567]86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i[34567]86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i[34567]86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach) # EGCS LOCAL
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta) # EGCS LOCAL
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ i386-go32 | go32) # EGCS LOCAL
+ basic_machine=i386-unknown
+ os=-go32
+ ;;
+ i386-mingw32 | mingw32)
+ basic_machine=i386-unknown
+ os=-mingw32
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ mipsel*-linux*)
+ basic_machine=mipsel-unknown
+ os=-linux-gnu
+ ;;
+ mips*-linux*)
+ basic_machine=mips-unknown
+ os=-linux-gnu
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor) # EGCS LOCAL
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ msdos) # EGCS LOCAL
+ basic_machine=i386-unknown
+ os=-msdos
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown # EGCS LOCAL
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-corel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70) # EGCS LOCAL
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960) # EGCS LOCAL
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ OSE68000 | ose68000) # EGCS LOCAL
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k) # EGCS LOCAL
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexen)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexen-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=rs6000-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rom68k) # EGCS LOCAL
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ sa29200) # EGCS LOCAL
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sparclite-wrs) # EGCS LOCAL
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000) # EGCS LOCAL
+ basic_machine=m68k-tandem
+ ;;
+ stratus) # EGCS LOCAL
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810) # EGCS LOCAL
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*) # EGCS LOCAL
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ xmp)
+ basic_machine=xmp-cray
+ os=-unicos
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ z8k-*-coff) # EGCS LOCAL
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k) # EGCS LOCAL
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n) # EGCS LOCAL
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c) # EGCS LOCAL
+ basic_machine=hppa1.1-oki
+ ;;
+ mips)
+ if [ x$os = x-linux-gnu ]; then
+ basic_machine=mips-unknown
+ else
+ basic_machine=mips-mips
+ fi
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sparc | sparcv9)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw) # EGCS LOCAL
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw) # EGCS LOCAL
+ basic_machine=powerpc-apple
+ ;;
+ c4x*)
+ basic_machine=c4x-none
+ os=-coff
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* )
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ # EGCS LOCAL
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mon960* | -lnews* )
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ # END EGCS LOCAL
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -386bsd) # EGCS LOCAL
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*) # EGCS LOCAL
+ os=-ose
+ ;;
+ -es1800*) # EGCS LOCAL
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-corel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco) # EGCS LOCAL
+ os=-aout
+ ;;
+ mips*-cisco) # EGCS LOCAL
+ os=-elf
+ ;;
+ mips*-*) # EGCS LOCAL
+ os=-elf
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-wec) # EGCS LOCAL
+ os=-proelf
+ ;;
+ *-winbond) # EGCS LOCAL
+ os=-proelf
+ ;;
+ *-oki) # EGCS LOCAL
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f301-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k) # EGCS LOCAL
+ os=-coff
+ ;;
+ *-*bug) # EGCS LOCAL
+ os=-coff
+ ;;
+ *-apple) # EGCS LOCAL
+ os=-macos
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*) # EGCS LOCAL
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*) # EGCS LOCAL
+ vendor=apple
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
diff --git a/usr.bin/ssh/configure b/usr.bin/ssh/configure
new file mode 100644
index 00000000000..62007c509de
--- /dev/null
+++ b/usr.bin/ssh/configure
@@ -0,0 +1,5293 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-warnings Enable -Wall if using gcc."
+ac_help="$ac_help
+ --with-gmp[=PATH] Where to find GMP library."
+ac_help="$ac_help
+ --with-idea Use IDEA (not default).
+ --without-idea Don't use IDEA: avoids patent problems in commercial use"
+ac_help="$ac_help
+ --with-rc4 Include RC4 support.
+ --without-rc4 Don't include RC4 support (default)"
+ac_help="$ac_help
+ --with-blowfish Include Blowfish support (default).
+ --without-blowfish Don't include Blowfish support"
+ac_help="$ac_help
+ --with-rsaref Use RSAREF (try to avoid patent problems in U.S.)
+ --without-rsaref Use normal RSA routines (default). "
+ac_help="$ac_help
+ --with-ssl Use SSL (try to avoid patent problems in U.S.)
+ --without-ssl Use normal RSA routines (default). "
+ac_help="$ac_help
+ --with-rsh=PATH Specify where to find rsh.
+ --without-rsh Do not use rsh under any conditions. "
+ac_help="$ac_help
+ --with-path=PATH Default path passed to user shell by sshd."
+ac_help="$ac_help
+ --with-etcdir=PATH Directory containing ssh system files (default /etc)."
+ac_help="$ac_help
+ --with-securid[=PATH] Enable support for Security Dynamics SecurID card."
+ac_help="$ac_help
+ --with-zlib Use zlib (default).
+ --without-zlib Don't use zlib."
+ac_help="$ac_help
+ --with-krb4[=PATH] Compile in Kerberos v4 support."
+ac_help="$ac_help
+ --with-afs Compile in AFS support (requires KTH krb4)."
+ac_help="$ac_help
+ --with-libwrap[=PATH] Compile in libwrap (tcp_wrappers) support."
+ac_help="$ac_help
+ --with-socks[=PATH] Compile with SOCKS firewall traversal support."
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=sshd.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+
+# Make sure we can run config.sub.
+if ${CONFIG_SHELL-/bin/sh} $ac_config_sub sun4 >/dev/null 2>&1; then :
+else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking host system type""... $ac_c" 1>&6
+echo "configure:593: checking host system type" >&5
+
+host_alias=$host
+case "$host_alias" in
+NONE)
+ case $nonopt in
+ NONE)
+ if host_alias=`${CONFIG_SHELL-/bin/sh} $ac_config_guess`; then :
+ else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
+ fi ;;
+ *) host_alias=$nonopt ;;
+ esac ;;
+esac
+
+host=`${CONFIG_SHELL-/bin/sh} $ac_config_sub $host_alias`
+host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+echo "$ac_t""$host" 1>&6
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:617: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:647: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:698: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:730: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 741 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:746: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:772: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:777: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:786: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:805: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:837: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 852 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:858: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 869 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:875: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 886 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:892: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+
+case "$host" in
+ *-*-sunos4.1.1*)
+ os_sunos=yes
+ # Tim Adam <tma@osa.com.au> says speed_t is defined in stdtypes.h
+ cat >> confdefs.h <<\EOF
+#define SPEED_T_IN_STDTYPES_H 1
+EOF
+
+ ;;
+ *-*-sunos*)
+ os_sunos=yes
+ ;;
+ *-sgi-irix5*)
+ # Irix stuff from snabb@niksula.hut.fi and tsurmacz@asic.ict.pwr.wroc.pl.
+ no_libsocket=yes
+ no_libsun=yes
+ ;;
+ *-sgi-irix6*)
+ # from d-champion@uchicago.edu
+ no_libsocket=yes
+ no_libsun=yes
+ if test "`uname -s`" = "IRIX64"; then
+ CFLAGS="-32 $CFLAGS"
+ LDFLAGS="-32 $LDFLAGS"
+ fi
+ ;;
+ *-ibm-aix3.2|*-ibm-aix3.2.0|*-ibm-aix3.2.1|*-ibm-aix3.2.2|*-ibm-aix3.2.3|*-ibm-aix3.2.4)
+ os_aix=yes
+ echo $ac_n "checking for getuserattr in -ls""... $ac_c" 1>&6
+echo "configure:946: checking for getuserattr in -ls" >&5
+ac_lib_var=`echo s'_'getuserattr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ls $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 954 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getuserattr();
+
+int main() {
+getuserattr()
+; return 0; }
+EOF
+if { (eval echo configure:965: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo s | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-ls $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+ *-ibm-aix*)
+ os_aix=yes
+ echo $ac_n "checking for getuserattr in -ls""... $ac_c" 1>&6
+echo "configure:996: checking for getuserattr in -ls" >&5
+ac_lib_var=`echo s'_'getuserattr | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ls $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1004 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getuserattr();
+
+int main() {
+getuserattr()
+; return 0; }
+EOF
+if { (eval echo configure:1015: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo s | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-ls $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+ mips-dec-mach3*)
+ # Mach3 stuff from kivinen@hut.fi
+ no_vhangup=yes
+ ;;
+ *-dec-ultrix*)
+ # Ultrix stuff from dmckilli@qc.bell.ca, jbotz@orixa.mtholyoke.edu.
+ cat >> confdefs.h <<\EOF
+#define O_NONBLOCK_BROKEN 1
+EOF
+
+ no_vhangup=yes
+ cat > conftest.$ac_ext <<EOF
+#line 1055 "configure"
+#include "confdefs.h"
+#include <syslog.h>
+int main() {
+int foo = LOG_DAEMON;
+; return 0; }
+EOF
+if { (eval echo configure:1062: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define NEED_SYS_SYSLOG_H 1
+EOF
+
+fi
+rm -f conftest*
+ ;;
+ *-*-hpux*)
+ # HPUX flags from jgotts@engin.umich.edu
+ if test -z "$GCC"; then
+ CFLAGS="$CFLAGS -Aa -D_HPUX_SOURCE"
+ fi
+ cat >> confdefs.h <<\EOF
+#define HPSUX_NONSTANDARD_X11_KLUDGE 1
+EOF
+
+ ;;
+ alpha-dec-osf*)
+ cat >> confdefs.h <<\EOF
+#define TTY_GROUP "terminal"
+EOF
+
+ echo $ac_n "checking for set_auth_parameters in -lsecurity""... $ac_c" 1>&6
+echo "configure:1091: checking for set_auth_parameters in -lsecurity" >&5
+ac_lib_var=`echo security'_'set_auth_parameters | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsecurity $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1099 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char set_auth_parameters();
+
+int main() {
+set_auth_parameters()
+; return 0; }
+EOF
+if { (eval echo configure:1110: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo security | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsecurity $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ echo $ac_n "checking for OSF/1 C2 security package""... $ac_c" 1>&6
+echo "configure:1138: checking for OSF/1 C2 security package" >&5
+ osfc2sec=`/usr/sbin/setld -i | grep '^OSFC2SEC'`
+ if test -n "$osfc2sec"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_OSF1_C2_SECURITY 1
+EOF
+
+ echo $ac_n "checking for set_auth_parameters in -lsecurity""... $ac_c" 1>&6
+echo "configure:1147: checking for set_auth_parameters in -lsecurity" >&5
+ac_lib_var=`echo security'_'set_auth_parameters | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsecurity $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1155 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char set_auth_parameters();
+
+int main() {
+set_auth_parameters()
+; return 0; }
+EOF
+if { (eval echo configure:1166: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lsecurity"
+else
+ echo "$ac_t""no" 1>&6
+{ echo "configure: error: "Could not find libsecurity even though C2 security installed."" 1>&2; exit 1; }
+fi
+
+ CONFOBJS="$CONFOBJS osfc2.o"
+ else
+ echo "$ac_t""no" 1>&6
+ fi
+ ;;
+ *-*-nextstep*)
+ # Nextstep support from a person who wants to remain anonymous
+ no_termios=yes
+ cat >> confdefs.h <<\EOF
+#define SPEED_T_IN_STDTYPES_H 1
+EOF
+
+ ;;
+ *-*-linux*)
+ # Linux shadow password support (Andrew.Macpherson.1248566@bnr.co.uk)
+ if test -f /etc/shadow && test -f /etc/login.defs; then
+ echo "$ac_t""Using linux John Haugh shadow passwords and pw_encrypt for password encryption" 1>&6
+ cat >> confdefs.h <<\EOF
+#define crypt pw_encrypt
+EOF
+
+ LIBS="$LIBS -lshadow"
+ fi
+ ;;
+ i*86-*-bsdi*)
+ no_pipe=yes
+ ;;
+ i*86-unknown-bsd*)
+ # Assume 386BSD. pgut01@cs.auckland.ac.nz reported this makes it compile.
+ cat >> confdefs.h <<\EOF
+#define __FreeBSD__ 1
+EOF
+
+ ;;
+ m68k-sony-newsos*)
+ # From snabb@niksula.hut.fi
+ no_vhangup=yes
+ ;;
+ m88k-dg-dgux*)
+ cat >> confdefs.h <<\EOF
+#define BROKEN_INET_ADDR 1
+EOF
+
+ ;;
+ *-cray-unicos*)
+ CFLAGS="$CFLAGS -DCRAY_STACKSEG_END=_getb67"
+ ;;
+ *-*-sysv4*)
+ echo $ac_n "checking for openlog in -lgen""... $ac_c" 1>&6
+echo "configure:1236: checking for openlog in -lgen" >&5
+ac_lib_var=`echo gen'_'openlog | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lgen $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1244 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char openlog();
+
+int main() {
+openlog()
+; return 0; }
+EOF
+if { (eval echo configure:1255: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo gen | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lgen $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+ *-*-machten*)
+ cat >> confdefs.h <<\EOF
+#define USE_STRLEN_FOR_AF_UNIX 1
+EOF
+
+ ;;
+ i*86-unknown-sco*)
+ # From moi@dio.com
+ cat >> confdefs.h <<\EOF
+#define HAVE_SCO_ETC_SHADOW 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define SCO 1
+EOF
+
+ no_ranlib=yes
+ LIBS="-L/usr/lib/libp -lprot -lx $LIBS"
+ ;;
+ *-convex-bsd*)
+ # From mark.martinec@nsc.ijs.si
+ # On Convex, getpwnam sets pw_passwd if running as root
+ no_shadows_password_checking=yes
+ ;;
+ *-*-freebsd*)
+ # From Ollivier Robert: FreeBSD and NetBSD use master.passwd, but set
+ # pw_passwd automatically when running as root.
+ no_shadow_password_checking=yes
+ ;;
+ *-*-netbsd*)
+ # From Ollivier Robert: FreeBSD and NetBSD use master.passwd, but set
+ # pw_passwd automatically when running as root.
+ no_shadow_password_checking=yes
+ ;;
+ *-*-openbsd*)
+ no_shadow_password_checking=yes
+ ;;
+ *)
+ ;;
+esac
+
+# Socket pairs appear to be broken on several systems. I don't know exactly
+# where, so I'll use pipes everywhere for now.
+cat >> confdefs.h <<\EOF
+#define USE_PIPES 1
+EOF
+
+
+echo $ac_n "checking that the compiler works""... $ac_c" 1>&6
+echo "configure:1332: checking that the compiler works" >&5
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: Could not compile and run even a trivial ANSI C program - check CC." 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1337 "configure"
+#include "confdefs.h"
+ main(int ac, char **av) { return 0; }
+EOF
+if { (eval echo configure:1341: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ echo "$ac_t""no" 1>&6
+ { echo "configure: error: Could not compile and run even a trivial ANSI C program - check CC." 1>&2; exit 1; }
+fi
+rm -fr conftest*
+fi
+
+
+if test -z "$no_pipe"; then
+if test -n "$GCC"; then
+ echo $ac_n "checking if the compiler understands -pipe""... $ac_c" 1>&6
+echo "configure:1358: checking if the compiler understands -pipe" >&5
+ OLDCC="$CC"
+ CC="$CC -pipe"
+ cat > conftest.$ac_ext <<EOF
+#line 1362 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1369: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ echo "$ac_t""yes" 1>&6
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CC="$OLDCC"
+ echo "$ac_t""no" 1>&6
+fi
+rm -f conftest*
+fi
+fi
+
+# Check whether --enable-warnings or --disable-warnings was given.
+if test "${enable_warnings+set}" = set; then
+ enableval="$enable_warnings"
+ if test -n "$GCC"; then
+ echo "$ac_t""Adding -Wall to CFLAGS." 1>&6
+ CFLAGS="$CFLAGS -Wall"
+ fi
+fi
+
+
+if test -z "$no_vhangup"; then
+ for ac_func in vhangup
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1397: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1402 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1425: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+if test -z "$no_setsid"; then
+ for ac_func in setsid
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1455: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1460 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1483: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking where to find mandatory GMP library""... $ac_c" 1>&6
+echo "configure:1510: checking where to find mandatory GMP library" >&5
+# Check whether --with-gmp or --without-gmp was given.
+if test "${with_gmp+set}" = set; then
+ withval="$with_gmp"
+ case "$withval" in
+ no)
+ echo "GMP is mandatory! Aborting!"
+ exit 1
+ ;;
+ *)
+ ;;
+ esac
+else
+ with_gmp=yes
+
+fi
+
+# gmp continued
+echo argument="$with_gmp"
+case "$with_gmp" in
+yes)
+ for ac_hdr in gmp.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1535: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1540 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1545: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ if test "$ac_cv_header_gmp_h" != yes; then
+ echo "Can't find include file gmp.h! Aborting!"
+ echo "You must first build and install GMP, please read the file INSTALL"
+ exit 1
+ fi
+ echo $ac_n "checking for main in -lgmp""... $ac_c" 1>&6
+echo "configure:1577: checking for main in -lgmp" >&5
+ac_lib_var=`echo gmp'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lgmp $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1585 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo gmp | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lgmp $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "$ac_cv_lib_gmp_main" != yes; then
+ echo "Can't find library gmp (libgmp.a)! Aborting"
+ echo "You must first build and install GMP, please read the file INSTALL"
+ exit 1
+ fi
+ GMPINCS=""
+ GMPLIBS="-lgmp"
+ ;;
+*)
+ GMPINCS="-I$with_gmp/include"
+ GMPLIBS="-L$with_gmp/lib -lgmp"
+ ;;
+esac
+
+for ac_func in _getpty clock fchmod getdtablesize gethostname getrusage
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1636: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1641 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1664: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in gettimeofday initgroups innetgr memcpy openpty popen seteuid
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1691: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1696 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_func in setlogin setluid setrlimit strchr times ulimit umask vsnprintf
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:1746: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1751 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1774: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+
+echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
+echo "configure:1800: checking return type of signal handlers" >&5
+if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1805 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C" void (*signal (int, void (*)(int)))(int);
+#else
+void (*signal ()) ();
+#endif
+
+int main() {
+int i;
+; return 0; }
+EOF
+if { (eval echo configure:1822: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_type_signal=void
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_type_signal=int
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_type_signal" 1>&6
+cat >> confdefs.h <<EOF
+#define RETSIGTYPE $ac_cv_type_signal
+EOF
+
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1841: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1846 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1854: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1871 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1889 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1910 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1921: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:1945: checking for size_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1950 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_size_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+ cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
+echo "configure:1978: checking for uid_t in sys/types.h" >&5
+if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1983 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "uid_t" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_uid_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_uid_t=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_type_uid_t" 1>&6
+if test $ac_cv_type_uid_t = no; then
+ cat >> confdefs.h <<\EOF
+#define uid_t int
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define gid_t int
+EOF
+
+fi
+
+echo $ac_n "checking for off_t""... $ac_c" 1>&6
+echo "configure:2012: checking for off_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2017 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_off_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_off_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_off_t" 1>&6
+if test $ac_cv_type_off_t = no; then
+ cat >> confdefs.h <<\EOF
+#define off_t long
+EOF
+
+fi
+
+echo $ac_n "checking for mode_t""... $ac_c" 1>&6
+echo "configure:2045: checking for mode_t" >&5
+if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2050 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "(^|[^a-zA-Z_0-9])mode_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_type_mode_t=yes
+else
+ rm -rf conftest*
+ ac_cv_type_mode_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_mode_t" 1>&6
+if test $ac_cv_type_mode_t = no; then
+ cat >> confdefs.h <<\EOF
+#define mode_t int
+EOF
+
+fi
+
+echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
+echo "configure:2078: checking for st_blksize in struct stat" >&5
+if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2083 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+int main() {
+struct stat s; s.st_blksize;
+; return 0; }
+EOF
+if { (eval echo configure:2091: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_struct_st_blksize=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_struct_st_blksize=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6
+if test $ac_cv_struct_st_blksize = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ST_BLKSIZE 1
+EOF
+
+fi
+
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2113: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2118 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:2167: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:2188: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 2195 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:2202: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
+echo "configure:2228: checking whether byte ordering is bigendian" >&5
+if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_bigendian=unknown
+# See if sys/param.h defines the BYTE_ORDER macro.
+cat > conftest.$ac_ext <<EOF
+#line 2235 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
+ bogus endian macros
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:2246: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+cat > conftest.$ac_ext <<EOF
+#line 2250 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+int main() {
+
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+#endif
+; return 0; }
+EOF
+if { (eval echo configure:2261: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_bigendian=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_bigendian=no
+fi
+rm -f conftest*
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+if test $ac_cv_c_bigendian = unknown; then
+if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2281 "configure"
+#include "confdefs.h"
+main () {
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long l;
+ char c[sizeof (long)];
+ } u;
+ u.l = 1;
+ exit (u.c[sizeof (long) - 1] == 1);
+}
+EOF
+if { (eval echo configure:2294: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_c_bigendian=no
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_c_bigendian=yes
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_c_bigendian" 1>&6
+if test $ac_cv_c_bigendian = yes; then
+ cat >> confdefs.h <<\EOF
+#define WORDS_BIGENDIAN 1
+EOF
+
+fi
+
+echo $ac_n "checking size of long""... $ac_c" 1>&6
+echo "configure:2318: checking size of long" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2326 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(long));
+ exit(0);
+}
+EOF
+if { (eval echo configure:2337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_long=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_long=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_long" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+EOF
+
+
+echo $ac_n "checking size of int""... $ac_c" 1>&6
+echo "configure:2357: checking size of int" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2365 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(int));
+ exit(0);
+}
+EOF
+if { (eval echo configure:2376: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_int=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_int=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_int" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+EOF
+
+
+echo $ac_n "checking size of short""... $ac_c" 1>&6
+echo "configure:2396: checking size of short" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2404 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(short));
+ exit(0);
+}
+EOF
+if { (eval echo configure:2415: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_short=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_short=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_short" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+EOF
+
+
+
+if test -z "$no_termios"; then
+ for ac_hdr in termios.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2440: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2445 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2450: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2479: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2484 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2492: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2509 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 2527 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2548 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:2559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:2583: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2588 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:2604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+for ac_hdr in unistd.h rusage.h sys/time.h lastlog.h utmp.h utmpx.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2628: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2633 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2638: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in sgtty.h sys/select.h sys/ioctl.h sys/filio.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2668: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2673 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2678: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in paths.h usersec.h utime.h netinet/in_systm.h ulimit.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2708: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2713 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2718: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
+echo "configure:2745: checking whether time.h and sys/time.h may both be included" >&5
+if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2750 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+int main() {
+struct tm *tp;
+; return 0; }
+EOF
+if { (eval echo configure:2759: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_time=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_time=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_time" 1>&6
+if test $ac_cv_header_time = yes; then
+ cat >> confdefs.h <<\EOF
+#define TIME_WITH_SYS_TIME 1
+EOF
+
+fi
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+echo "configure:2784: checking for $ac_hdr that defines DIR" >&5
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2789 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if { (eval echo configure:2797: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
+echo "configure:2822: checking for opendir in -ldir" >&5
+ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldir $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2830 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:2841: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -ldir"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
+echo "configure:2863: checking for opendir in -lx" >&5
+ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lx $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 2871 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char opendir();
+
+int main() {
+opendir()
+; return 0; }
+EOF
+if { (eval echo configure:2882: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ LIBS="$LIBS -lx"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
+echo "configure:2905: checking whether stat file-mode macros are broken" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2910 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(S_ISBLK) && defined(S_IFDIR)
+# if S_ISBLK (S_IFDIR)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISBLK) && defined(S_IFCHR)
+# if S_ISBLK (S_IFCHR)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISLNK) && defined(S_IFREG)
+# if S_ISLNK (S_IFREG)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISSOCK) && defined(S_IFREG)
+# if S_ISSOCK (S_IFREG)
+You lose.
+# endif
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "You lose" >/dev/null 2>&1; then
+ rm -rf conftest*
+ ac_cv_header_stat_broken=yes
+else
+ rm -rf conftest*
+ ac_cv_header_stat_broken=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_header_stat_broken" 1>&6
+if test $ac_cv_header_stat_broken = yes; then
+ cat >> confdefs.h <<\EOF
+#define STAT_MACROS_BROKEN 1
+EOF
+
+fi
+
+cat > conftest.$ac_ext <<EOF
+#line 2961 "configure"
+#include "confdefs.h"
+#include <utmp.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ut_pid" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_PID_IN_UTMP 1
+EOF
+
+fi
+rm -f conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 2976 "configure"
+#include "confdefs.h"
+#include <utmp.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ut_name" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_NAME_IN_UTMP 1
+EOF
+
+fi
+rm -f conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 2991 "configure"
+#include "confdefs.h"
+#include <utmp.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ut_id" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_ID_IN_UTMP 1
+EOF
+
+fi
+rm -f conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 3006 "configure"
+#include "confdefs.h"
+#include <utmp.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ut_host" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_HOST_IN_UTMP 1
+EOF
+
+fi
+rm -f conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 3021 "configure"
+#include "confdefs.h"
+#include <utmp.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ut_addr" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_ADDR_IN_UTMP 1
+EOF
+
+fi
+rm -f conftest*
+
+
+cat > conftest.$ac_ext <<EOF
+#line 3037 "configure"
+#include "confdefs.h"
+#include <utmpx.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ut_session" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_UT_SESSION 1
+EOF
+
+fi
+rm -f conftest*
+
+cat > conftest.$ac_ext <<EOF
+#line 3052 "configure"
+#include "confdefs.h"
+#include <utmpx.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "ut_syslen" >/dev/null 2>&1; then
+ rm -rf conftest*
+ cat >> confdefs.h <<\EOF
+#define HAVE_UT_SYSLEN 1
+EOF
+
+fi
+rm -f conftest*
+
+
+echo $ac_n "checking for crypt in -lc""... $ac_c" 1>&6
+echo "configure:3068: checking for crypt in -lc" >&5
+ac_lib_var=`echo c'_'crypt | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lc $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3076 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char crypt();
+
+int main() {
+crypt()
+; return 0; }
+EOF
+if { (eval echo configure:3087: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ true
+else
+ echo "$ac_t""no" 1>&6
+echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
+echo "configure:3106: checking for crypt in -lcrypt" >&5
+ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcrypt $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3114 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char crypt();
+
+int main() {
+crypt()
+; return 0; }
+EOF
+if { (eval echo configure:3125: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo crypt | sed -e 's/^a-zA-Z0-9_/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lcrypt $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
+echo "configure:3155: checking for main in -lnsl" >&5
+ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3163 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:3170: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lnsl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$no_libsocket"; then
+ echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6
+echo "configure:3199: checking for socket in -lsocket" >&5
+ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsocket $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3207 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char socket();
+
+int main() {
+socket()
+; return 0; }
+EOF
+if { (eval echo configure:3218: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo socket | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsocket $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+if test -z "$no_libsun"; then
+ echo $ac_n "checking for getpwnam in -lsun""... $ac_c" 1>&6
+echo "configure:3248: checking for getpwnam in -lsun" >&5
+ac_lib_var=`echo sun'_'getpwnam | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lsun $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3256 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char getpwnam();
+
+int main() {
+getpwnam()
+; return 0; }
+EOF
+if { (eval echo configure:3267: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo sun | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lsun $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+fi
+echo $ac_n "checking for login in -lutil""... $ac_c" 1>&6
+echo "configure:3296: checking for login in -lutil" >&5
+ac_lib_var=`echo util'_'login | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lutil $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3304 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char login();
+
+int main() {
+login()
+; return 0; }
+EOF
+if { (eval echo configure:3315: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_LIBUTIL_LOGIN 1
+EOF
+
+ LIBS="$LIBS -lutil"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking for main in -ldes""... $ac_c" 1>&6
+echo "configure:3341: checking for main in -ldes" >&5
+ac_lib_var=`echo des'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-ldes $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 3349 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:3356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo des | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-ldes $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+for ac_func in strerror memmove remove random putenv socketpair
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:3387: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3392 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:3415: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+LIBOBJS="$LIBOBJS ${ac_func}.${ac_objext}"
+fi
+done
+
+
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:3443: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
+fi
+fi
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:3475: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+if test -z "$no_ranlib"; then
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3531: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_RANLIB="ranlib"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+fi
+fi
+RANLIB="$ac_cv_prog_RANLIB"
+if test -n "$RANLIB"; then
+ echo "$ac_t""$RANLIB" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+else
+ RANLIB=":"
+fi
+for ac_prog in makedepend makedep
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3566: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_MAKEDEP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$MAKEDEP"; then
+ ac_cv_prog_MAKEDEP="$MAKEDEP" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_MAKEDEP="$ac_prog"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+MAKEDEP="$ac_cv_prog_MAKEDEP"
+if test -n "$MAKEDEP"; then
+ echo "$ac_t""$MAKEDEP" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$MAKEDEP" && break
+done
+test -n "$MAKEDEP" || MAKEDEP="makedepend"
+
+for ac_prog in wish8.0 wish wishx wish4.1 true
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3601: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_WISH'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$WISH" in
+ /*)
+ ac_cv_path_WISH="$WISH" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_WISH="$WISH" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_WISH="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+WISH="$ac_cv_path_WISH"
+if test -n "$WISH"; then
+ echo "$ac_t""$WISH" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$WISH" && break
+done
+
+if test `basename $WISH` = "true"; then
+ echo "configure: warning: the wish program was not found - ssh-askpass will not work." 1>&2
+ WISH="/usr/local/bin/wish"
+fi
+# Extract the first word of "xauth", so it can be a program name with args.
+set dummy xauth; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:3643: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_XAUTH_PATH'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$XAUTH_PATH" in
+ /*)
+ ac_cv_path_XAUTH_PATH="$XAUTH_PATH" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_XAUTH_PATH="$XAUTH_PATH" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH:/usr/X11R6/bin"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_XAUTH_PATH="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+XAUTH_PATH="$ac_cv_path_XAUTH_PATH"
+if test -n "$XAUTH_PATH"; then
+ echo "$ac_t""$XAUTH_PATH" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -n "$XAUTH_PATH"; then
+ cat >> confdefs.h <<EOF
+#define XAUTH_PATH "$XAUTH_PATH"
+EOF
+
+fi
+
+echo $ac_n "checking for pseudo ttys""... $ac_c" 1>&6
+echo "configure:3683: checking for pseudo ttys" >&5
+if test -c /dev/ptmx && test -c /dev/pts/0
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_DEV_PTMX 1
+EOF
+
+ echo "$ac_t""streams ptys" 1>&6
+else
+if test -c /dev/pts && test -c /dev/ptc
+then
+ cat >> confdefs.h <<\EOF
+#define HAVE_DEV_PTS_AND_PTC 1
+EOF
+
+ echo "$ac_t""/dev/pts and /dev/ptc" 1>&6
+else
+ echo "$ac_t""bsd-style ptys" 1>&6
+fi
+fi
+
+echo $ac_n "checking for /etc/default/login""... $ac_c" 1>&6
+echo "configure:3705: checking for /etc/default/login" >&5
+if test -f /etc/default/login; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ETC_DEFAULT_LOGIN 1
+EOF
+
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$no_shadows_password_checking"; then
+ echo $ac_n "checking for shadow passwords""... $ac_c" 1>&6
+echo "configure:3718: checking for shadow passwords" >&5
+ if test -f /etc/shadow; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ETC_SHADOW 1
+EOF
+
+ echo "$ac_t""/etc/shadow" 1>&6
+ elif test -n "$os_aix"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ETC_SECURITY_PASSWD 1
+EOF
+
+ echo "$ac_t""/etc/security/passwd" 1>&6
+ elif test -n "$os_sunos"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_ETC_SECURITY_PASSWD_ADJUNCT 1
+EOF
+
+ echo "$ac_t""/etc/security/passwd.adjunct" 1>&6
+ else
+ echo "$ac_t""no" 1>&6
+ fi
+fi
+
+echo $ac_n "checking location of mail spool files""... $ac_c" 1>&6
+echo "configure:3743: checking location of mail spool files" >&5
+for dir in /var/spool/mail /var/mail /usr/spool/mail /usr/mail NEWMAIL
+do
+ if test "$dir" = "NEWMAIL"; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_TILDE_NEWMAIL 1
+EOF
+
+ echo "$ac_t""\$HOME/newmail" 1>&6
+ echo "configure: warning: mail spool directory was not found: assuming you use \$HOME/newmail" 1>&2
+ elif test -d $dir; then
+ cat >> confdefs.h <<EOF
+#define MAIL_SPOOL_DIRECTORY "$dir"
+EOF
+
+ echo "$ac_t""$dir" 1>&6
+ break
+ fi
+done
+
+echo $ac_n "checking location of utmp""... $ac_c" 1>&6
+echo "configure:3764: checking location of utmp" >&5
+if test -f /var/run/utmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_UTMP "/var/run/utmp"
+EOF
+
+ echo "$ac_t""/var/run/utmp" 1>&6
+elif test -f /var/log/utmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_UTMP "/var/log/utmp"
+EOF
+
+ echo "$ac_t""/var/log/utmp" 1>&6
+elif test -f /var/adm/utmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_UTMP "/var/adm/utmp"
+EOF
+
+ echo "$ac_t""/var/adm/utmp" 1>&6
+elif test -f /usr/adm/utmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_UTMP "/usr/adm/utmp"
+EOF
+
+ echo "$ac_t""/usr/adm/utmp" 1>&6
+elif test -f /etc/utmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_UTMP "/etc/utmp"
+EOF
+
+ echo "$ac_t""/etc/utmp" 1>&6
+else
+ echo "$ac_t""not found" 1>&6
+fi
+
+echo $ac_n "checking location of wtmp""... $ac_c" 1>&6
+echo "configure:3800: checking location of wtmp" >&5
+if test -f /var/log/wtmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_WTMP "/var/log/wtmp"
+EOF
+
+ echo "$ac_t""/var/log/wtmp" 1>&6
+elif test -f /var/adm/wtmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_WTMP "/var/adm/wtmp"
+EOF
+
+ echo "$ac_t""/var/adm/wtmp" 1>&6
+elif test -f /usr/adm/wtmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_WTMP "/usr/adm/wtmp"
+EOF
+
+ echo "$ac_t""/usr/adm/wtmp" 1>&6
+elif test -f /etc/wtmp; then
+ cat >> confdefs.h <<\EOF
+#define SSH_WTMP "/etc/wtmp"
+EOF
+
+ echo "$ac_t""/etc/wtmp" 1>&6
+else
+ cat >> confdefs.h <<\EOF
+#define SSH_WTMP "/var/adm/wtmp"
+EOF
+
+ echo "$ac_t""not found" 1>&6
+fi
+
+echo $ac_n "checking location of lastlog""... $ac_c" 1>&6
+echo "configure:3834: checking location of lastlog" >&5
+if test -f /var/log/lastlog || test -d /var/log/lastlog; then
+ cat >> confdefs.h <<\EOF
+#define SSH_LASTLOG "/var/log/lastlog"
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_LASTLOG 1
+EOF
+
+ LASTLOG=/var/log/lastlog
+ echo "$ac_t""/var/log/lastlog" 1>&6
+elif test -f /var/adm/lastlog || test -d /var/adm/lastlog; then
+ cat >> confdefs.h <<\EOF
+#define SSH_LASTLOG "/var/adm/lastlog"
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_LASTLOG 1
+EOF
+
+ LASTLOG=/var/adm/lastlog
+ echo "$ac_t""/var/adm/lastlog" 1>&6
+elif test -f /usr/adm/lastlog || test -d /usr/adm/lastlog; then
+ cat >> confdefs.h <<\EOF
+#define SSH_LASTLOG "/usr/adm/lastlog"
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_LASTLOG 1
+EOF
+
+ LASTLOG=/usr/adm/lastlog
+ echo "$ac_t""/usr/adm/lastlog" 1>&6
+elif test -f /etc/lastlog || test -d /etc/lastlog; then
+ cat >> confdefs.h <<\EOF
+#define SSH_LASTLOG "/etc/lastlog"
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define HAVE_LASTLOG 1
+EOF
+
+ LASTLOG=/etc/lastlog
+ echo "$ac_t""/etc/lastlog" 1>&6
+else
+ echo "$ac_t""not found" 1>&6
+ cat >> confdefs.h <<\EOF
+#define SSH_LASTLOG "/var/log/lastlog"
+EOF
+
+ LASTLOG=/var/log/lastlog
+fi
+
+echo $ac_n "checking whether $LASTLOG is a directory""... $ac_c" 1>&6
+echo "configure:3889: checking whether $LASTLOG is a directory" >&5
+if test -d $LASTLOG
+then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define LASTLOG_IS_DIR 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking whether to include the IDEA encryption algorithm""... $ac_c" 1>&6
+echo "configure:3902: checking whether to include the IDEA encryption algorithm" >&5
+# Check whether --with-idea or --without-idea was given.
+if test "${with_idea+set}" = set; then
+ withval="$with_idea"
+ case "$withval" in
+ yes)
+ echo "$ac_t""yes" 1>&6
+ CONFOBJS="$CONFOBJS idea.o"
+ cat >> confdefs.h <<\EOF
+#define WITH_IDEA 1
+EOF
+
+ ;;
+ *)
+ echo "$ac_t""no" 1>&6
+ ;;
+ esac
+else
+ echo "$ac_t""no" 1>&6
+
+fi
+
+
+echo $ac_n "checking whether to include the RC4 encryption algorithm""... $ac_c" 1>&6
+echo "configure:3926: checking whether to include the RC4 encryption algorithm" >&5
+# Check whether --with-rc4 or --without-rc4 was given.
+if test "${with_rc4+set}" = set; then
+ withval="$with_rc4"
+ case "$withval" in
+ yes)
+ echo "$ac_t""yes" 1>&6
+ CONFOBJS="$CONFOBJS rc4.o"
+ cat >> confdefs.h <<\EOF
+#define WITH_RC4 1
+EOF
+
+ ;;
+ *)
+ echo "$ac_t""no" 1>&6
+ ;;
+ esac
+else
+ echo "$ac_t""no" 1>&6
+
+fi
+
+
+echo $ac_n "checking whether to include the Blowfish encryption algorithm""... $ac_c" 1>&6
+echo "configure:3950: checking whether to include the Blowfish encryption algorithm" >&5
+# Check whether --with-blowfish or --without-blowfish was given.
+if test "${with_blowfish+set}" = set; then
+ withval="$with_blowfish"
+ case "$withval" in
+ no)
+ ;;
+ *)
+ with_blowfish=yes
+ ;;
+ esac
+else
+ with_blowfish=yes
+
+fi
+
+
+case "$with_blowfish" in
+yes)
+ cat >> confdefs.h <<\EOF
+#define WITH_BLOWFISH 1
+EOF
+
+ CONFOBJS="$CONFOBJS bf_skey.o bf_enc.o"
+ echo "$ac_t""yes" 1>&6
+ ;;
+no)
+ echo "$ac_t""no" 1>&6
+ ;;
+esac
+
+echo $ac_n "checking whether to use rsaref""... $ac_c" 1>&6
+echo "configure:3982: checking whether to use rsaref" >&5
+# Check whether --with-rsaref or --without-rsaref was given.
+if test "${with_rsaref+set}" = set; then
+ withval="$with_rsaref"
+ case "$withval" in
+ no)
+ echo "$ac_t""no" 1>&6
+ ;;
+ *)
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define RSAREF 1
+EOF
+
+ RSAREFDEP="rsaref2/source/librsaref.a"
+ LIBS="-lrsaref $LIBS"
+ LDFLAGS="-Lrsaref2/source $LDFLAGS"
+ ;;
+ esac
+else
+ echo "$ac_t""no" 1>&6
+
+fi
+
+
+echo $ac_n "checking whether to use ssl""... $ac_c" 1>&6
+echo "configure:4008: checking whether to use ssl" >&5
+# Check whether --with-ssl or --without-ssl was given.
+if test "${with_ssl+set}" = set; then
+ withval="$with_ssl"
+ case "$withval" in
+ no)
+ echo "$ac_t""no" 1>&6
+ ;;
+ *)
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define DO_SSL 1
+EOF
+
+ LIBS="-lcrypto $LIBS"
+ ;;
+ esac
+else
+ echo "$ac_t""no" 1>&6
+
+fi
+
+
+echo $ac_n "checking whether to use rsh""... $ac_c" 1>&6
+echo "configure:4032: checking whether to use rsh" >&5
+# Check whether --with-rsh or --without-rsh was given.
+if test "${with_rsh+set}" = set; then
+ withval="$with_rsh"
+ case "$withval" in
+ no)
+ echo "$ac_t""no" 1>&6
+ ;;
+ yes)
+ echo "$ac_t""yes" 1>&6
+ for ac_prog in remsh rsh
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4047: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_RSH_PATH'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$RSH_PATH" in
+ /*)
+ ac_cv_path_RSH_PATH="$RSH_PATH" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_RSH_PATH="$RSH_PATH" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_RSH_PATH="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+RSH_PATH="$ac_cv_path_RSH_PATH"
+if test -n "$RSH_PATH"; then
+ echo "$ac_t""$RSH_PATH" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$RSH_PATH" && break
+done
+
+ cat >> confdefs.h <<EOF
+#define RSH_PATH "$RSH_PATH"
+EOF
+
+ ;;
+ *)
+ echo "$ac_t""$withval" 1>&6
+ cat >> confdefs.h <<EOF
+#define RSH_PATH "$withval"
+EOF
+
+ ;;
+ esac
+else
+ echo "$ac_t""yes" 1>&6
+ for ac_prog in remsh rsh
+do
+# Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:4102: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_path_RSH_PATH'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ case "$RSH_PATH" in
+ /*)
+ ac_cv_path_RSH_PATH="$RSH_PATH" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_RSH_PATH="$RSH_PATH" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_path_RSH_PATH="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+RSH_PATH="$ac_cv_path_RSH_PATH"
+if test -n "$RSH_PATH"; then
+ echo "$ac_t""$RSH_PATH" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+test -n "$RSH_PATH" && break
+done
+
+ cat >> confdefs.h <<EOF
+#define RSH_PATH "$RSH_PATH"
+EOF
+
+
+fi
+
+
+# Code to permit setting default path for users (alden@math.ohio-state.edu)
+echo $ac_n "checking default path""... $ac_c" 1>&6
+echo "configure:4147: checking default path" >&5
+# Check whether --with-path or --without-path was given.
+if test "${with_path+set}" = set; then
+ withval="$with_path"
+ case "$withval" in
+ no)
+ echo "$ac_t""use system default" 1>&6
+ ;;
+ *)
+ echo "$ac_t""$withval" 1>&6
+ cat >> confdefs.h <<EOF
+#define DEFAULT_PATH "$withval"
+EOF
+
+ ;;
+ esac
+else
+ echo "$ac_t""use system default" 1>&6
+
+fi
+
+
+echo $ac_n "checking etcdir""... $ac_c" 1>&6
+echo "configure:4170: checking etcdir" >&5
+# Check whether --with-etcdir or --without-etcdir was given.
+if test "${with_etcdir+set}" = set; then
+ withval="$with_etcdir"
+ case "$withval" in
+ no)
+ { echo "configure: error: Need ETCDIR." 1>&2; exit 1; }
+ ;;
+ yes)
+ ETCDIR="/etc"
+ echo "$ac_t""/etc" 1>&6
+ ;;
+ *)
+ ETCDIR="$withval"
+ echo "$ac_t""$withval" 1>&6
+ ;;
+ esac
+else
+ ETCDIR="/etc"
+ echo "$ac_t""/etc" 1>&6
+
+fi
+
+
+echo $ac_n "checking whether to support SecurID""... $ac_c" 1>&6
+echo "configure:4195: checking whether to support SecurID" >&5
+# Check whether --with-securid or --without-securid was given.
+if test "${with_securid+set}" = set; then
+ withval="$with_securid"
+ case "$withval" in
+ no)
+ echo "$ac_t""no" 1>&6
+ ;;
+ yes)
+ echo "$ac_t""yes" 1>&6
+ if test '!' -f /usr/ace/sdiclient.a; then
+ { echo "configure: error: SecurID sdiclient.a not found in /usr/ace: you must supply the path." 1>&2; exit 1; }
+ fi
+ echo "$ac_t""yes" 1>&6
+ echo "$ac_t""Assuming SecurID headers and libraries are in /usr/ace." 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_SECURID 1
+EOF
+
+ CFLAGS="$CFLAGS -I/usr/ace"
+ LIBS="/usr/ace/sdiclient.a $LIBS"
+ ;;
+ *)
+ echo "$ac_t""yes" 1>&6
+ if test '!' -f $withval/sdiclient.a; then
+ { echo "configure: error: SecurID sdiclient.a not found in $withval: please supply the correct path." 1>&2; exit 1; }
+ fi
+ echo "$ac_t""Assuming SecurID headers and libraries are in $withval." 1>&6
+ cat >> confdefs.h <<\EOF
+#define HAVE_SECURID 1
+EOF
+
+ CFLAGS="$CFLAGS -I$withval"
+ LIBS="$withval/sdiclient.a $LIBS"
+ ;;
+ esac
+else
+ echo "$ac_t""no" 1>&6
+
+fi
+
+
+echo $ac_n "checking whether to include compression support""... $ac_c" 1>&6
+echo "configure:4238: checking whether to include compression support" >&5
+# Check whether --with-zlib or --without-zlib was given.
+if test "${with_zlib+set}" = set; then
+ withval="$with_zlib"
+ case "$withval" in
+ no)
+ ;;
+ *)
+ with_zlib=yes
+ ;;
+ esac
+else
+ with_zlib=yes
+
+fi
+
+
+case "$with_zlib" in
+yes)
+ echo "$ac_t""yes" 1>&6
+ for ac_hdr in zlib.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4262: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4267 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4272: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ if test "$ac_cv_header_zlib_h" != yes; then
+ echo "Can't find zlib.h, disable with --without-zlib"
+ exit 1
+ fi
+ echo $ac_n "checking for main in -lz""... $ac_c" 1>&6
+echo "configure:4303: checking for main in -lz" >&5
+ac_lib_var=`echo z'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lz $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4311 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:4318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo z | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lz $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "$ac_cv_lib_z_main" != yes; then
+ echo "Can't find library z (libz.a), disable with --without-zlib"
+ exit 1
+ fi
+ CONFOBJS="$CONFOBJS compress.o"
+ cat >> confdefs.h <<\EOF
+#define WITH_ZLIB 1
+EOF
+
+ ;;
+no)
+ echo "$ac_t""no" 1>&6
+ ;;
+esac
+
+echo $ac_n "checking whether to use Kerberos v4""... $ac_c" 1>&6
+echo "configure:4361: checking whether to use Kerberos v4" >&5
+# Check whether --with-krb4 or --without-krb4 was given.
+if test "${with_krb4+set}" = set; then
+ withval="$with_krb4"
+ case "$withval" in
+ yes)
+ ;;
+ no)
+ ;;
+ *)
+ ;;
+ esac
+else
+ with_krb4=default
+
+fi
+
+# krb4 continued
+case "$with_krb4" in
+no)
+ echo "$ac_t""no" 1>&6
+ ;;
+yes)
+ echo "$ac_t""yes" 1>&6
+ for ac_hdr in krb.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4389: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4394 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4399: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ if test "$ac_cv_header_krb_h" != yes; then
+ echo "Can't find include file krb.h! Aborting!"
+ exit 1
+ fi
+ echo $ac_n "checking for main in -lkrb""... $ac_c" 1>&6
+echo "configure:4430: checking for main in -lkrb" >&5
+ac_lib_var=`echo krb'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lkrb $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4438 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:4445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo krb | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lkrb $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "$ac_cv_lib_krb_main" != yes; then
+ echo "Can't find library krb (libkrb.a)! Aborting"
+ exit 1
+ fi
+ cat >> confdefs.h <<\EOF
+#define KRB4 1
+EOF
+
+ KRB4_AUTH="auth-krb4.o"
+ KRB4_ROOT=""
+ KRB4_INCS=""
+ KRB4_LIBS="-lkrb -ldes"
+ echo $ac_n "checking for dn_expand in -lresolv""... $ac_c" 1>&6
+echo "configure:4485: checking for dn_expand in -lresolv" >&5
+ac_lib_var=`echo resolv'_'dn_expand | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lresolv $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4493 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dn_expand();
+
+int main() {
+dn_expand()
+; return 0; }
+EOF
+if { (eval echo configure:4504: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ KRB4_LIBS="$KRB4_LIBS -lresolv"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+default)
+ for ac_hdr in krb.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:4530: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 4535 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:4540: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ echo $ac_n "checking for main in -lkrb""... $ac_c" 1>&6
+echo "configure:4567: checking for main in -lkrb" >&5
+ac_lib_var=`echo krb'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lkrb $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4575 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:4582: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo krb | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lkrb $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test "$ac_cv_header_krb_h" = yes -a "$ac_cv_lib_krb_main" = yes; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define KRB4 1
+EOF
+
+ KRB4_AUTH="auth-krb4.o"
+ KRB4_ROOT=""
+ KRB4_INCS=""
+ KRB4_LIBS="-lkrb -ldes"
+ echo $ac_n "checking for dn_expand in -lresolv""... $ac_c" 1>&6
+echo "configure:4620: checking for dn_expand in -lresolv" >&5
+ac_lib_var=`echo resolv'_'dn_expand | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lresolv $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4628 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dn_expand();
+
+int main() {
+dn_expand()
+; return 0; }
+EOF
+if { (eval echo configure:4639: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ KRB4_LIBS="$KRB4_LIBS -lresolv"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ else
+ echo "$ac_t""no" 1>&6
+ fi
+ ;;
+*)
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define KRB4 1
+EOF
+
+ KRB4_AUTH="auth-krb4.o"
+ KRB4_ROOT="$with_krb4"
+ KRB4_INCS="-I\$(KRB4_ROOT)/include"
+ KRB4_LIBS="-L\$(KRB4_ROOT)/lib -lkrb -ldes"
+ echo $ac_n "checking for dn_expand in -lresolv""... $ac_c" 1>&6
+echo "configure:4674: checking for dn_expand in -lresolv" >&5
+ac_lib_var=`echo resolv'_'dn_expand | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lresolv $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 4682 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char dn_expand();
+
+int main() {
+dn_expand()
+; return 0; }
+EOF
+if { (eval echo configure:4693: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ KRB4_LIBS="$KRB4_LIBS -lresolv"
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ ;;
+esac
+
+echo $ac_n "checking whether to use AFS""... $ac_c" 1>&6
+echo "configure:4717: checking whether to use AFS" >&5
+# Check whether --with-afs or --without-afs was given.
+if test "${with_afs+set}" = set; then
+ withval="$with_afs"
+ if test "$with_afs" = no; then
+ echo "$ac_t""no" 1>&6
+ else
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define AFS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define KERBEROS_TGT_PASSING 1
+EOF
+
+ RADIX="radix.o"
+ if test "$with_krb4" = no; then
+ echo "$ac_t""no" 1>&6
+ echo "configure: warning: "AFS requires Kerberos v4 support."" 1>&2
+ else
+ KRB4_LIBS="${KRB4_LIBS} -lkafs"
+ if test -n "$os_aix"; then
+ KRB4_LIBS="${KRB4_LIBS} -lld"
+ fi
+ fi
+fi
+
+fi
+
+
+echo $ac_n "checking whether to use libwrap""... $ac_c" 1>&6
+echo "configure:4749: checking whether to use libwrap" >&5
+# Check whether --with-libwrap or --without-libwrap was given.
+if test "${with_libwrap+set}" = set; then
+ withval="$with_libwrap"
+ case "$withval" in
+ no)
+ echo "$ac_t""no" 1>&6
+ ;;
+ yes)
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define LIBWRAP 1
+EOF
+
+ LIBS="-lwrap $LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 4765 "configure"
+#include "confdefs.h"
+ int allow_severity; int deny_severity;
+int main() {
+ hosts_access();
+; return 0; }
+EOF
+if { (eval echo configure:4772: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ { echo "configure: error: Could not find the libwrap.a library. You must first install tcp_wrappers." 1>&2; exit 1; }
+fi
+rm -f conftest*
+ ;;
+ *)
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define LIBWRAP 1
+EOF
+
+ LIBS="$withval $LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 4790 "configure"
+#include "confdefs.h"
+ int allow_severity; int deny_severity;
+int main() {
+ hosts_access();
+; return 0; }
+EOF
+if { (eval echo configure:4797: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ { echo "configure: error: Could not find the $withval library. You must first install tcp_wrappers." 1>&2; exit 1; }
+fi
+rm -f conftest*
+ ;;
+ esac
+else
+ echo "$ac_t""no" 1>&6
+
+fi
+
+
+echo $ac_n "checking whether to support SOCKS""... $ac_c" 1>&6
+echo "configure:4815: checking whether to support SOCKS" >&5
+# Check whether --with-socks or --without-socks was given.
+if test "${with_socks+set}" = set; then
+ withval="$with_socks"
+ case "$withval" in
+ no)
+ echo "$ac_t""no" 1>&6
+ ;;
+ *)
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define SOCKS 1
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define connect Rconnect
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define getsockname Rgetsockname
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define bind Rbind
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define accept Raccept
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define listen Rlisten
+EOF
+
+ cat >> confdefs.h <<\EOF
+#define select Rselect
+EOF
+
+ if test "x$withval" = "xyes"; then
+ withval="-lsocks"
+ fi
+ LIBS="$withval $LIBS"
+ cat > conftest.$ac_ext <<EOF
+#line 4858 "configure"
+#include "confdefs.h"
+
+int main() {
+ Rconnect();
+; return 0; }
+EOF
+if { (eval echo configure:4865: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ { echo "configure: error: Could not find the $withval library. You must first install socks." 1>&2; exit 1; }
+fi
+rm -f conftest*
+ ;;
+ esac
+else
+ echo "$ac_t""no" 1>&6
+
+fi
+
+
+PIDDIR="/var/run"
+echo $ac_n "checking where to put sshd.pid""... $ac_c" 1>&6
+echo "configure:4884: checking where to put sshd.pid" >&5
+if test '!' -d $PIDDIR; then
+ PIDDIR="$ETCDIR"
+fi
+echo "$ac_t""$PIDDIR" 1>&6
+
+if test "$program_transform_name" = s,x,x,; then
+ program_transform_name=
+else
+ # Double any \ or $. echo might interpret backslashes.
+ cat <<\EOF_SED > conftestsed
+s,\\,\\\\,g; s,\$,$$,g
+EOF_SED
+ program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
+ rm -f conftestsed
+fi
+test "$program_prefix" != NONE &&
+ program_transform_name="s,^,${program_prefix},; $program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
+
+# sed with no file args requires a program.
+test "$program_transform_name" = "" && program_transform_name="s,x,x,"
+
+
+
+
+
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile sshd.8 ssh.1 config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@host@%$host%g
+s%@host_alias@%$host_alias%g
+s%@host_cpu@%$host_cpu%g
+s%@host_vendor@%$host_vendor%g
+s%@host_os@%$host_os%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@GMPINCS@%$GMPINCS%g
+s%@GMPLIBS@%$GMPLIBS%g
+s%@LIBOBJS@%$LIBOBJS%g
+s%@LN_S@%$LN_S%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@RANLIB@%$RANLIB%g
+s%@MAKEDEP@%$MAKEDEP%g
+s%@WISH@%$WISH%g
+s%@XAUTH_PATH@%$XAUTH_PATH%g
+s%@RSH_PATH@%$RSH_PATH%g
+s%@KRB4_AUTH@%$KRB4_AUTH%g
+s%@KRB4_ROOT@%$KRB4_ROOT%g
+s%@KRB4_INCS@%$KRB4_INCS%g
+s%@KRB4_LIBS@%$KRB4_LIBS%g
+s%@RADIX@%$RADIX%g
+s%@ETCDIR@%$ETCDIR%g
+s%@PIDDIR@%$PIDDIR%g
+s%@RSAREFDEP@%$RSAREFDEP%g
+s%@CONFOBJS@%$CONFOBJS%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile sshd.8 ssh.1"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='\([ ][ ]*\)[^ ]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='\([ ]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+if test "${CONFIG_HEADERS+set}" != set; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+ CONFIG_HEADERS="config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
+for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ echo creating $ac_file
+
+ rm -f conftest.frag conftest.in conftest.out
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ cat $ac_file_inputs > conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h. And first:
+# Protect against being on the right side of a sed subst in config.status.
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# Break up conftest.vals because some shells have a limit on
+# the size of here documents, and old seds have small limits too.
+
+rm -f conftest.tail
+while :
+do
+ ac_lines=`grep -c . conftest.vals`
+ # grep -c gives empty output for an empty file on some AIX systems.
+ if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+ # Write a limited-size here document to conftest.frag.
+ echo ' cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+ echo 'CEOF
+ sed -f conftest.frag conftest.in > conftest.out
+ rm -f conftest.in
+ mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+ rm -f conftest.vals
+ mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+ rm -f conftest.frag conftest.h
+ echo "/* $ac_file. Generated automatically by configure. */" > conftest.h
+ cat conftest.in >> conftest.h
+ rm -f conftest.in
+ if cmp -s $ac_file conftest.h 2>/dev/null; then
+ echo "$ac_file is unchanged"
+ rm -f conftest.h
+ else
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ fi
+ rm -f $ac_file
+ mv conftest.h $ac_file
+ fi
+fi; done
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/usr.bin/ssh/configure.in b/usr.bin/ssh/configure.in
new file mode 100644
index 00000000000..84b06b0990e
--- /dev/null
+++ b/usr.bin/ssh/configure.in
@@ -0,0 +1,815 @@
+#
+# configure.in
+#
+# Author: Tatu Ylonen <ylo@cs.hut.fi>
+#
+# Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+# All rights reserved
+#
+# Created: Wed Mar 22 18:02:48 1995 ylo
+#
+# $Id: configure.in,v 1.1 1999/09/26 20:53:35 deraadt Exp $
+#
+
+AC_INIT(sshd.c)
+AC_CONFIG_HEADER(config.h)
+AC_PREREQ(2.4)
+
+AC_CANONICAL_HOST
+
+AC_PROG_CC
+AC_PROG_CPP
+
+case "$host" in
+ *-*-sunos4.1.1*)
+ os_sunos=yes
+ # Tim Adam <tma@osa.com.au> says speed_t is defined in stdtypes.h
+ AC_DEFINE(SPEED_T_IN_STDTYPES_H)
+ ;;
+ *-*-sunos*)
+ os_sunos=yes
+ ;;
+ *-sgi-irix5*)
+ # Irix stuff from snabb@niksula.hut.fi and tsurmacz@asic.ict.pwr.wroc.pl.
+ no_libsocket=yes
+ no_libsun=yes
+ ;;
+ *-sgi-irix6*)
+ # from d-champion@uchicago.edu
+ no_libsocket=yes
+ no_libsun=yes
+ if test "`uname -s`" = "IRIX64"; then
+ CFLAGS="-32 $CFLAGS"
+ LDFLAGS="-32 $LDFLAGS"
+ fi
+ ;;
+ *-ibm-aix3.2|*-ibm-aix3.2.0|*-ibm-aix3.2.1|*-ibm-aix3.2.2|*-ibm-aix3.2.3|*-ibm-aix3.2.4)
+ os_aix=yes
+ AC_CHECK_LIB(s, getuserattr)
+ ;;
+ *-ibm-aix*)
+ os_aix=yes
+ AC_CHECK_LIB(s, getuserattr)
+ ;;
+ mips-dec-mach3*)
+ # Mach3 stuff from kivinen@hut.fi
+ no_vhangup=yes
+ ;;
+ *-dec-ultrix*)
+ # Ultrix stuff from dmckilli@qc.bell.ca, jbotz@orixa.mtholyoke.edu.
+ AC_DEFINE(O_NONBLOCK_BROKEN)
+ no_vhangup=yes
+ AC_TRY_COMPILE([#include <syslog.h>],
+ [int foo = LOG_DAEMON; ],
+ ,
+ AC_DEFINE(NEED_SYS_SYSLOG_H))
+ ;;
+ *-*-hpux*)
+ # HPUX flags from jgotts@engin.umich.edu
+ if test -z "$GCC"; then
+ CFLAGS="$CFLAGS -Aa -D_HPUX_SOURCE"
+ fi
+ AC_DEFINE(HPSUX_NONSTANDARD_X11_KLUDGE)
+ ;;
+ alpha-dec-osf*)
+ AC_DEFINE(TTY_GROUP, "terminal")
+ AC_CHECK_LIB(security, set_auth_parameters)
+ AC_MSG_CHECKING(for OSF/1 C2 security package)
+ osfc2sec=`/usr/sbin/setld -i | grep '^OSFC2SEC'`
+ if test -n "$osfc2sec"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_OSF1_C2_SECURITY)
+ AC_CHECK_LIB(security, set_auth_parameters,
+ LIBS="$LIBS -lsecurity",
+ AC_MSG_ERROR("Could not find libsecurity even though C2 security installed."))
+ CONFOBJS="$CONFOBJS osfc2.o"
+ else
+ AC_MSG_RESULT(no)
+ fi
+ ;;
+ *-*-nextstep*)
+ # Nextstep support from a person who wants to remain anonymous
+ no_termios=yes
+ AC_DEFINE(SPEED_T_IN_STDTYPES_H)
+ ;;
+ *-*-linux*)
+ # Linux shadow password support (Andrew.Macpherson.1248566@bnr.co.uk)
+ if test -f /etc/shadow && test -f /etc/login.defs; then
+ AC_MSG_RESULT(Using linux John Haugh shadow passwords and pw_encrypt for password encryption)
+ AC_DEFINE(crypt,pw_encrypt)
+ LIBS="$LIBS -lshadow"
+ fi
+ ;;
+ i*86-*-bsdi*)
+ no_pipe=yes
+ ;;
+ i*86-unknown-bsd*)
+ # Assume 386BSD. pgut01@cs.auckland.ac.nz reported this makes it compile.
+ AC_DEFINE(__FreeBSD__)
+ ;;
+ m68k-sony-newsos*)
+ # From snabb@niksula.hut.fi
+ no_vhangup=yes
+ ;;
+ m88k-dg-dgux*)
+ AC_DEFINE(BROKEN_INET_ADDR)
+ ;;
+ *-cray-unicos*)
+ CFLAGS="$CFLAGS -DCRAY_STACKSEG_END=_getb67"
+ ;;
+ *-*-sysv4*)
+ AC_CHECK_LIB(gen, openlog)
+ ;;
+ *-*-machten*)
+ AC_DEFINE(USE_STRLEN_FOR_AF_UNIX)
+ ;;
+ i*86-unknown-sco*)
+ # From moi@dio.com
+ AC_DEFINE(HAVE_SCO_ETC_SHADOW)
+ AC_DEFINE(SCO)
+ no_ranlib=yes
+ LIBS="-L/usr/lib/libp -lprot -lx $LIBS"
+ ;;
+ *-convex-bsd*)
+ # From mark.martinec@nsc.ijs.si
+ # On Convex, getpwnam sets pw_passwd if running as root
+ no_shadows_password_checking=yes
+ ;;
+ *-*-freebsd*)
+ # From Ollivier Robert: FreeBSD and NetBSD use master.passwd, but set
+ # pw_passwd automatically when running as root.
+ no_shadow_password_checking=yes
+ ;;
+ *-*-netbsd*)
+ # From Ollivier Robert: FreeBSD and NetBSD use master.passwd, but set
+ # pw_passwd automatically when running as root.
+ no_shadow_password_checking=yes
+ ;;
+ *-*-openbsd*)
+ no_shadow_password_checking=yes
+ ;;
+ *)
+ ;;
+esac
+
+# Socket pairs appear to be broken on several systems. I don't know exactly
+# where, so I'll use pipes everywhere for now.
+AC_DEFINE(USE_PIPES)
+
+AC_MSG_CHECKING([that the compiler works])
+AC_TRY_RUN([ main(int ac, char **av) { return 0; } ],
+ AC_MSG_RESULT(yes),
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR(Could not compile and run even a trivial ANSI C program - check CC.),
+ AC_MSG_ERROR(Could not compile and run even a trivial ANSI C program - check CC.))
+
+if test -z "$no_pipe"; then
+if test -n "$GCC"; then
+ AC_MSG_CHECKING([if the compiler understands -pipe])
+ OLDCC="$CC"
+ CC="$CC -pipe"
+ AC_TRY_COMPILE(,,
+ AC_MSG_RESULT(yes),
+ CC="$OLDCC"
+ AC_MSG_RESULT(no))
+fi
+fi
+
+AC_ARG_ENABLE(warnings,
+[ --enable-warnings Enable -Wall if using gcc.],
+[ if test -n "$GCC"; then
+ AC_MSG_RESULT(Adding -Wall to CFLAGS.)
+ CFLAGS="$CFLAGS -Wall"
+ fi])
+
+if test -z "$no_vhangup"; then
+ AC_CHECK_FUNCS(vhangup)
+fi
+
+if test -z "$no_setsid"; then
+ AC_CHECK_FUNCS(setsid)
+fi
+
+AC_MSG_CHECKING(where to find mandatory GMP library)
+AC_ARG_WITH(gmp,
+[ --with-gmp[=PATH] Where to find GMP library.],
+[ case "$withval" in
+ no)
+ echo "GMP is mandatory! Aborting!"
+ exit 1
+ ;;
+ *)
+ ;;
+ esac ],
+[ with_gmp=yes ]
+)
+# gmp continued
+echo argument="$with_gmp"
+case "$with_gmp" in
+yes)
+ AC_CHECK_HEADERS(gmp.h)
+ if test "$ac_cv_header_gmp_h" != yes; then
+ echo "Can't find include file gmp.h! Aborting!"
+ echo "You must first build and install GMP, please read the file INSTALL"
+ exit 1
+ fi
+ AC_CHECK_LIB(gmp, main)
+ if test "$ac_cv_lib_gmp_main" != yes; then
+ echo "Can't find library gmp (libgmp.a)! Aborting"
+ echo "You must first build and install GMP, please read the file INSTALL"
+ exit 1
+ fi
+ GMPINCS=""
+ GMPLIBS="-lgmp"
+ ;;
+*)
+ GMPINCS="-I$with_gmp/include"
+ GMPLIBS="-L$with_gmp/lib -lgmp"
+ ;;
+esac
+AC_SUBST(GMPINCS) dnl
+AC_SUBST(GMPLIBS) dnl
+
+AC_CHECK_FUNCS(_getpty clock fchmod getdtablesize gethostname getrusage)
+AC_CHECK_FUNCS(gettimeofday initgroups innetgr memcpy openpty popen seteuid)
+AC_CHECK_FUNCS(setlogin setluid setrlimit strchr times ulimit umask vsnprintf)
+
+AC_TYPE_SIGNAL
+AC_TYPE_SIZE_T
+AC_TYPE_UID_T
+AC_TYPE_OFF_T
+AC_TYPE_MODE_T
+AC_STRUCT_ST_BLKSIZE
+
+AC_C_CONST
+AC_C_INLINE
+AC_C_BIGENDIAN
+AC_CHECK_SIZEOF(long)
+AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(short)
+
+if test -z "$no_termios"; then
+ AC_CHECK_HEADERS(termios.h)
+fi
+
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(unistd.h rusage.h sys/time.h lastlog.h utmp.h utmpx.h)
+AC_CHECK_HEADERS(sgtty.h sys/select.h sys/ioctl.h sys/filio.h)
+AC_CHECK_HEADERS(paths.h usersec.h utime.h netinet/in_systm.h ulimit.h)
+AC_HEADER_TIME
+AC_HEADER_DIRENT
+AC_HEADER_STAT
+AC_EGREP_HEADER(ut_pid, utmp.h, AC_DEFINE(HAVE_PID_IN_UTMP))
+AC_EGREP_HEADER(ut_name, utmp.h, AC_DEFINE(HAVE_NAME_IN_UTMP))
+AC_EGREP_HEADER(ut_id, utmp.h, AC_DEFINE(HAVE_ID_IN_UTMP))
+AC_EGREP_HEADER(ut_host, utmp.h, AC_DEFINE(HAVE_HOST_IN_UTMP))
+AC_EGREP_HEADER(ut_addr, utmp.h, AC_DEFINE(HAVE_ADDR_IN_UTMP))
+
+AC_EGREP_HEADER(ut_session, utmpx.h, AC_DEFINE(HAVE_UT_SESSION))
+AC_EGREP_HEADER(ut_syslen, utmpx.h, AC_DEFINE(HAVE_UT_SYSLEN))
+
+AC_CHECK_LIB(c, crypt, [true], AC_CHECK_LIB(crypt, crypt))
+AC_CHECK_LIB(nsl, main)
+if test -z "$no_libsocket"; then
+ AC_CHECK_LIB(socket, socket)
+fi
+if test -z "$no_libsun"; then
+ AC_CHECK_LIB(sun, getpwnam)
+fi
+AC_CHECK_LIB(util, login, AC_DEFINE(HAVE_LIBUTIL_LOGIN)
+ LIBS="$LIBS -lutil")
+
+AC_CHECK_LIB(des, main)
+
+AC_REPLACE_FUNCS(strerror memmove remove random putenv socketpair)
+
+AC_PROG_LN_S
+AC_PROG_INSTALL
+if test -z "$no_ranlib"; then
+ AC_PROG_RANLIB
+else
+ RANLIB=":"
+fi
+AC_PROGRAMS_CHECK(MAKEDEP, makedepend makedep, makedepend)
+AC_PATH_PROGS(WISH, wish8.0 wish wishx wish4.1 true)
+if test `basename $WISH` = "true"; then
+ AC_MSG_WARN(the wish program was not found - ssh-askpass will not work.)
+ WISH="/usr/local/bin/wish"
+fi
+AC_PATH_PROG(XAUTH_PATH, xauth, , $PATH:/usr/X11R6/bin)
+if test -n "$XAUTH_PATH"; then
+ AC_DEFINE_UNQUOTED(XAUTH_PATH, "$XAUTH_PATH")
+fi
+
+AC_MSG_CHECKING(for pseudo ttys)
+if test -c /dev/ptmx && test -c /dev/pts/0
+then
+ AC_DEFINE(HAVE_DEV_PTMX)
+ AC_MSG_RESULT(streams ptys)
+else
+if test -c /dev/pts && test -c /dev/ptc
+then
+ AC_DEFINE(HAVE_DEV_PTS_AND_PTC)
+ AC_MSG_RESULT(/dev/pts and /dev/ptc)
+else
+ AC_MSG_RESULT(bsd-style ptys)
+fi
+fi
+
+AC_MSG_CHECKING(for /etc/default/login)
+if test -f /etc/default/login; then
+ AC_DEFINE(HAVE_ETC_DEFAULT_LOGIN)
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+if test -z "$no_shadows_password_checking"; then
+ AC_MSG_CHECKING(for shadow passwords)
+ if test -f /etc/shadow; then
+ AC_DEFINE(HAVE_ETC_SHADOW)
+ AC_MSG_RESULT(/etc/shadow)
+ elif test -n "$os_aix"; then
+ AC_DEFINE(HAVE_ETC_SECURITY_PASSWD)
+ AC_MSG_RESULT(/etc/security/passwd)
+ elif test -n "$os_sunos"; then
+ AC_DEFINE(HAVE_ETC_SECURITY_PASSWD_ADJUNCT)
+ AC_MSG_RESULT(/etc/security/passwd.adjunct)
+ else
+ AC_MSG_RESULT(no)
+ fi
+fi
+
+AC_MSG_CHECKING(location of mail spool files)
+for dir in /var/spool/mail /var/mail /usr/spool/mail /usr/mail NEWMAIL
+do
+ if test "$dir" = "NEWMAIL"; then
+ AC_DEFINE(HAVE_TILDE_NEWMAIL)
+ AC_MSG_RESULT(\$HOME/newmail)
+ AC_MSG_WARN(mail spool directory was not found: assuming you use \$HOME/newmail)
+ elif test -d $dir; then
+ AC_DEFINE_UNQUOTED(MAIL_SPOOL_DIRECTORY, "$dir")
+ AC_MSG_RESULT($dir)
+ break
+ fi
+done
+
+AC_MSG_CHECKING(location of utmp)
+if test -f /var/run/utmp; then
+ AC_DEFINE(SSH_UTMP, "/var/run/utmp")
+ AC_MSG_RESULT(/var/run/utmp)
+elif test -f /var/log/utmp; then
+ AC_DEFINE(SSH_UTMP, "/var/log/utmp")
+ AC_MSG_RESULT(/var/log/utmp)
+elif test -f /var/adm/utmp; then
+ AC_DEFINE(SSH_UTMP, "/var/adm/utmp")
+ AC_MSG_RESULT(/var/adm/utmp)
+elif test -f /usr/adm/utmp; then
+ AC_DEFINE(SSH_UTMP, "/usr/adm/utmp")
+ AC_MSG_RESULT(/usr/adm/utmp)
+elif test -f /etc/utmp; then
+ AC_DEFINE(SSH_UTMP, "/etc/utmp")
+ AC_MSG_RESULT(/etc/utmp)
+else
+ AC_MSG_RESULT(not found)
+fi
+
+AC_MSG_CHECKING(location of wtmp)
+if test -f /var/log/wtmp; then
+ AC_DEFINE(SSH_WTMP, "/var/log/wtmp")
+ AC_MSG_RESULT(/var/log/wtmp)
+elif test -f /var/adm/wtmp; then
+ AC_DEFINE(SSH_WTMP, "/var/adm/wtmp")
+ AC_MSG_RESULT(/var/adm/wtmp)
+elif test -f /usr/adm/wtmp; then
+ AC_DEFINE(SSH_WTMP, "/usr/adm/wtmp")
+ AC_MSG_RESULT(/usr/adm/wtmp)
+elif test -f /etc/wtmp; then
+ AC_DEFINE(SSH_WTMP, "/etc/wtmp")
+ AC_MSG_RESULT(/etc/wtmp)
+else
+ AC_DEFINE(SSH_WTMP, "/var/adm/wtmp")
+ AC_MSG_RESULT(not found)
+fi
+
+AC_MSG_CHECKING(location of lastlog)
+if test -f /var/log/lastlog || test -d /var/log/lastlog; then
+ AC_DEFINE(SSH_LASTLOG, "/var/log/lastlog")
+ AC_DEFINE(HAVE_LASTLOG)
+ LASTLOG=/var/log/lastlog
+ AC_MSG_RESULT(/var/log/lastlog)
+elif test -f /var/adm/lastlog || test -d /var/adm/lastlog; then
+ AC_DEFINE(SSH_LASTLOG, "/var/adm/lastlog")
+ AC_DEFINE(HAVE_LASTLOG)
+ LASTLOG=/var/adm/lastlog
+ AC_MSG_RESULT(/var/adm/lastlog)
+elif test -f /usr/adm/lastlog || test -d /usr/adm/lastlog; then
+ AC_DEFINE(SSH_LASTLOG, "/usr/adm/lastlog")
+ AC_DEFINE(HAVE_LASTLOG)
+ LASTLOG=/usr/adm/lastlog
+ AC_MSG_RESULT(/usr/adm/lastlog)
+elif test -f /etc/lastlog || test -d /etc/lastlog; then
+ AC_DEFINE(SSH_LASTLOG, "/etc/lastlog")
+ AC_DEFINE(HAVE_LASTLOG)
+ LASTLOG=/etc/lastlog
+ AC_MSG_RESULT(/etc/lastlog)
+else
+ AC_MSG_RESULT(not found)
+ AC_DEFINE(SSH_LASTLOG, "/var/log/lastlog")
+ LASTLOG=/var/log/lastlog
+fi
+
+AC_MSG_CHECKING(whether $LASTLOG is a directory)
+if test -d $LASTLOG
+then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(LASTLOG_IS_DIR)
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_MSG_CHECKING(whether to include the IDEA encryption algorithm)
+AC_ARG_WITH(idea,
+[ --with-idea Use IDEA (not default).
+ --without-idea Don't use IDEA: avoids patent problems in commercial use],
+[ case "$withval" in
+ yes)
+ AC_MSG_RESULT(yes)
+ CONFOBJS="$CONFOBJS idea.o"
+ AC_DEFINE(WITH_IDEA)
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(whether to include the RC4 encryption algorithm)
+AC_ARG_WITH(rc4,
+[ --with-rc4 Include RC4 support.
+ --without-rc4 Don't include RC4 support (default)],
+[ case "$withval" in
+ yes)
+ AC_MSG_RESULT(yes)
+ CONFOBJS="$CONFOBJS rc4.o"
+ AC_DEFINE(WITH_RC4)
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(whether to include the Blowfish encryption algorithm)
+AC_ARG_WITH(blowfish,
+[ --with-blowfish Include Blowfish support (default).
+ --without-blowfish Don't include Blowfish support],
+[ case "$withval" in
+ no)
+ ;;
+ *)
+ with_blowfish=yes
+ ;;
+ esac ],
+ with_blowfish=yes
+)
+
+case "$with_blowfish" in
+yes)
+ AC_DEFINE(WITH_BLOWFISH)
+ CONFOBJS="$CONFOBJS bf_skey.o bf_enc.o"
+ AC_MSG_RESULT(yes)
+ ;;
+no)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+
+AC_MSG_CHECKING(whether to use rsaref)
+AC_ARG_WITH(rsaref,
+[ --with-rsaref Use RSAREF (try to avoid patent problems in U.S.)
+ --without-rsaref Use normal RSA routines (default). ],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(RSAREF)
+ RSAREFDEP="rsaref2/source/librsaref.a"
+ LIBS="-lrsaref $LIBS"
+ LDFLAGS="-Lrsaref2/source $LDFLAGS"
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(whether to use ssl)
+AC_ARG_WITH(ssl,
+[ --with-ssl Use SSL (try to avoid patent problems in U.S.)
+ --without-ssl Use normal RSA routines (default). ],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(DO_SSL)
+ LIBS="-lcrypto $LIBS"
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(whether to use rsh)
+AC_ARG_WITH(rsh,
+[ --with-rsh=PATH Specify where to find rsh.
+ --without-rsh Do not use rsh under any conditions. ],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ yes)
+ AC_MSG_RESULT(yes)
+ AC_PATH_PROGS(RSH_PATH, remsh rsh)
+ AC_DEFINE_UNQUOTED(RSH_PATH, "$RSH_PATH")
+ ;;
+ *)
+ AC_MSG_RESULT($withval)
+ AC_DEFINE_UNQUOTED(RSH_PATH, "$withval")
+ ;;
+ esac ],
+ [ AC_MSG_RESULT(yes)
+ AC_PATH_PROGS(RSH_PATH, remsh rsh)
+ AC_DEFINE_UNQUOTED(RSH_PATH, "$RSH_PATH") ]
+)
+
+# Code to permit setting default path for users (alden@math.ohio-state.edu)
+AC_MSG_CHECKING(default path)
+AC_ARG_WITH(path,
+[ --with-path=PATH Default path passed to user shell by sshd.],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(use system default)
+ ;;
+ *)
+ AC_MSG_RESULT($withval)
+ AC_DEFINE_UNQUOTED(DEFAULT_PATH, "$withval")
+ ;;
+ esac ],
+ AC_MSG_RESULT(use system default)
+)
+
+AC_MSG_CHECKING(etcdir)
+AC_ARG_WITH(etcdir,
+[ --with-etcdir=PATH Directory containing ssh system files (default /etc).],
+[ case "$withval" in
+ no)
+ AC_MSG_ERROR(Need ETCDIR.)
+ ;;
+ yes)
+ ETCDIR="/etc"
+ AC_MSG_RESULT(/etc)
+ ;;
+ *)
+ ETCDIR="$withval"
+ AC_MSG_RESULT($withval)
+ ;;
+ esac ],
+ ETCDIR="/etc"
+ AC_MSG_RESULT(/etc)
+)
+
+AC_MSG_CHECKING(whether to support SecurID)
+AC_ARG_WITH(securid,
+[ --with-securid[=PATH] Enable support for Security Dynamics SecurID card.],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ yes)
+ AC_MSG_RESULT(yes)
+ if test '!' -f /usr/ace/sdiclient.a; then
+ AC_ERROR(SecurID sdiclient.a not found in /usr/ace: you must supply the path.)
+ fi
+ AC_MSG_RESULT(yes)
+ AC_MSG_RESULT(Assuming SecurID headers and libraries are in /usr/ace.)
+ AC_DEFINE(HAVE_SECURID)
+ CFLAGS="$CFLAGS -I/usr/ace"
+ LIBS="/usr/ace/sdiclient.a $LIBS"
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ if test '!' -f $withval/sdiclient.a; then
+ AC_ERROR(SecurID sdiclient.a not found in $withval: please supply the correct path.)
+ fi
+ AC_MSG_RESULT(Assuming SecurID headers and libraries are in $withval.)
+ AC_DEFINE(HAVE_SECURID)
+ CFLAGS="$CFLAGS -I$withval"
+ LIBS="$withval/sdiclient.a $LIBS"
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(whether to include compression support)
+AC_ARG_WITH(zlib,
+[ --with-zlib Use zlib (default).
+ --without-zlib Don't use zlib.],
+[ case "$withval" in
+ no)
+ ;;
+ *)
+ with_zlib=yes
+ ;;
+ esac ],
+ with_zlib=yes
+)
+
+case "$with_zlib" in
+yes)
+ AC_MSG_RESULT(yes)
+ AC_CHECK_HEADERS(zlib.h)
+ if test "$ac_cv_header_zlib_h" != yes; then
+ echo "Can't find zlib.h, disable with --without-zlib"
+ exit 1
+ fi
+ AC_CHECK_LIB(z, main)
+ if test "$ac_cv_lib_z_main" != yes; then
+ echo "Can't find library z (libz.a), disable with --without-zlib"
+ exit 1
+ fi
+ CONFOBJS="$CONFOBJS compress.o"
+ AC_DEFINE(WITH_ZLIB)
+ ;;
+no)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+
+AC_MSG_CHECKING(whether to use Kerberos v4)
+AC_ARG_WITH(krb4,
+[ --with-krb4[=PATH] Compile in Kerberos v4 support.],
+[ case "$withval" in
+ yes)
+ ;;
+ no)
+ ;;
+ *)
+ ;;
+ esac ],
+[ with_krb4=default ]
+)
+# krb4 continued
+case "$with_krb4" in
+no)
+ AC_MSG_RESULT(no)
+ ;;
+yes)
+ AC_MSG_RESULT(yes)
+ AC_CHECK_HEADERS(krb.h)
+ if test "$ac_cv_header_krb_h" != yes; then
+ echo "Can't find include file krb.h! Aborting!"
+ exit 1
+ fi
+ AC_CHECK_LIB(krb, main)
+ if test "$ac_cv_lib_krb_main" != yes; then
+ echo "Can't find library krb (libkrb.a)! Aborting"
+ exit 1
+ fi
+ AC_DEFINE(KRB4)
+ KRB4_AUTH="auth-krb4.o"
+ KRB4_ROOT=""
+ KRB4_INCS=""
+ KRB4_LIBS="-lkrb -ldes"
+ AC_CHECK_LIB(resolv, dn_expand, KRB4_LIBS="$KRB4_LIBS -lresolv")
+ ;;
+default)
+ AC_CHECK_HEADERS(krb.h)
+ AC_CHECK_LIB(krb, main)
+ if test "$ac_cv_header_krb_h" = yes -a "$ac_cv_lib_krb_main" = yes; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(KRB4)
+ KRB4_AUTH="auth-krb4.o"
+ KRB4_ROOT=""
+ KRB4_INCS=""
+ KRB4_LIBS="-lkrb -ldes"
+ AC_CHECK_LIB(resolv, dn_expand, KRB4_LIBS="$KRB4_LIBS -lresolv")
+ else
+ AC_MSG_RESULT(no)
+ fi
+ ;;
+*)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(KRB4)
+ KRB4_AUTH="auth-krb4.o"
+ KRB4_ROOT="$with_krb4"
+ KRB4_INCS="-I\$(KRB4_ROOT)/include"
+ KRB4_LIBS="-L\$(KRB4_ROOT)/lib -lkrb -ldes"
+ AC_CHECK_LIB(resolv, dn_expand, KRB4_LIBS="$KRB4_LIBS -lresolv")
+ ;;
+esac
+AC_SUBST(KRB4_AUTH) dnl
+AC_SUBST(KRB4_ROOT) dnl
+AC_SUBST(KRB4_INCS) dnl
+AC_SUBST(KRB4_LIBS) dnl
+
+AC_MSG_CHECKING(whether to use AFS)
+AC_ARG_WITH(afs,
+[ --with-afs Compile in AFS support (requires KTH krb4).],
+if test "$with_afs" = no; then
+ AC_MSG_RESULT(no)
+ else
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(AFS)
+ AC_DEFINE(KERBEROS_TGT_PASSING)
+ RADIX="radix.o"
+ if test "$with_krb4" = no; then
+ AC_MSG_RESULT(no)
+ AC_MSG_WARN("AFS requires Kerberos v4 support.")
+ else
+ KRB4_LIBS="${KRB4_LIBS} -lkafs"
+ if test -n "$os_aix"; then
+ KRB4_LIBS="${KRB4_LIBS} -lld"
+ fi
+ fi
+fi
+)
+AC_SUBST(RADIX)dnl
+
+AC_MSG_CHECKING(whether to use libwrap)
+AC_ARG_WITH(libwrap,
+[ --with-libwrap[=PATH] Compile in libwrap (tcp_wrappers) support.],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ yes)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(LIBWRAP)
+ LIBS="-lwrap $LIBS"
+ AC_TRY_LINK([ int allow_severity; int deny_severity; ],
+ [ hosts_access(); ],
+ [],
+ [ AC_MSG_ERROR(Could not find the libwrap.a library. You must first install tcp_wrappers.) ])
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(LIBWRAP)
+ LIBS="$withval $LIBS"
+ AC_TRY_LINK([ int allow_severity; int deny_severity; ],
+ [ hosts_access(); ],
+ [],
+ [ AC_MSG_ERROR(Could not find the $withval library. You must first install tcp_wrappers.) ])
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+)
+
+AC_MSG_CHECKING(whether to support SOCKS)
+AC_ARG_WITH(socks,
+[ --with-socks[=PATH] Compile with SOCKS firewall traversal support.],
+[ case "$withval" in
+ no)
+ AC_MSG_RESULT(no)
+ ;;
+ *)
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(SOCKS)
+ AC_DEFINE(connect, Rconnect)
+ AC_DEFINE(getsockname, Rgetsockname)
+ AC_DEFINE(bind, Rbind)
+ AC_DEFINE(accept, Raccept)
+ AC_DEFINE(listen, Rlisten)
+ AC_DEFINE(select, Rselect)
+ if test "x$withval" = "xyes"; then
+ withval="-lsocks"
+ fi
+ LIBS="$withval $LIBS"
+ AC_TRY_LINK([],
+ [ Rconnect(); ],
+ [],
+ [ AC_MSG_ERROR(Could not find the $withval library. You must first install socks.) ])
+ ;;
+ esac ],
+ AC_MSG_RESULT(no)
+)
+
+PIDDIR="/var/run"
+AC_MSG_CHECKING(where to put sshd.pid)
+if test '!' -d $PIDDIR; then
+ PIDDIR="$ETCDIR"
+fi
+AC_MSG_RESULT($PIDDIR)
+
+AC_ARG_PROGRAM
+
+AC_SUBST(ETCDIR)
+AC_SUBST(PIDDIR)
+AC_SUBST(RSAREFDEP)
+AC_SUBST(CONFOBJS)
+
+AC_OUTPUT(Makefile sshd.8 ssh.1)
diff --git a/usr.bin/ssh/crc32.c b/usr.bin/ssh/crc32.c
new file mode 100644
index 00000000000..7473e278279
--- /dev/null
+++ b/usr.bin/ssh/crc32.c
@@ -0,0 +1,120 @@
+/* The implementation here was originally done by Gary S. Brown. I have
+ borrowed the tables directly, and made some minor changes to the
+ crc32-function (including changing the interface). //ylo */
+
+#include "includes.h"
+RCSID("$Id: crc32.c,v 1.1 1999/09/26 20:53:35 deraadt Exp $");
+
+#include "crc32.h"
+
+ /* ============================================================= */
+ /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
+ /* code or tables extracted from it, as desired without restriction. */
+ /* */
+ /* First, the polynomial itself and its table of feedback terms. The */
+ /* polynomial is */
+ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
+ /* */
+ /* Note that we take it "backwards" and put the highest-order term in */
+ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
+ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
+ /* the MSB being 1. */
+ /* */
+ /* Note that the usual hardware shift register implementation, which */
+ /* is what we're using (we're merely optimizing it by doing eight-bit */
+ /* chunks at a time) shifts bits into the lowest-order term. In our */
+ /* implementation, that means shifting towards the right. Why do we */
+ /* do it this way? Because the calculated CRC must be transmitted in */
+ /* order from highest-order term to lowest-order term. UARTs transmit */
+ /* characters in order from LSB to MSB. By storing the CRC this way, */
+ /* we hand it to the UART in the order low-byte to high-byte; the UART */
+ /* sends each low-bit to hight-bit; and the result is transmission bit */
+ /* by bit from highest- to lowest-order term without requiring any bit */
+ /* shuffling on our part. Reception works similarly. */
+ /* */
+ /* The feedback terms table consists of 256, 32-bit entries. Notes: */
+ /* */
+ /* The table can be generated at runtime if desired; code to do so */
+ /* is shown later. It might not be obvious, but the feedback */
+ /* terms simply represent the results of eight shift/xor opera- */
+ /* tions for all combinations of data and CRC register values. */
+ /* */
+ /* The values must be right-shifted by eight bits by the "updcrc" */
+ /* logic; the shift must be unsigned (bring in zeroes). On some */
+ /* hardware you could probably optimize the shift in assembler by */
+ /* using byte-swap instructions. */
+ /* polynomial $edb88320 */
+ /* */
+ /* -------------------------------------------------------------------- */
+
+static unsigned long crc32_tab[] = {
+ 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+ 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+ 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+ 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+ 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+ 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+ 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+ 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+ 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+ 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+ 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+ 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+ 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+ 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+ 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+ 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+ 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+ 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+ 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+ 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+ 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+ 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+ 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+ 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+ 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+ 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+ 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+ 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+ 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+ 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+ 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+ 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+ 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+ 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+ 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+ 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+ 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+ 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+ 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+ 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+ 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+ 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+ 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+ 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+ 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+ 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+ 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+ 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+ 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+ 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+ 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+ 0x2d02ef8dL
+ };
+
+/* Return a 32-bit CRC of the contents of the buffer. */
+
+unsigned long crc32(const unsigned char *s, unsigned int len)
+{
+ unsigned int i;
+ unsigned long crc32val;
+
+ crc32val = 0;
+ for (i = 0; i < len; i ++)
+ {
+ crc32val =
+ crc32_tab[(crc32val ^ s[i]) & 0xff] ^
+ (crc32val >> 8);
+ }
+ return crc32val;
+}
diff --git a/usr.bin/ssh/crc32.h b/usr.bin/ssh/crc32.h
new file mode 100644
index 00000000000..dbc0a2fb1e7
--- /dev/null
+++ b/usr.bin/ssh/crc32.h
@@ -0,0 +1,25 @@
+/*
+
+crc32.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1992 Tatu Ylonen, Espoo, Finland
+ All rights reserved
+
+Created: Tue Feb 11 14:37:27 1992 ylo
+
+Functions for computing 32-bit CRC.
+
+*/
+
+/* RCSID("$Id: crc32.h,v 1.1 1999/09/26 20:53:35 deraadt Exp $"); */
+
+#ifndef CRC32_H
+#define CRC32_H
+
+/* This computes a 32 bit CRC of the data in the buffer, and returns the
+ CRC. The polynomial used is 0xedb88320. */
+unsigned long crc32(const unsigned char *buf, unsigned int len);
+
+#endif /* CRC32_H */
diff --git a/usr.bin/ssh/fdlim.h b/usr.bin/ssh/fdlim.h
new file mode 100644
index 00000000000..eec041b2c5b
--- /dev/null
+++ b/usr.bin/ssh/fdlim.h
@@ -0,0 +1,69 @@
+/*
+
+fdlim.h
+
+Author: David Mazieres <dm@lcs.mit.edu>
+ Contributed to be part of ssh.
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Tue Aug 22 17:21:32 1995 ylo
+
+*/
+
+/* RCSID("$Id: fdlim.h,v 1.1 1999/09/26 20:53:36 deraadt Exp $"); */
+
+#ifndef FDLIM_H
+#define FDLIM_H
+
+static int
+fdlim_get (int hard)
+{
+#ifdef RLIMIT_NOFILE
+ struct rlimit rlfd;
+ if (getrlimit (RLIMIT_NOFILE, &rlfd) < 0)
+ return (-1);
+#ifdef RLIM_INFINITY /* not defined on HPSUX */
+ if ((hard ? rlfd.rlim_max : rlfd.rlim_cur) == RLIM_INFINITY)
+ return 10000;
+ else
+ return hard ? rlfd.rlim_max : rlfd.rlim_cur;
+#else /* RLIM_INFINITY */
+ return hard ? rlfd.rlim_max : rlfd.rlim_cur;
+#endif /* RLIM_INFINITY */
+#else /* !RLIMIT_NOFILE */
+#ifdef HAVE_GETDTABLESIZE
+ return (getdtablesize ());
+#else /* !HAVE_GETDTABLESIZE */
+#ifdef _SC_OPEN_MAX
+ return (sysconf (_SC_OPEN_MAX));
+#else /* !_SC_OPEN_MAX */
+#ifdef NOFILE
+ return (NOFILE);
+#else /* !NOFILE */
+ return (25);
+#endif /* !NOFILE */
+#endif /* !_SC_OPEN_MAX */
+#endif /* !HAVE_GETDTABLESIZE */
+#endif /* !RLIMIT_NOFILE */
+}
+
+static int
+fdlim_set (int lim) {
+#ifdef RLIMIT_NOFILE
+ struct rlimit rlfd;
+ if (lim <= 0)
+ return (-1);
+ if (getrlimit (RLIMIT_NOFILE, &rlfd) < 0)
+ return (-1);
+ rlfd.rlim_cur = lim;
+ if (setrlimit (RLIMIT_NOFILE, &rlfd) < 0)
+ return (-1);
+ return (0);
+#else /* !RLIMIT_NOFILE */
+ return (-1);
+#endif /* !RLIMIT_NOFILE */
+}
+
+#endif /* FDLIM_H */
diff --git a/usr.bin/ssh/gen_minfd.c b/usr.bin/ssh/gen_minfd.c
new file mode 100644
index 00000000000..6d1bbcd2317
--- /dev/null
+++ b/usr.bin/ssh/gen_minfd.c
@@ -0,0 +1,123 @@
+/*
+
+gen_minfd.c
+
+Author: David Mazieres <dm@lcs.mit.edu>
+ Contributed to be part of ssh.
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Tue Aug 22 17:22:57 1995 ylo
+Last modified: Tue Aug 22 17:44:32 1995 ylo
+
+*/
+
+#include "includes.h"
+#include <sys/resource.h>
+#include "fdlim.h"
+
+static char *self;
+
+static void
+child_test (char *fdstr)
+{
+ int fd = atoi (fdstr);
+ if (fcntl (fd, F_GETFL, NULL) < 0) {
+ exit (1);
+ }
+ exit (0);
+}
+
+static int
+run_child (char *shell, int fd)
+{
+ char cmd[128];
+ int pid;
+ int status;
+
+ if (dup2 (0, fd) < 0) {
+ perror ("dup2");
+ return (-1);
+ }
+
+ sprintf (cmd, "%s -fd %d", self, fd);
+
+ fflush (stdout);
+ pid = fork ();
+ if (! pid) {
+ close (1); /* prevent any garbage from entering the output */
+ dup (2);
+ execlp (shell, shell, "-c", cmd, NULL);
+ exit (1);
+ }
+ close (fd);
+ if (wait (&status) != pid) {
+ fprintf (stderr, "wrong/no child??\n");
+ exit (1);
+ }
+ return (status ? -1 : 0);
+}
+
+static int
+do_shell (char *shell)
+{
+ int fd, min, max;
+
+ min = 3;
+ max = fdlim_get (0) - 1;
+ if (max < 0) {
+ printf ("fdlim_get: bad value\n");
+ exit (1);
+ }
+
+ if (run_child (shell, max)
+ && run_child (shell, --max)) /* bizarre ultrix weirdness */
+ return (-1);
+
+ while (min + 1 < max) {
+ fd = (min + max) / 2;
+ if (run_child (shell, fd))
+ min = fd;
+ else
+ max = fd;
+ }
+ return (max);
+}
+
+int
+main (int argc, char **argv)
+{
+ int fd;
+ int i;
+ char *p;
+
+ if (argc == 3 && !strcmp (argv[1], "-fd"))
+ child_test (argv[2]);
+ self = argv[0];
+
+ fd = fdlim_get (1);
+ if (fd < 0) {
+ fprintf (stderr, "fdlim_get: bad value\n");
+ exit (1);
+ }
+ fdlim_set (fd);
+ printf ("/* maximum file descriptors = %d */\n\n", fd);
+ printf ("struct Min_Auth_Fd {\n"
+ " int fd;\n"
+ " char shell[32];\n"
+ "};\n\n"
+ "static struct Min_Auth_Fd mafd[] = {\n");
+ for (i = 1; i < argc; i++) {
+ fd = do_shell (argv[i]);
+ if ((p = strrchr (argv[i], '/')))
+ p++;
+ else
+ p = argv[i];
+ if (fd > 0)
+ printf (" { %d, \"%s\" },\n", fd, p);
+ }
+ printf (" { 0, \"\" },\n};\n\n"
+ "#define MAFD_MAX (sizeof (mafd) / sizeof (mafd[0]) - 1)\n");
+ return (0);
+}
diff --git a/usr.bin/ssh/getput.h b/usr.bin/ssh/getput.h
new file mode 100644
index 00000000000..1c255bdbaa4
--- /dev/null
+++ b/usr.bin/ssh/getput.h
@@ -0,0 +1,64 @@
+/*
+
+getput.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Jun 28 22:36:30 1995 ylo
+
+Macros for storing and retrieving data in msb first and lsb first order.
+
+*/
+
+/* RCSID("$Id: getput.h,v 1.1 1999/09/26 20:53:36 deraadt Exp $"); */
+
+#ifndef GETPUT_H
+#define GETPUT_H
+
+/*------------ macros for storing/extracting msb first words -------------*/
+
+#define GET_32BIT(cp) (((unsigned long)(unsigned char)(cp)[0] << 24) | \
+ ((unsigned long)(unsigned char)(cp)[1] << 16) | \
+ ((unsigned long)(unsigned char)(cp)[2] << 8) | \
+ ((unsigned long)(unsigned char)(cp)[3]))
+
+#define GET_16BIT(cp) (((unsigned long)(unsigned char)(cp)[0] << 8) | \
+ ((unsigned long)(unsigned char)(cp)[1]))
+
+#define PUT_32BIT(cp, value) do { \
+ (cp)[0] = (value) >> 24; \
+ (cp)[1] = (value) >> 16; \
+ (cp)[2] = (value) >> 8; \
+ (cp)[3] = (value); } while (0)
+
+#define PUT_16BIT(cp, value) do { \
+ (cp)[0] = (value) >> 8; \
+ (cp)[1] = (value); } while (0)
+
+/*------------ macros for storing/extracting lsb first words -------------*/
+
+#define GET_32BIT_LSB_FIRST(cp) \
+ (((unsigned long)(unsigned char)(cp)[0]) | \
+ ((unsigned long)(unsigned char)(cp)[1] << 8) | \
+ ((unsigned long)(unsigned char)(cp)[2] << 16) | \
+ ((unsigned long)(unsigned char)(cp)[3] << 24))
+
+#define GET_16BIT_LSB_FIRST(cp) \
+ (((unsigned long)(unsigned char)(cp)[0]) | \
+ ((unsigned long)(unsigned char)(cp)[1] << 8))
+
+#define PUT_32BIT_LSB_FIRST(cp, value) do { \
+ (cp)[0] = (value); \
+ (cp)[1] = (value) >> 8; \
+ (cp)[2] = (value) >> 16; \
+ (cp)[3] = (value) >> 24; } while (0)
+
+#define PUT_16BIT_LSB_FIRST(cp, value) do { \
+ (cp)[0] = (value); \
+ (cp)[1] = (value) >> 8; } while (0)
+
+#endif /* GETPUT_H */
+
diff --git a/usr.bin/ssh/host_config.sample b/usr.bin/ssh/host_config.sample
new file mode 100644
index 00000000000..3d9d600de6f
--- /dev/null
+++ b/usr.bin/ssh/host_config.sample
@@ -0,0 +1,29 @@
+# This is ssh client systemwide configuration file. This file provides
+# defaults for users, and the values can be changed in per-user configuration
+# files or on the command line.
+
+# Configuration data is parsed as follows:
+# 1. command line options
+# 2. user-specific file
+# 3. system-wide file
+# Any configuration value is only changed the first time it is set.
+# Thus, host-specific definitions should be at the beginning of the
+# configuration file, and defaults at the end.
+
+# Site-wide defaults for various options
+
+# Host *
+# ForwardAgent yes
+# ForwardX11 yes
+# RhostsAuthentication yes
+# RhostsRSAAuthentication yes
+# RSAAuthentication yes
+# PasswordAuthentication yes
+# FallBackToRsh yes
+# UseRsh no
+# BatchMode no
+# StrictHostKeyChecking no
+# IdentityFile ~/.ssh/identity
+# Port 22
+# Cipher idea
+# EscapeChar ~
diff --git a/usr.bin/ssh/hostfile.c b/usr.bin/ssh/hostfile.c
new file mode 100644
index 00000000000..27c56af2eb7
--- /dev/null
+++ b/usr.bin/ssh/hostfile.c
@@ -0,0 +1,275 @@
+/*
+
+hostfile.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Thu Jun 29 07:10:56 1995 ylo
+
+Functions for manipulating the known hosts files.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: hostfile.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include "packet.h"
+#include "ssh.h"
+
+/* Reads a multiple-precision integer in hex from the buffer, and advances the
+ pointer. The integer must already be initialized. This function is
+ permitted to modify the buffer. This leaves *cpp to point just beyond
+ the last processed (and maybe modified) character. Note that this may
+ modify the buffer containing the number. */
+
+int auth_rsa_read_mp_int(char **cpp, MP_INT *value)
+{
+ char *cp = *cpp;
+ int len, old;
+
+ /* Skip any leading whitespace. */
+ for (; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+
+ /* Check that it begins with a hex digit. */
+ if (*cp < '0' || *cp > '9')
+ return 0;
+
+ /* Save starting position. */
+ *cpp = cp;
+
+ /* Move forward until all hex digits skipped. */
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+
+ /* Compute the length of the hex number. */
+ len = cp - *cpp;
+
+ /* Save the old terminating character, and replace it by \0. */
+ old = *cp;
+ *cp = 0;
+
+ /* Parse the number. */
+ if (mpz_set_str(value, *cpp, 10) != 0)
+ return 0;
+
+ /* Restore old terminating character. */
+ *cp = old;
+
+ /* Move beyond the number and return success. */
+ *cpp = cp;
+ return 1;
+}
+
+/* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
+ over the key. Skips any whitespace at the beginning and at end. */
+
+int auth_rsa_read_key(char **cpp, unsigned int *bitsp, MP_INT *e, MP_INT *n)
+{
+ unsigned int bits;
+ char *cp;
+
+ /* Skip leading whitespace. */
+ for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+
+ /* Get number of bits. */
+ if (*cp < '0' || *cp > '9')
+ return 0; /* Bad bit count... */
+ for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
+ bits = 10 * bits + *cp - '0';
+
+ /* Get public exponent. */
+ if (!auth_rsa_read_mp_int(&cp, e))
+ return 0;
+
+ /* Get public modulus. */
+ if (!auth_rsa_read_mp_int(&cp, n))
+ return 0;
+
+ /* Skip trailing whitespace. */
+ for (; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+
+ /* Return results. */
+ *cpp = cp;
+ *bitsp = bits;
+ return 1;
+}
+
+/* Tries to match the host name (which must be in all lowercase) against the
+ comma-separated sequence of subpatterns (each possibly preceded by ! to
+ indicate negation). Returns true if there is a positive match; zero
+ otherwise. */
+
+int match_hostname(const char *host, const char *pattern, unsigned int len)
+{
+ char sub[1024];
+ int negated;
+ int got_positive;
+ unsigned int i, subi;
+
+ got_positive = 0;
+ for (i = 0; i < len;)
+ {
+ /* Check if the subpattern is negated. */
+ if (pattern[i] == '!')
+ {
+ negated = 1;
+ i++;
+ }
+ else
+ negated = 0;
+
+ /* Extract the subpattern up to a comma or end. Convert the subpattern
+ to lowercase. */
+ for (subi = 0;
+ i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
+ subi++, i++)
+ sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];
+ /* If subpattern too long, return failure (no match). */
+ if (subi >= sizeof(sub) - 1)
+ return 0;
+
+ /* If the subpattern was terminated by a comma, skip the comma. */
+ if (i < len && pattern[i] == ',')
+ i++;
+
+ /* Null-terminate the subpattern. */
+ sub[subi] = '\0';
+
+ /* Try to match the subpattern against the host name. */
+ if (match_pattern(host, sub))
+ if (negated)
+ return 0; /* Fail if host matches any negated subpattern. */
+ else
+ got_positive = 1;
+ }
+
+ /* Return success if got a positive match. If there was a negative match,
+ we have already returned zero and never get here. */
+ return got_positive;
+}
+
+/* Checks whether the given host (which must be in all lowercase) is
+ already in the list of our known hosts.
+ Returns HOST_OK if the host is known and has the specified key,
+ HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
+ but used to have a different host key. */
+
+HostStatus check_host_in_hostfile(const char *filename,
+ const char *host, unsigned int bits,
+ MP_INT *e, MP_INT *n)
+{
+ FILE *f;
+ char line[8192];
+ MP_INT ke, kn;
+ unsigned int kbits, hostlen;
+ char *cp, *cp2;
+ HostStatus end_return;
+ struct stat st;
+
+ /* Open the file containing the list of known hosts. */
+ f = fopen(filename, "r");
+ if (!f)
+ {
+ if (stat(filename, &st) >= 0)
+ {
+ packet_send_debug("Could not open %.900s for reading.", filename);
+ packet_send_debug("If your home directory is on an NFS volume, it may need to be world-readable.");
+ }
+ return HOST_NEW;
+ }
+
+ /* Initialize mp-int variables. */
+ mpz_init(&ke);
+ mpz_init(&kn);
+
+ /* Cache the length of the host name. */
+ hostlen = strlen(host);
+
+ /* Return value when the loop terminates. This is set to HOST_CHANGED if
+ we have seen a different key for the host and have not found the proper
+ one. */
+ end_return = HOST_NEW;
+
+ /* Go trough the file. */
+ while (fgets(line, sizeof(line), f))
+ {
+ cp = line;
+
+ /* Skip any leading whitespace. */
+ for (; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+
+ /* Ignore comment lines and empty lines. */
+ if (!*cp || *cp == '#' || *cp == '\n')
+ continue;
+
+ /* Find the end of the host name portion. */
+ for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
+ ;
+
+ /* Check if the host name matches. */
+ if (!match_hostname(host, cp, (unsigned int)(cp2 - cp)))
+ continue;
+
+ /* Got a match. Skip host name. */
+ cp = cp2;
+
+ /* Extract the key from the line. This will skip any leading
+ whitespace. Ignore badly formatted lines. */
+ if (!auth_rsa_read_key(&cp, &kbits, &ke, &kn))
+ continue;
+
+ /* Check if the current key is the same as the previous one. */
+ if (kbits == bits && mpz_cmp(&ke, e) == 0 && mpz_cmp(&kn, n) == 0)
+ {
+ /* Ok, they match. */
+ mpz_clear(&ke);
+ mpz_clear(&kn);
+ fclose(f);
+ return HOST_OK;
+ }
+
+ /* They do not match. We will continue to go through the file; however,
+ we note that we will not return that it is new. */
+ end_return = HOST_CHANGED;
+ }
+ /* Clear variables and close the file. */
+ mpz_clear(&ke);
+ mpz_clear(&kn);
+ fclose(f);
+
+ /* Return either HOST_NEW or HOST_CHANGED, depending on whether we saw a
+ different key for the host. */
+ return end_return;
+}
+
+/* Appends an entry to the host file. Returns false if the entry
+ could not be appended. */
+
+int add_host_to_hostfile(const char *filename, const char *host,
+ unsigned int bits, MP_INT *e, MP_INT *n)
+{
+ FILE *f;
+
+ /* Open the file for appending. */
+ f = fopen(filename, "a");
+ if (!f)
+ return 0;
+
+ /* Print the host name and key to the file. */
+ fprintf(f, "%s %u ", host, bits);
+ mpz_out_str(f, 10, e);
+ fprintf(f, " ");
+ mpz_out_str(f, 10, n);
+ fprintf(f, "\n");
+
+ /* Close the file. */
+ fclose(f);
+ return 1;
+}
diff --git a/usr.bin/ssh/includes.h b/usr.bin/ssh/includes.h
new file mode 100644
index 00000000000..d0f32525e1f
--- /dev/null
+++ b/usr.bin/ssh/includes.h
@@ -0,0 +1,263 @@
+/*
+
+includes.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Thu Mar 23 16:29:37 1995 ylo
+
+This file includes most of the needed system headers.
+
+*/
+
+/* RCSID("$Id: includes.h,v 1.1 1999/09/26 20:53:36 deraadt Exp $"); */
+
+#ifndef INCLUDES_H
+#define INCLUDES_H
+
+/* Note: autoconf documentation tells to use the <...> syntax and have -I. */
+#include <config.h>
+
+#include "version.h"
+
+typedef unsigned short word16;
+
+#if SIZEOF_LONG == 4
+typedef unsigned long word32;
+#else
+#if SIZEOF_INT == 4
+typedef unsigned int word32;
+#else
+#if SIZEOF_SHORT >= 4
+typedef unsigned short word32;
+#else
+YOU_LOSE
+#endif
+#endif
+#endif
+
+#ifdef SCO
+/* this is defined so that winsize gets ifdef'd in termio.h */
+#define _IBCS2
+#endif
+
+#if defined(__mips)
+/* Mach3 on MIPS defines conflicting garbage. */
+#define uint32 hidden_uint32
+#endif /* __mips */
+#include <sys/types.h>
+#if defined(__mips)
+#undef uint32
+#endif /* __mips */
+
+#if defined(bsd_44) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__PARAGON__)
+#include <sys/param.h>
+#include <machine/endian.h>
+#endif
+#if defined(linux)
+#include <endian.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <signal.h>
+
+#ifdef sparc
+#undef HAVE_SYS_IOCTL_H
+#endif
+
+#ifdef HAVE_SYS_IOCTL_H
+#include <sys/ioctl.h>
+#endif /* HAVE_SYS_IOCTL_H */
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#define USING_TERMIOS
+#endif /* HAVE_TERMIOS_H */
+
+#if defined(HAVE_SGTTY_H) && !defined(USING_TERMIOS)
+#include <sgtty.h>
+#define USING_SGTTY
+#endif
+
+#if !defined(USING_SGTTY) && !defined(USING_TERMIOS)
+ ERROR_NO_TERMIOS_OR_SGTTY
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#else /* STDC_HEADERS */
+/* stdarg.h is present almost everywhere, and comes with gcc; I am too lazy
+ to make things work with both it and varargs. */
+#include <stdarg.h>
+#ifndef HAVE_STRCHR
+#define strchr index
+#define strrchr rindex
+#endif
+char *strchr(), *strrchr();
+#ifndef HAVE_MEMCPY
+#define memcpy(d, s, n) bcopy((s), (d), (n))
+#define memmove(d, s, n) bcopy((s), (d), (n))
+#define memset(d, ch, n) bzero((d), (n)) /* We only memset to 0. */
+#define memcmp(a, b, n) bcmp((a), (b), (n))
+#endif
+#endif /* STDC_HEADERS */
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#ifdef HAVE_NETINET_IN_SYSTM_H
+#include <netinet/in_systm.h>
+#else /* Some old linux systems at least have in_system.h instead. */
+#include <netinet/in_system.h>
+#endif /* HAVE_NETINET_IN_SYSTM_H */
+#ifdef SCO
+/* SCO does not have a un.h and there is no appropriate substitute. */
+/* Latest news: it doesn't have AF_UNIX at all, but this allows
+ it to compile, and outgoing forwarded connections appear to work. */
+struct sockaddr_un {
+ short sun_family; /* AF_UNIX */
+ char sun_path[108]; /* path name (gag) */
+};
+/* SCO needs sys/stream.h and sys/ptem.h */
+#include <sys/stream.h>
+#include <sys/ptem.h>
+#else /* SCO */
+#include <sys/un.h>
+#endif /* SCO */
+#if !defined(__PARAGON__)
+#include <netinet/ip.h>
+#endif /* !__PARAGON__ */
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
+
+#include <pwd.h>
+#include <grp.h>
+#ifdef HAVE_GETSPNAM
+#include <shadow.h>
+#endif /* HAVE_GETSPNAM */
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#else /* HAVE_SYS_WAIT_H */
+#if !defined(WNOHANG) /* && (defined(bsd43) || defined(vax)) */
+#define WNOHANG 1
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(X) ((unsigned)(X) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(X) (((X) & 255) == 0)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(X) ((((X) & 255) != 0x255 && ((X) & 255) != 0))
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(X) ((X) & 255)
+#endif
+#endif /* HAVE_SYS_WAIT_H */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#ifdef TIME_WITH_SYS_TIME
+#ifndef SCO
+/* I excluded <sys/time.h> to avoid redefinition of timeval
+ which SCO puts in both <sys/select.h> and <sys/time.h> */
+#include <sys/time.h>
+#endif /* SCO */
+#include <time.h>
+#else /* TIME_WITH_SYS_TIME */
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#else /* HAVE_SYS_TIME_H */
+#include <time.h>
+#endif /* HAVE_SYS_TIME_H */
+#endif /* TIME_WITH_SYS_TIME */
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#if HAVE_DIRENT_H
+#include <dirent.h>
+#define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+#define dirent direct
+#define NAMLEN(dirent) (dirent)->d_namlen
+#if HAVE_SYS_NDIR_H
+#include <sys/ndir.h>
+#endif
+#if HAVE_SYS_DIR_H
+#include <sys/dir.h>
+#endif
+#if HAVE_NDIR_H
+#include <ndir.h>
+#endif
+#endif
+
+#ifdef HAVE_SETRLIMIT
+#include <sys/resource.h>
+#endif
+
+#ifndef HAVE_VSNPRINTF
+#define vsnprintf(buf, len, fmt, args) vsprintf(buf, fmt, args)
+#endif
+
+/* These POSIX macros are not defined in every system. */
+
+#ifndef S_IRWXU
+#define S_IRWXU 00700 /* read, write, execute: owner */
+#define S_IRUSR 00400 /* read permission: owner */
+#define S_IWUSR 00200 /* write permission: owner */
+#define S_IXUSR 00100 /* execute permission: owner */
+#define S_IRWXG 00070 /* read, write, execute: group */
+#define S_IRGRP 00040 /* read permission: group */
+#define S_IWGRP 00020 /* write permission: group */
+#define S_IXGRP 00010 /* execute permission: group */
+#define S_IRWXO 00007 /* read, write, execute: other */
+#define S_IROTH 00004 /* read permission: other */
+#define S_IWOTH 00002 /* write permission: other */
+#define S_IXOTH 00001 /* execute permission: other */
+#endif /* S_IRWXU */
+
+#ifndef S_ISUID
+#define S_ISUID 0x800
+#endif /* S_ISUID */
+#ifndef S_ISGID
+#define S_ISGID 0x400
+#endif /* S_ISGID */
+
+#ifndef S_ISDIR
+/* NextStep apparently fails to define this. */
+#define S_ISDIR(mode) (((mode)&(_S_IFMT))==(_S_IFDIR))
+#endif
+
+#ifdef STAT_MACROS_BROKEN
+/* Some systems have broken S_ISDIR etc. macros in sys/stat.h. Please ask
+ your vendor to fix them. You can then remove the line below, but only
+ after you have sent a complaint to your vendor. */
+WARNING_MACROS_IN_SYS_STAT_H_ARE_BROKEN_ON_YOUR_SYSTEM_READ_INCLUDES_H
+#endif /* STAT_MACROS_BROKEN */
+
+#if USE_STRLEN_FOR_AF_UNIX
+#define AF_UNIX_SIZE(unaddr) \
+ (sizeof((unaddr).sun_family) + strlen((unaddr).sun_path) + 1)
+#else
+#define AF_UNIX_SIZE(unaddr) sizeof(unaddr)
+#endif
+
+#endif /* INCLUDES_H */
diff --git a/usr.bin/ssh/install-sh b/usr.bin/ssh/install-sh
new file mode 100644
index 00000000000..89fc9b098b8
--- /dev/null
+++ b/usr.bin/ssh/install-sh
@@ -0,0 +1,238 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+#
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+tranformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/usr.bin/ssh/log-client.c b/usr.bin/ssh/log-client.c
new file mode 100644
index 00000000000..651f991e3f1
--- /dev/null
+++ b/usr.bin/ssh/log-client.c
@@ -0,0 +1,137 @@
+/*
+
+log-client.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Mar 20 21:13:40 1995 ylo
+
+Client-side versions of debug(), log(), etc. These print to stderr.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: log-client.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include "xmalloc.h"
+#include "ssh.h"
+
+static int log_debug = 0;
+static int log_quiet = 0;
+
+void log_init(char *av0, int on_stderr, int debug, int quiet,
+ SyslogFacility facility)
+{
+ log_debug = debug;
+ log_quiet = quiet;
+}
+
+void log(const char *fmt, ...)
+{
+ va_list args;
+
+ if (log_quiet)
+ return;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+}
+
+void debug(const char *fmt, ...)
+{
+ va_list args;
+ if (log_quiet || !log_debug)
+ return;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+}
+
+void error(const char *fmt, ...)
+{
+ va_list args;
+ if (log_quiet)
+ return;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+}
+
+struct fatal_cleanup
+{
+ struct fatal_cleanup *next;
+ void (*proc)(void *);
+ void *context;
+};
+
+static struct fatal_cleanup *fatal_cleanups = NULL;
+
+/* Registers a cleanup function to be called by fatal() before exiting. */
+
+void fatal_add_cleanup(void (*proc)(void *), void *context)
+{
+ struct fatal_cleanup *cu;
+
+ cu = xmalloc(sizeof(*cu));
+ cu->proc = proc;
+ cu->context = context;
+ cu->next = fatal_cleanups;
+ fatal_cleanups = cu;
+}
+
+/* Removes a cleanup frunction to be called at fatal(). */
+
+void fatal_remove_cleanup(void (*proc)(void *context), void *context)
+{
+ struct fatal_cleanup **cup, *cu;
+
+ for (cup = &fatal_cleanups; *cup; cup = &cu->next)
+ {
+ cu = *cup;
+ if (cu->proc == proc && cu->context == context)
+ {
+ *cup = cu->next;
+ xfree(cu);
+ return;
+ }
+ }
+ fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n",
+ (unsigned long)proc, (unsigned long)context);
+}
+
+/* Function to display an error message and exit. This is in this file because
+ this needs to restore terminal modes before exiting. See log-client.c
+ for other related functions. */
+
+void fatal(const char *fmt, ...)
+{
+ va_list args;
+ struct fatal_cleanup *cu, *next_cu;
+ static int fatal_called = 0;
+
+ if (!fatal_called)
+ {
+ fatal_called = 1;
+
+ /* Call cleanup functions. */
+ for (cu = fatal_cleanups; cu; cu = next_cu)
+ {
+ next_cu = cu->next;
+ (*cu->proc)(cu->context);
+ }
+ }
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+ exit(255);
+}
+
+/* fatal() is in ssh.c so that it can properly reset terminal modes. */
diff --git a/usr.bin/ssh/log-server.c b/usr.bin/ssh/log-server.c
new file mode 100644
index 00000000000..a5086b5df91
--- /dev/null
+++ b/usr.bin/ssh/log-server.c
@@ -0,0 +1,242 @@
+/*
+
+log-server.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Mar 20 21:19:30 1995 ylo
+
+Server-side versions of debug(), log(), etc. These normally send the output
+to the system log.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: log-server.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include <syslog.h>
+#ifdef NEED_SYS_SYSLOG_H
+#include <sys/syslog.h>
+#endif /* NEED_SYS_SYSLOG_H */
+#include "packet.h"
+#include "xmalloc.h"
+#include "ssh.h"
+
+static int log_debug = 0;
+static int log_quiet = 0;
+static int log_on_stderr = 0;
+
+/* Initialize the log.
+ av0 program name (should be argv[0])
+ on_stderr print also on stderr
+ debug send debugging messages to system log
+ quiet don\'t log anything
+ */
+
+void log_init(char *av0, int on_stderr, int debug, int quiet,
+ SyslogFacility facility)
+{
+ int log_facility;
+
+ switch (facility)
+ {
+ case SYSLOG_FACILITY_DAEMON:
+ log_facility = LOG_DAEMON;
+ break;
+ case SYSLOG_FACILITY_USER:
+ log_facility = LOG_USER;
+ break;
+ case SYSLOG_FACILITY_AUTH:
+ log_facility = LOG_AUTH;
+ break;
+ case SYSLOG_FACILITY_LOCAL0:
+ log_facility = LOG_LOCAL0;
+ break;
+ case SYSLOG_FACILITY_LOCAL1:
+ log_facility = LOG_LOCAL1;
+ break;
+ case SYSLOG_FACILITY_LOCAL2:
+ log_facility = LOG_LOCAL2;
+ break;
+ case SYSLOG_FACILITY_LOCAL3:
+ log_facility = LOG_LOCAL3;
+ break;
+ case SYSLOG_FACILITY_LOCAL4:
+ log_facility = LOG_LOCAL4;
+ break;
+ case SYSLOG_FACILITY_LOCAL5:
+ log_facility = LOG_LOCAL5;
+ break;
+ case SYSLOG_FACILITY_LOCAL6:
+ log_facility = LOG_LOCAL6;
+ break;
+ case SYSLOG_FACILITY_LOCAL7:
+ log_facility = LOG_LOCAL7;
+ break;
+ default:
+ fprintf(stderr, "Unrecognized internal syslog facility code %d\n",
+ (int)facility);
+ exit(1);
+ }
+
+ log_debug = debug;
+ log_quiet = quiet;
+ log_on_stderr = on_stderr;
+ closelog(); /* Close any previous log. */
+ openlog(av0, LOG_PID, log_facility);
+}
+
+#define MSGBUFSIZE 1024
+
+#ifdef HAVE_VSNPRINTF
+#define DECL_MSGBUF char msgbuf[MSGBUFSIZE]
+#else
+static char msgbuf[MSGBUFSIZE];
+#define DECL_MSGBUF
+#endif
+
+/* Log this message (information that usually should go to the log). */
+
+void log(const char *fmt, ...)
+{
+ va_list args;
+ DECL_MSGBUF;
+ if (log_quiet)
+ return;
+ va_start(args, fmt);
+ vsnprintf(msgbuf, MSGBUFSIZE, fmt, args);
+ va_end(args);
+ if (log_on_stderr)
+ fprintf(stderr, "log: %s\n", msgbuf);
+ syslog(LOG_INFO, "log: %.500s", msgbuf);
+}
+
+/* Debugging messages that should not be logged during normal operation. */
+
+void debug(const char *fmt, ...)
+{
+ va_list args;
+ DECL_MSGBUF;
+ if (!log_debug || log_quiet)
+ return;
+ va_start(args, fmt);
+ vsnprintf(msgbuf, MSGBUFSIZE, fmt, args);
+ va_end(args);
+ if (log_on_stderr)
+ fprintf(stderr, "debug: %s\n", msgbuf);
+ syslog(LOG_DEBUG, "debug: %.500s", msgbuf);
+}
+
+/* Error messages that should be logged. */
+
+void error(const char *fmt, ...)
+{
+ va_list args;
+ DECL_MSGBUF;
+ if (log_quiet)
+ return;
+ va_start(args, fmt);
+ vsnprintf(msgbuf, MSGBUFSIZE, fmt, args);
+ va_end(args);
+ if (log_on_stderr)
+ fprintf(stderr, "error: %s\n", msgbuf);
+ syslog(LOG_ERR, "error: %.500s", msgbuf);
+}
+
+struct fatal_cleanup
+{
+ struct fatal_cleanup *next;
+ void (*proc)(void *);
+ void *context;
+};
+
+static struct fatal_cleanup *fatal_cleanups = NULL;
+
+/* Registers a cleanup function to be called by fatal() before exiting. */
+
+void fatal_add_cleanup(void (*proc)(void *), void *context)
+{
+ struct fatal_cleanup *cu;
+
+ cu = xmalloc(sizeof(*cu));
+ cu->proc = proc;
+ cu->context = context;
+ cu->next = fatal_cleanups;
+ fatal_cleanups = cu;
+}
+
+/* Removes a cleanup frunction to be called at fatal(). */
+
+void fatal_remove_cleanup(void (*proc)(void *context), void *context)
+{
+ struct fatal_cleanup **cup, *cu;
+
+ for (cup = &fatal_cleanups; *cup; cup = &cu->next)
+ {
+ cu = *cup;
+ if (cu->proc == proc && cu->context == context)
+ {
+ *cup = cu->next;
+ xfree(cu);
+ return;
+ }
+ }
+ fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx\n",
+ (unsigned long)proc, (unsigned long)context);
+}
+
+/* Fatal messages. This function never returns. */
+
+void fatal(const char *fmt, ...)
+{
+ va_list args;
+ struct fatal_cleanup *cu, *next_cu;
+ static int fatal_called = 0;
+#if defined(KRB4)
+ extern char *ticket;
+#endif /* KRB4 */
+ DECL_MSGBUF;
+
+ if (log_quiet)
+ exit(1);
+ va_start(args, fmt);
+ vsnprintf(msgbuf, MSGBUFSIZE, fmt, args);
+ va_end(args);
+ if (log_on_stderr)
+ fprintf(stderr, "fatal: %s\n", msgbuf);
+ syslog(LOG_ERR, "fatal: %.500s", msgbuf);
+
+ if (fatal_called)
+ exit(1);
+ fatal_called = 1;
+
+ /* Call cleanup functions. */
+ for (cu = fatal_cleanups; cu; cu = next_cu)
+ {
+ next_cu = cu->next;
+ debug("Calling cleanup 0x%lx(0x%lx)",
+ (unsigned long)cu->proc, (unsigned long)cu->context);
+ (*cu->proc)(cu->context);
+ }
+#if defined(KRB4)
+ /* If you forwarded a ticket you get one shot for proper
+ authentication. */
+ /* If tgt was passed unlink file */
+ if (ticket)
+ {
+ if (strcmp(ticket,"none"))
+ /* ticket -> FILE:path */
+ unlink(ticket + 5);
+ else
+ ticket = NULL;
+ }
+#endif /* KRB4 */
+
+ /* If local XAUTHORITY was created, remove it. */
+ if (xauthfile) unlink(xauthfile);
+
+ exit(1);
+}
diff --git a/usr.bin/ssh/login.c b/usr.bin/ssh/login.c
new file mode 100644
index 00000000000..6386d45f99f
--- /dev/null
+++ b/usr.bin/ssh/login.c
@@ -0,0 +1,399 @@
+/*
+
+login.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Fri Mar 24 14:51:08 1995 ylo
+
+This file performs some of the things login(1) normally does. We cannot
+easily use something like login -p -h host -f user, because there are
+several different logins around, and it is hard to determined what kind of
+login the current system has. Also, we want to be able to execute commands
+on a tty.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: login.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#ifdef HAVE_UTMP_H
+#include <utmp.h>
+#ifdef HAVE_LASTLOG_H
+#include <lastlog.h> /* Some have the definitions in utmp.h. */
+#endif /* HAVE_LASTLOG_H */
+#endif /* HAVE_UTMP_H */
+#ifdef HAVE_UTMPX_H
+#include <utmpx.h>
+#endif /* HAVE_UTMPX_H */
+#ifdef HAVE_USERSEC_H
+#include <usersec.h>
+#endif /* HAVE_USERSEC_H */
+#include "ssh.h"
+
+/* Returns the time when the user last logged in. Returns 0 if the
+ information is not available. This must be called before record_login.
+ The host the user logged in from will be returned in buf. */
+
+#ifdef LASTLOG_IS_DIR
+unsigned long get_last_login_time(uid_t uid, const char *name,
+ char *buf, unsigned int bufsize)
+{
+#if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
+ struct lastlog ll;
+ char lastlogfile[500];
+ int fd;
+
+#ifdef _PATH_LASTLOG
+ sprintf(lastlogfile, "%.200s/%.200s", _PATH_LASTLOG, name);
+#else
+#ifdef LASTLOG_FILE
+ sprintf(lastlogfile, "%.200s/%.200s", LASTLOG_FILE, name);
+#else
+ sprintf(lastlogfile, "%.200s/%.200s", SSH_LASTLOG, name);
+#endif
+#endif
+
+ strcpy(buf, "");
+
+ fd = open(lastlogfile, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ if (read(fd, &ll, sizeof(ll)) != sizeof(ll))
+ {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+ if (bufsize > sizeof(ll.ll_host) + 1)
+ bufsize = sizeof(ll.ll_host) + 1;
+ strncpy(buf, ll.ll_host, bufsize - 1);
+ buf[bufsize - 1] = 0;
+ return ll.ll_time;
+
+#else /* HAVE_LASTLOG_H || HAVE_LASTLOG */
+
+ return 0;
+
+#endif /* HAVE_LASTLOG_H || HAVE_LASTLOG */
+}
+
+#else /* LASTLOG_IS_DIR */
+
+/* Returns the time when the user last logged in (or 0 if no previous login
+ is found). The name of the host used last time is returned in buf. */
+
+unsigned long get_last_login_time(uid_t uid, const char *logname,
+ char *buf, unsigned int bufsize)
+{
+#if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
+
+ struct lastlog ll;
+ char *lastlog;
+ int fd;
+
+#ifdef _PATH_LASTLOG
+ lastlog = _PATH_LASTLOG;
+#else
+#ifdef LASTLOG_FILE
+ lastlog = LASTLOG_FILE;
+#else
+ lastlog = SSH_LASTLOG;
+#endif
+#endif
+
+ strcpy(buf, "");
+
+ fd = open(lastlog, O_RDONLY);
+ if (fd < 0)
+ return 0;
+ lseek(fd, (off_t)((long)uid * sizeof(ll)), 0);
+ if (read(fd, &ll, sizeof(ll)) != sizeof(ll))
+ {
+ close(fd);
+ return 0;
+ }
+ close(fd);
+ if (bufsize > sizeof(ll.ll_host) + 1)
+ bufsize = sizeof(ll.ll_host) + 1;
+ strncpy(buf, ll.ll_host, bufsize - 1);
+ buf[bufsize - 1] = 0;
+ return ll.ll_time;
+
+#else /* HAVE_LASTLOG_H || HAVE_LASTLOG */
+
+#ifdef HAVE_USERSEC_H
+
+ char *lasthost;
+ int lasttime;
+ if (setuserdb(S_READ) < 0)
+ return 0;
+ if (getuserattr((char *)logname, S_LASTTIME, &lasttime, SEC_INT) < 0)
+ {
+ enduserdb();
+ return 0;
+ }
+ if (getuserattr((char *)logname, S_LASTHOST, &lasthost, SEC_CHAR) < 0)
+ {
+ enduserdb();
+ return 0;
+ }
+ strncpy(buf, lasthost, bufsize);
+ buf[bufsize - 1] = 0;
+ if (enduserdb() < 0)
+ return 0;
+ return lasttime;
+
+#else /* HAVE_USERSEC_H */
+
+ return 0;
+
+#endif /* HAVE_USERSEC_H */
+
+#endif /* HAVE_LASTLOG_H || HAVE_LASTLOG */
+}
+#endif /* LASTLOG_IS_DIR */
+
+/* Records that the user has logged in. I these parts of operating systems
+ were more standardized. */
+
+void record_login(int pid, const char *ttyname, const char *user, uid_t uid,
+ const char *host, struct sockaddr_in *addr)
+{
+ int fd;
+
+#if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
+ struct lastlog ll;
+ char *lastlog;
+#ifdef LASTLOG_IS_DIR
+ char lastlogfile[100];
+#endif /* LASTLOG_IS_DIR */
+#endif /* HAVE_LASTLOG_H || HAVE_LASTLOG */
+
+#if defined(HAVE_UTMP_H) && !defined(HAVE_UTMPX_H)
+ struct utmp u, u2;
+ off_t offset;
+ const char *utmp, *wtmp;
+
+ /* Construct an utmp/wtmp entry. */
+ memset(&u, 0, sizeof(u));
+#ifdef DEAD_PROCESS
+ if (strcmp(user, "") == 0)
+ u.ut_type = DEAD_PROCESS; /* logout */
+ else
+ u.ut_type = USER_PROCESS;
+#endif /* LOGIN_PROCESS */
+#ifdef HAVE_PID_IN_UTMP
+ u.ut_pid = pid;
+#endif /* PID_IN_UTMP */
+#ifdef HAVE_ID_IN_UTMP
+#ifdef __sgi
+ strncpy(u.ut_id, ttyname + 8, sizeof(u.ut_id)); /* /dev/ttyq99 -> q99 */
+#else /* __sgi */
+ if (sizeof(u.ut_id) > 4)
+ strncpy(u.ut_id, ttyname + 5, sizeof(u.ut_id));
+ else
+ strncpy(u.ut_id, ttyname + strlen(ttyname) - 2, sizeof(u.ut_id));
+#endif /* __sgi */
+#endif /* HAVE_ID_IN_UTMP */
+ strncpy(u.ut_line, ttyname + 5, sizeof(u.ut_line));
+ u.ut_time = time(NULL);
+#ifdef HAVE_NAME_IN_UTMP
+ strncpy(u.ut_name, user, sizeof(u.ut_name));
+#else /* HAVE_NAME_IN_UTMP */
+ strncpy(u.ut_user, user, sizeof(u.ut_user));
+#endif /* HAVE_NAME_IN_UTMP */
+#ifdef HAVE_HOST_IN_UTMP
+ strncpy(u.ut_host, host, sizeof(u.ut_host));
+#endif /* HAVE_HOST_IN_UTMP */
+#ifdef HAVE_ADDR_IN_UTMP
+ if (addr)
+ memcpy(&u.ut_addr, &addr->sin_addr, sizeof(u.ut_addr));
+ else
+ memset(&u.ut_addr, 0, sizeof(u.ut_addr));
+#endif
+
+ /* Figure out the file names. */
+#ifdef _PATH_UTMP
+ utmp = _PATH_UTMP;
+ wtmp = _PATH_WTMP;
+#else
+#ifdef UTMP_FILE
+ utmp = UTMP_FILE;
+ wtmp = WTMP_FILE;
+#else
+ utmp = SSH_UTMP;
+ wtmp = SSH_WTMP;
+#endif
+#endif
+
+#ifdef HAVE_LIBUTIL_LOGIN
+ login(&u);
+#else /* HAVE_LIBUTIL_LOGIN */
+ /* Append an entry to wtmp. */
+ fd = open(wtmp, O_WRONLY|O_APPEND);
+ if (fd >= 0)
+ {
+ if (write(fd, &u, sizeof(u)) != sizeof(u))
+ log("Could not write %.100s: %.100s", wtmp, strerror(errno));
+ close(fd);
+ }
+
+ /* Replace the proper entry in utmp, as identified by ut_line. Append a
+ new entry if the line could not be found. */
+ fd = open(utmp, O_RDWR);
+ if (fd >= 0)
+ {
+ while (1)
+ {
+ offset = lseek(fd, (off_t)0L, 1);
+ if (read(fd, &u2, sizeof(u2)) != sizeof(u2))
+ {
+ lseek(fd, offset, 0);
+ if (write(fd, &u, sizeof(u)) != sizeof(u))
+ log("Could not append to %.100s: %.100s",
+ utmp, strerror(errno));
+ break;
+ }
+ if (strncmp(u2.ut_line, ttyname + 5, sizeof(u2.ut_line)) == 0)
+ {
+ lseek(fd, offset, 0);
+ if (write(fd, &u, sizeof(u)) != sizeof(u))
+ log("Could not write to %.100s: %.100s",
+ utmp, strerror(errno));
+ break;
+ }
+ }
+ close(fd);
+ }
+#endif /* HAVE_LIBUTIL_LOGIN */
+#endif /* HAVE_UTMP_H && !HAVE_UTMPX_H */
+
+#ifdef HAVE_UTMPX_H
+ {
+ struct utmpx ux, *uxp;
+ memset(&ux, 0, sizeof(ux));
+ strncpy(ux.ut_line, ttyname + 5, sizeof(ux.ut_line));
+ uxp = getutxline(&ux);
+ if (uxp)
+ ux = *uxp;
+ strncpy(ux.ut_user, user, sizeof(ux.ut_user));
+#ifdef __sgi
+ strncpy(ux.ut_id, ttyname + 8, sizeof(ux.ut_id)); /* /dev/ttyq99 -> q99 */
+#else /* __sgi */
+ if (sizeof(ux.ut_id) > 4)
+ strncpy(ux.ut_id, ttyname + 5, sizeof(ux.ut_id));
+ else
+ strncpy(ux.ut_id, ttyname + strlen(ttyname) - 2, sizeof(ux.ut_id));
+#endif /* __sgi */
+ ux.ut_pid = pid;
+ if (strcmp(user, "") == 0)
+ ux.ut_type = DEAD_PROCESS;
+ else
+ ux.ut_type = USER_PROCESS;
+ gettimeofday(&ux.ut_tv, NULL);
+#if HAVE_UT_SESSION
+ ux.ut_session = pid;
+#endif
+ strncpy(ux.ut_host, host, sizeof(ux.ut_host));
+ ux.ut_host[sizeof(ux.ut_host) - 1] = 0;
+#ifdef HAVE_UT_SYSLEN
+ ux.ut_syslen = strlen(ux.ut_host);
+#endif
+ pututxline(&ux);
+#ifdef WTMPX_FILE
+ updwtmpx(WTMPX_FILE, &ux);
+#endif
+ endutxent();
+ }
+#endif /* HAVE_UTMPX_H */
+
+#if defined(HAVE_LASTLOG_H) || defined(HAVE_LASTLOG)
+
+#ifdef _PATH_LASTLOG
+ lastlog = _PATH_LASTLOG;
+#else
+#ifdef LASTLOG_FILE
+ lastlog = LASTLOG_FILE;
+#else
+ lastlog = SSH_LASTLOG;
+#endif
+#endif
+
+ /* Update lastlog unless actually recording a logout. */
+ if (strcmp(user, "") != 0)
+ {
+ /* It is safer to bzero the lastlog structure first because some
+ systems might have some extra fields in it (e.g. SGI) */
+ memset(&ll, 0, sizeof(ll));
+
+ /* Update lastlog. */
+ ll.ll_time = time(NULL);
+ strncpy(ll.ll_line, ttyname + 5, sizeof(ll.ll_line));
+ strncpy(ll.ll_host, host, sizeof(ll.ll_host));
+#ifdef LASTLOG_IS_DIR
+ sprintf(lastlogfile, "%.100s/%.100s", lastlog, user);
+ fd = open(lastlogfile, O_WRONLY | O_CREAT, 0644);
+ if (fd >= 0)
+ {
+ if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
+ log("Could not write %.100s: %.100s",
+ lastlogfile, strerror(errno));
+ close(fd);
+ }
+ else
+ {
+ log("Could not open %.100s: %.100s", lastlogfile, strerror(errno));
+ }
+#else /* LASTLOG_IS_DIR */
+ fd = open(lastlog, O_RDWR);
+ if (fd >= 0)
+ {
+ lseek(fd, (off_t)((long)uid * sizeof(ll)), 0);
+ if (write(fd, &ll, sizeof(ll)) != sizeof(ll))
+ log("Could not write %.100s: %.100s", lastlog, strerror(errno));
+ close(fd);
+ }
+#endif /* LASTLOG_IS_DIR */
+ }
+#endif /* HAVE_LASTLOG_H || HAVE_LASTLOG */
+
+#ifdef HAVE_USERSEC_H
+
+ if (strcmp(user, "") != 0)
+ {
+ int lasttime = time(NULL);
+ if (setuserdb(S_WRITE) < 0)
+ log("setuserdb S_WRITE failed: %.100s", strerror(errno));
+ if (putuserattr((char *)user, S_LASTTIME, (void *)lasttime, SEC_INT) < 0)
+ log("putuserattr S_LASTTIME failed: %.100s", strerror(errno));
+ if (putuserattr((char *)user, S_LASTTTY, (void *)(ttyname + 5),
+ SEC_CHAR) < 0)
+ log("putuserattr S_LASTTTY %.900s failed: %.100s",
+ ttyname, strerror(errno));
+ if (putuserattr((char *)user, S_LASTHOST, (void *)host, SEC_CHAR) < 0)
+ log("putuserattr S_LASTHOST %.900s failed: %.100s",
+ host, strerror(errno));
+ if (putuserattr((char *)user, 0, NULL, SEC_COMMIT) < 0)
+ log("putuserattr SEC_COMMIT failed: %.100s", strerror(errno));
+ if (enduserdb() < 0)
+ log("enduserdb failed: %.100s", strerror(errno));
+ }
+#endif
+}
+
+/* Records that the user has logged out. */
+
+void record_logout(int pid, const char *ttyname)
+{
+#ifdef HAVE_LIBUTIL_LOGIN
+ const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
+ if (logout(line))
+ logwtmp(line, "", "");
+#else /* HAVE_LIBUTIL_LOGIN */
+ record_login(pid, ttyname, "", -1, "", NULL);
+#endif /* HAVE_LIBUTIL_LOGIN */
+}
diff --git a/usr.bin/ssh/match.c b/usr.bin/ssh/match.c
new file mode 100644
index 00000000000..a5cab2877e4
--- /dev/null
+++ b/usr.bin/ssh/match.c
@@ -0,0 +1,78 @@
+/*
+
+match.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Thu Jun 22 01:17:50 1995 ylo
+
+Simple pattern matching, with '*' and '?' as wildcards.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: match.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include "ssh.h"
+
+/* Returns true if the given string matches the pattern (which may contain
+ ? and * as wildcards), and zero if it does not match. */
+
+int match_pattern(const char *s, const char *pattern)
+{
+ while (1)
+ {
+ /* If at end of pattern, accept if also at end of string. */
+ if (!*pattern)
+ return !*s;
+
+ /* Process '*'. */
+ if (*pattern == '*')
+ {
+ /* Skip the asterisk. */
+ pattern++;
+
+ /* If at end of pattern, accept immediately. */
+ if (!*pattern)
+ return 1;
+
+ /* If next character in pattern is known, optimize. */
+ if (*pattern != '?' && *pattern != '*')
+ {
+ /* Look instances of the next character in pattern, and try
+ to match starting from those. */
+ for (; *s; s++)
+ if (*s == *pattern &&
+ match_pattern(s + 1, pattern + 1))
+ return 1;
+ /* Failed. */
+ return 0;
+ }
+
+ /* Move ahead one character at a time and try to match at each
+ position. */
+ for (; *s; s++)
+ if (match_pattern(s, pattern))
+ return 1;
+ /* Failed. */
+ return 0;
+ }
+
+ /* There must be at least one more character in the string. If we are
+ at the end, fail. */
+ if (!*s)
+ return 0;
+
+ /* Check if the next character of the string is acceptable. */
+ if (*pattern != '?' && *pattern != *s)
+ return 0;
+
+ /* Move to the next character, both in string and in pattern. */
+ s++;
+ pattern++;
+ }
+ /*NOTREACHED*/
+}
diff --git a/usr.bin/ssh/minfd.c b/usr.bin/ssh/minfd.c
new file mode 100644
index 00000000000..a074acbf265
--- /dev/null
+++ b/usr.bin/ssh/minfd.c
@@ -0,0 +1,96 @@
+/*
+
+minfd.c
+
+Author: David Mazieres <dm@lcs.mit.edu>
+ Contributed to be part of ssh.
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Tue Aug 22 17:25:30 1995 ylo
+
+*/
+
+#include "includes.h"
+RCSID("$Id: minfd.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include <sys/resource.h> /* Needed by fdlim.h */
+#include "fdlim.h"
+#include "minfd.h"
+
+#ifdef _PATH_BSHELL
+#define DEFAULT_SHELL _PATH_BSHELL
+#else
+#define DEFAULT_SHELL "/bin/sh"
+#endif
+
+static int
+_get_permanent_fd(const char *shellpath)
+{
+ const char *shell;
+ struct passwd *pwd;
+ int fdmin;
+ int fdlim;
+ int fd;
+ int i;
+
+ if (!shellpath)
+ {
+ if (!shellpath)
+ shellpath = getenv("SHELL");
+ if (!shellpath)
+ if ((pwd = getpwuid(getuid())))
+ shellpath = pwd->pw_shell;
+ if (!shellpath)
+ shellpath = DEFAULT_SHELL;
+ }
+ if ((shell = strrchr(shellpath, '/')))
+ shell++;
+ else
+ shell = shellpath;
+
+ for (i = 0; strcmp(mafd[i].shell, shell); i++)
+ if (i == MAFD_MAX - 1)
+ return -1;
+
+ fdmin = mafd[i].fd;
+ fdlim = fdlim_get(0);
+
+ if (fdmin < fdlim)
+ {
+ /* First try to find a file descriptor as high as possible without
+ upping the limit */
+ fd = fdlim - 1;
+ while (fd >= fdmin)
+ {
+ if (fcntl(fd, F_GETFL, NULL) < 0)
+ return fd;
+ fd--;
+ }
+ }
+
+ fd = fdlim;
+ for (;;)
+ {
+ if (fdlim_set(fd + 1) < 0)
+ return -1;
+ if (fcntl(fd, F_GETFL, NULL) < 0)
+ break;
+ fd++;
+ }
+ return fd;
+}
+
+int
+get_permanent_fd(const char *shellpath)
+{
+ static int fd = -2;
+
+ if (fd >= -1)
+ return fd;
+ fd = _get_permanent_fd(shellpath);
+ if (fd < 0)
+ fd = -1;
+ return fd;
+}
diff --git a/usr.bin/ssh/mpaux.c b/usr.bin/ssh/mpaux.c
new file mode 100644
index 00000000000..78ff1f93d68
--- /dev/null
+++ b/usr.bin/ssh/mpaux.c
@@ -0,0 +1,93 @@
+/*
+
+mpaux.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sun Jul 16 04:29:30 1995 ylo
+
+This file contains various auxiliary functions related to multiple
+precision integers.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: mpaux.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include <gmp.h>
+#include "getput.h"
+#include "xmalloc.h"
+#include "ssh_md5.h"
+
+/* Converts a multiple-precision integer into bytes to be stored in the buffer.
+ The buffer will contain the value of the integer, msb first. */
+
+void mp_linearize_msb_first(unsigned char *buf, unsigned int len,
+ MP_INT *value)
+{
+ unsigned int i;
+ MP_INT aux;
+ mpz_init_set(&aux, value);
+ for (i = len; i >= 4; i -= 4)
+ {
+ unsigned int limb = mpz_get_ui(&aux);
+ PUT_32BIT(buf + i - 4, limb);
+ mpz_div_2exp(&aux, &aux, 32);
+ }
+ for (; i > 0; i--)
+ {
+ buf[i - 1] = mpz_get_ui(&aux);
+ mpz_div_2exp(&aux, &aux, 8);
+ }
+ mpz_clear(&aux);
+}
+
+/* Extract a multiple-precision integer from buffer. The value is stored
+ in the buffer msb first. */
+
+void mp_unlinearize_msb_first(MP_INT *value, const unsigned char *buf,
+ unsigned int len)
+{
+ unsigned int i;
+ mpz_set_ui(value, 0);
+ for (i = 0; i + 4 <= len; i += 4)
+ {
+ unsigned int limb = GET_32BIT(buf + i);
+ mpz_mul_2exp(value, value, 32);
+ mpz_add_ui(value, value, limb);
+ }
+ for (; i < len; i++)
+ {
+ mpz_mul_2exp(value, value, 8);
+ mpz_add_ui(value, value, buf[i]);
+ }
+}
+
+/* Computes a 16-byte session id in the global variable session_id.
+ The session id is computed by concatenating the linearized, msb
+ first representations of host_key_n, session_key_n, and the cookie. */
+
+void compute_session_id(unsigned char session_id[16],
+ unsigned char cookie[8],
+ unsigned int host_key_bits,
+ MP_INT *host_key_n,
+ unsigned int session_key_bits,
+ MP_INT *session_key_n)
+{
+ unsigned int bytes = (host_key_bits + 7) / 8 + (session_key_bits + 7) / 8 + 8;
+ unsigned char *buf = xmalloc(bytes);
+ struct MD5Context md;
+
+ mp_linearize_msb_first(buf, (host_key_bits + 7 ) / 8, host_key_n);
+ mp_linearize_msb_first(buf + (host_key_bits + 7 ) / 8,
+ (session_key_bits + 7) / 8, session_key_n);
+ memcpy(buf + (host_key_bits + 7) / 8 + (session_key_bits + 7) / 8,
+ cookie, 8);
+ MD5Init(&md);
+ MD5Update(&md, buf, bytes);
+ MD5Final(session_id, &md);
+ xfree(buf);
+}
diff --git a/usr.bin/ssh/mpaux.h b/usr.bin/ssh/mpaux.h
new file mode 100644
index 00000000000..1a310901786
--- /dev/null
+++ b/usr.bin/ssh/mpaux.h
@@ -0,0 +1,42 @@
+/*
+
+mpaux.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sun Jul 16 04:29:30 1995 ylo
+
+This file contains various auxiliary functions related to multiple
+precision integers.
+
+*/
+
+/* RCSID("$Id: mpaux.h,v 1.1 1999/09/26 20:53:36 deraadt Exp $"); */
+
+#ifndef MPAUX_H
+#define MPAUX_H
+
+/* Converts a multiple-precision integer into bytes to be stored in the buffer.
+ The buffer will contain the value of the integer, msb first. */
+void mp_linearize_msb_first(unsigned char *buf, unsigned int len,
+ MP_INT *value);
+
+/* Extract a multiple-precision integer from buffer. The value is stored
+ in the buffer msb first. */
+void mp_unlinearize_msb_first(MP_INT *value, const unsigned char *buf,
+ unsigned int len);
+
+/* Computes a 16-byte session id in the global variable session_id.
+ The session id is computed by concatenating the linearized, msb
+ first representations of host_key_n, session_key_n, and the cookie. */
+void compute_session_id(unsigned char session_id[16],
+ unsigned char cookie[8],
+ unsigned int host_key_bits,
+ MP_INT *host_key_n,
+ unsigned int session_key_bits,
+ MP_INT *session_key_n);
+
+#endif /* MPAUX_H */
diff --git a/usr.bin/ssh/packet.c b/usr.bin/ssh/packet.c
new file mode 100644
index 00000000000..8b3fd513fc3
--- /dev/null
+++ b/usr.bin/ssh/packet.c
@@ -0,0 +1,732 @@
+/*
+
+packet.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 18 02:40:40 1995 ylo
+
+This file contains code implementing the packet protocol and communication
+with the other side. This same code is used both on client and server side.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: packet.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include "xmalloc.h"
+#include "randoms.h"
+#include "buffer.h"
+#include "packet.h"
+#include "bufaux.h"
+#include "ssh.h"
+#include "crc32.h"
+#include "cipher.h"
+#include "getput.h"
+
+#ifdef WITH_ZLIB
+#include "compress.h"
+#endif /* WITH_ZLIB */
+
+/* This variable contains the file descriptors used for communicating with
+ the other side. connection_in is used for reading; connection_out
+ for writing. These can be the same descriptor, in which case it is
+ assumed to be a socket. */
+static int connection_in = -1;
+static int connection_out = -1;
+
+/* Cipher type. This value is only used to determine whether to pad the
+ packets with zeroes or random data. */
+static int cipher_type = SSH_CIPHER_NONE;
+
+/* Protocol flags for the remote side. */
+static unsigned int remote_protocol_flags = 0;
+
+/* Encryption context for receiving data. This is only used for decryption. */
+static CipherContext receive_context;
+/* Encryption coontext for sending data. This is only used for encryption. */
+static CipherContext send_context;
+
+/* Buffer for raw input data from the socket. */
+static Buffer input;
+
+/* Buffer for raw output data going to the socket. */
+static Buffer output;
+
+/* Buffer for the partial outgoing packet being constructed. */
+static Buffer outgoing_packet;
+
+/* Buffer for the incoming packet currently being processed. */
+static Buffer incoming_packet;
+
+/* Scratch buffer for packet compression/decompression. */
+static Buffer compression_buffer;
+
+#ifdef WITH_ZLIB
+/* Flag indicating whether packet compression/decompression is enabled. */
+static int packet_compression = 0;
+#endif /* WITH_ZLIB */
+
+/* Pointer to the random number generator state. */
+static RandomState *random_state;
+
+/* Flag indicating whether this module has been initialized. */
+static int initialized = 0;
+
+/* Set to true if the connection is interactive. */
+static int interactive_mode = 0;
+
+/* Sets the descriptors used for communication. Disables encryption until
+ packet_set_encryption_key is called. */
+
+void packet_set_connection(int fd_in, int fd_out, RandomState *state)
+{
+ connection_in = fd_in;
+ connection_out = fd_out;
+ random_state = state;
+ cipher_type = SSH_CIPHER_NONE;
+ cipher_set_key(&send_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 1);
+ cipher_set_key(&receive_context, SSH_CIPHER_NONE, (unsigned char *)"", 0, 0);
+ if (!initialized)
+ {
+ initialized = 1;
+ buffer_init(&input);
+ buffer_init(&output);
+ buffer_init(&outgoing_packet);
+ buffer_init(&incoming_packet);
+ }
+
+ /* Kludge: arrange the close function to be called from fatal(). */
+ fatal_add_cleanup((void (*)(void *))packet_close, NULL);
+}
+
+/* Sets the connection into non-blocking mode. */
+
+void packet_set_nonblocking()
+{
+ /* Set the socket into non-blocking mode. */
+#if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN)
+ if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)
+ error("fcntl O_NONBLOCK: %.100s", strerror(errno));
+#else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+ if (fcntl(connection_in, F_SETFL, O_NDELAY) < 0)
+ error("fcntl O_NDELAY: %.100s", strerror(errno));
+#endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+
+ if (connection_out != connection_in)
+ {
+#if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN)
+ if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)
+ error("fcntl O_NONBLOCK: %.100s", strerror(errno));
+#else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+ if (fcntl(connection_out, F_SETFL, O_NDELAY) < 0)
+ error("fcntl O_NDELAY: %.100s", strerror(errno));
+#endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+ }
+}
+
+/* Returns the socket used for reading. */
+
+int packet_get_connection_in()
+{
+ return connection_in;
+}
+
+/* Returns the descriptor used for writing. */
+
+int packet_get_connection_out()
+{
+ return connection_out;
+}
+
+/* Closes the connection and clears and frees internal data structures. */
+
+void packet_close()
+{
+ if (!initialized)
+ return;
+ initialized = 0;
+ if (connection_in == connection_out)
+ {
+ shutdown(connection_out, 2);
+ close(connection_out);
+ }
+ else
+ {
+ close(connection_in);
+ close(connection_out);
+ }
+ buffer_free(&input);
+ buffer_free(&output);
+ buffer_free(&outgoing_packet);
+ buffer_free(&incoming_packet);
+#ifdef WITH_ZLIB
+ if (packet_compression)
+ {
+ buffer_free(&compression_buffer);
+ buffer_compress_uninit();
+ }
+#endif /* WITH_ZLIB */
+}
+
+/* Sets remote side protocol flags. */
+
+void packet_set_protocol_flags(unsigned int protocol_flags)
+{
+ remote_protocol_flags = protocol_flags;
+ channel_set_options((protocol_flags & SSH_PROTOFLAG_HOST_IN_FWD_OPEN) != 0);
+}
+
+/* Returns the remote protocol flags set earlier by the above function. */
+
+unsigned int packet_get_protocol_flags()
+{
+ return remote_protocol_flags;
+}
+
+#ifdef WITH_ZLIB
+/* Starts packet compression from the next packet on in both directions.
+ Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */
+
+void packet_start_compression(int level)
+{
+ if (packet_compression)
+ fatal("Compression already enabled.");
+ packet_compression = 1;
+ buffer_init(&compression_buffer);
+ buffer_compress_init(level);
+}
+#endif /* WITH_ZLIB */
+
+/* Encrypts the given number of bytes, copying from src to dest.
+ bytes is known to be a multiple of 8. */
+
+void packet_encrypt(CipherContext *cc, void *dest, void *src,
+ unsigned int bytes)
+{
+ assert((bytes % 8) == 0);
+ cipher_encrypt(cc, dest, src, bytes);
+}
+
+/* Decrypts the given number of bytes, copying from src to dest.
+ bytes is known to be a multiple of 8. */
+
+void packet_decrypt(CipherContext *cc, void *dest, void *src,
+ unsigned int bytes)
+{
+ assert((bytes % 8) == 0);
+ cipher_decrypt(cc, dest, src, bytes);
+}
+
+/* Causes any further packets to be encrypted using the given key. The same
+ key is used for both sending and reception. However, both directions
+ are encrypted independently of each other. */
+
+void packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
+ int cipher, int is_client)
+{
+ cipher_type = cipher;
+ if (cipher == SSH_CIPHER_RC4)
+ {
+ if (is_client)
+ { /* In client: use first half for receiving, second for sending. */
+ cipher_set_key(&receive_context, cipher, key, keylen / 2, 0);
+ cipher_set_key(&send_context, cipher, key + keylen / 2,
+ keylen / 2, 1);
+ }
+ else
+ { /* In server: use first half for sending, second for receiving. */
+ cipher_set_key(&receive_context, cipher, key + keylen / 2,
+ keylen / 2, 0);
+ cipher_set_key(&send_context, cipher, key, keylen / 2, 1);
+ }
+ }
+ else
+ {
+ /* All other ciphers use the same key in both directions for now. */
+ cipher_set_key(&receive_context, cipher, key, keylen, 0);
+ cipher_set_key(&send_context, cipher, key, keylen, 1);
+ }
+}
+
+/* Starts constructing a packet to send. */
+
+void packet_start(int type)
+{
+ char buf[9];
+
+ buffer_clear(&outgoing_packet);
+ memset(buf, 0, 8);
+ buf[8] = type;
+ buffer_append(&outgoing_packet, buf, 9);
+}
+
+/* Appends a character to the packet data. */
+
+void packet_put_char(int value)
+{
+ char ch = value;
+ buffer_append(&outgoing_packet, &ch, 1);
+}
+
+/* Appends an integer to the packet data. */
+
+void packet_put_int(unsigned int value)
+{
+ buffer_put_int(&outgoing_packet, value);
+}
+
+/* Appends a string to packet data. */
+
+void packet_put_string(const char *buf, unsigned int len)
+{
+ buffer_put_string(&outgoing_packet, buf, len);
+}
+
+/* Appends an arbitrary precision integer to packet data. */
+
+void packet_put_mp_int(MP_INT *value)
+{
+ buffer_put_mp_int(&outgoing_packet, value);
+}
+
+/* Finalizes and sends the packet. If the encryption key has been set,
+ encrypts the packet before sending. */
+
+void packet_send()
+{
+ char buf[8], *cp;
+ int i, padding, len;
+ unsigned long checksum;
+
+#ifdef WITH_ZLIB
+ /* If using packet compression, compress the payload of the outgoing
+ packet. */
+ if (packet_compression)
+ {
+ buffer_clear(&compression_buffer);
+ buffer_consume(&outgoing_packet, 8); /* Skip padding. */
+ buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); /* padding */
+ buffer_compress(&outgoing_packet, &compression_buffer);
+ buffer_clear(&outgoing_packet);
+ buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),
+ buffer_len(&compression_buffer));
+ }
+#endif /* WITH_ZLIB */
+
+ /* Compute packet length without padding (add checksum, remove padding). */
+ len = buffer_len(&outgoing_packet) + 4 - 8;
+
+ /* Insert padding. */
+ padding = 8 - len % 8;
+ if (cipher_type != SSH_CIPHER_NONE)
+ {
+ cp = buffer_ptr(&outgoing_packet);
+ for (i = 0; i < padding; i++)
+ cp[7 - i] = random_get_byte(random_state);
+ }
+ buffer_consume(&outgoing_packet, 8 - padding);
+
+ /* Add check bytes. */
+ checksum = crc32((unsigned char *)buffer_ptr(&outgoing_packet),
+ buffer_len(&outgoing_packet));
+ PUT_32BIT(buf, checksum);
+ buffer_append(&outgoing_packet, buf, 4);
+
+#ifdef PACKET_DEBUG
+ fprintf(stderr, "packet_send plain: ");
+ buffer_dump(&outgoing_packet);
+#endif
+
+ /* Append to output. */
+ PUT_32BIT(buf, len);
+ buffer_append(&output, buf, 4);
+ buffer_append_space(&output, &cp, buffer_len(&outgoing_packet));
+ packet_encrypt(&send_context, cp, buffer_ptr(&outgoing_packet),
+ buffer_len(&outgoing_packet));
+
+#ifdef PACKET_DEBUG
+ fprintf(stderr, "encrypted: "); buffer_dump(&output);
+#endif
+
+ buffer_clear(&outgoing_packet);
+
+ /* Note that the packet is now only buffered in output. It won\'t be
+ actually sent until packet_write_wait or packet_write_poll is called. */
+}
+
+/* Waits until a packet has been received, and returns its type. Note that
+ no other data is processed until this returns, so this function should
+ not be used during the interactive session. */
+
+int packet_read(int *payload_len_ptr)
+{
+ int type, len;
+ fd_set set;
+ char buf[8192];
+
+ /* Since we are blocking, ensure that all written packets have been sent. */
+ packet_write_wait();
+
+ /* Stay in the loop until we have received a complete packet. */
+ for (;;)
+ {
+ /* Try to read a packet from the buffer. */
+ type = packet_read_poll(payload_len_ptr);
+ if (type == SSH_SMSG_SUCCESS
+ || type == SSH_SMSG_FAILURE
+ || type == SSH_CMSG_EOF
+ || type == SSH_CMSG_EXIT_CONFIRMATION)
+ packet_integrity_check(*payload_len_ptr, 0, type);
+ /* If we got a packet, return it. */
+ if (type != SSH_MSG_NONE)
+ return type;
+ /* Otherwise, wait for some data to arrive, add it to the buffer,
+ and try again. */
+ FD_ZERO(&set);
+ FD_SET(connection_in, &set);
+ /* Wait for some data to arrive. */
+ select(connection_in + 1, &set, NULL, NULL, NULL);
+ /* Read data from the socket. */
+ len = read(connection_in, buf, sizeof(buf));
+ if (len == 0)
+ fatal("Connection closed by remote host.");
+ if (len < 0)
+ fatal("Read from socket failed: %.100s", strerror(errno));
+ /* Append it to the buffer. */
+ packet_process_incoming(buf, len);
+ }
+ /*NOTREACHED*/
+}
+
+/* Waits until a packet has been received, verifies that its type matches
+ that given, and gives a fatal error and exits if there is a mismatch. */
+
+void packet_read_expect(int *payload_len_ptr, int expected_type)
+{
+ int type;
+
+ type = packet_read(payload_len_ptr);
+ if (type != expected_type)
+ packet_disconnect("Protocol error: expected packet type %d, got %d",
+ expected_type, type);
+}
+
+/* Checks if a full packet is available in the data received so far via
+ packet_process_incoming. If so, reads the packet; otherwise returns
+ SSH_MSG_NONE. This does not wait for data from the connection.
+
+ SSH_MSG_DISCONNECT is handled specially here. Also,
+ SSH_MSG_IGNORE messages are skipped by this function and are never returned
+ to higher levels.
+
+ The returned payload_len does include space consumed by:
+ Packet length
+ Padding
+ Packet type
+ Check bytes
+
+
+ */
+
+int packet_read_poll(int *payload_len_ptr)
+{
+ unsigned int len, padded_len;
+ unsigned char *ucp;
+ char buf[8], *cp;
+ unsigned long checksum, stored_checksum;
+
+ restart:
+
+ /* Check if input size is less than minimum packet size. */
+ if (buffer_len(&input) < 4 + 8)
+ return SSH_MSG_NONE;
+ /* Get length of incoming packet. */
+ ucp = (unsigned char *)buffer_ptr(&input);
+ len = GET_32BIT(ucp);
+ if (len < 1 + 2 + 2 || len > 256*1024)
+ packet_disconnect("Bad packet length %d.", len);
+ padded_len = (len + 8) & ~7;
+
+ /* Check if the packet has been entirely received. */
+ if (buffer_len(&input) < 4 + padded_len)
+ return SSH_MSG_NONE;
+
+ /* The entire packet is in buffer. */
+
+ /* Consume packet length. */
+ buffer_consume(&input, 4);
+
+ /* Copy data to incoming_packet. */
+ buffer_clear(&incoming_packet);
+ buffer_append_space(&incoming_packet, &cp, padded_len);
+ packet_decrypt(&receive_context, cp, buffer_ptr(&input), padded_len);
+ buffer_consume(&input, padded_len);
+
+#ifdef PACKET_DEBUG
+ fprintf(stderr, "read_poll plain: "); buffer_dump(&incoming_packet);
+#endif
+
+ /* Compute packet checksum. */
+ checksum = crc32((unsigned char *)buffer_ptr(&incoming_packet),
+ buffer_len(&incoming_packet) - 4);
+
+ /* Skip padding. */
+ buffer_consume(&incoming_packet, 8 - len % 8);
+
+ /* Test check bytes. */
+ assert(len == buffer_len(&incoming_packet));
+ ucp = (unsigned char *)buffer_ptr(&incoming_packet) + len - 4;
+ stored_checksum = GET_32BIT(ucp);
+ if (checksum != stored_checksum)
+ packet_disconnect("Corrupted check bytes on input.");
+ buffer_consume_end(&incoming_packet, 4);
+
+#ifdef WITH_ZLIB
+ /* If using packet compression, decompress the packet. */
+ if (packet_compression)
+ {
+ buffer_clear(&compression_buffer);
+ buffer_uncompress(&incoming_packet, &compression_buffer);
+ buffer_clear(&incoming_packet);
+ buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),
+ buffer_len(&compression_buffer));
+ }
+#endif /* WITH_ZLIB */
+
+ /* Get packet type. */
+ buffer_get(&incoming_packet, &buf[0], 1);
+
+ /* Return length of payload (without type field). */
+ *payload_len_ptr = buffer_len(&incoming_packet);
+
+ /* Handle disconnect message. */
+ if ((unsigned char)buf[0] == SSH_MSG_DISCONNECT)
+ fatal("%.900s", packet_get_string(NULL));
+
+ /* Ignore ignore messages. */
+ if ((unsigned char)buf[0] == SSH_MSG_IGNORE)
+ goto restart;
+
+ /* Send debug messages as debugging output. */
+ if ((unsigned char)buf[0] == SSH_MSG_DEBUG)
+ {
+ debug("Remote: %.900s", packet_get_string(NULL));
+ goto restart;
+ }
+
+ /* Return type. */
+ return (unsigned char)buf[0];
+}
+
+/* Buffers the given amount of input characters. This is intended to be
+ used together with packet_read_poll. */
+
+void packet_process_incoming(const char *buf, unsigned int len)
+{
+ buffer_append(&input, buf, len);
+}
+
+/* Returns a character from the packet. */
+
+unsigned int packet_get_char()
+{
+ char ch;
+ buffer_get(&incoming_packet, &ch, 1);
+ return (unsigned char)ch;
+}
+
+/* Returns an integer from the packet data. */
+
+unsigned int packet_get_int()
+{
+ return buffer_get_int(&incoming_packet);
+}
+
+/* Returns an arbitrary precision integer from the packet data. The integer
+ must have been initialized before this call. */
+
+void packet_get_mp_int(MP_INT *value, int *length_ptr)
+{
+ *length_ptr = buffer_get_mp_int(&incoming_packet, value);
+}
+
+/* Returns a string from the packet data. The string is allocated using
+ xmalloc; it is the responsibility of the calling program to free it when
+ no longer needed. The length_ptr argument may be NULL, or point to an
+ integer into which the length of the string is stored. */
+
+char *packet_get_string(unsigned int *length_ptr)
+{
+ return buffer_get_string(&incoming_packet, length_ptr);
+}
+
+/* Sends a diagnostic message from the server to the client. This message
+ can be sent at any time (but not while constructing another message).
+ The message is printed immediately, but only if the client is being
+ executed in verbose mode. These messages are primarily intended to
+ ease debugging authentication problems. The length of the formatted
+ message must not exceed 1024 bytes. This will automatically call
+ packet_write_wait. */
+
+void packet_send_debug(const char *fmt, ...)
+{
+ char buf[1024];
+ va_list args;
+
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ packet_start(SSH_MSG_DEBUG);
+ packet_put_string(buf, strlen(buf));
+ packet_send();
+ packet_write_wait();
+}
+
+/* Logs the error plus constructs and sends a disconnect
+ packet, closes the connection, and exits. This function never returns.
+ The error message should not contain a newline. The length of the
+ formatted message must not exceed 1024 bytes. */
+
+void packet_disconnect(const char *fmt, ...)
+{
+ char buf[1024];
+ va_list args;
+ static int disconnecting = 0;
+ if (disconnecting) /* Guard against recursive invocations. */
+ fatal("packet_disconnect called recursively.");
+ disconnecting = 1;
+
+ /* Format the message. Note that the caller must make sure the message
+ is of limited size. */
+ va_start(args, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ /* Send the disconnect message to the other side, and wait for it to get
+ sent. */
+ packet_start(SSH_MSG_DISCONNECT);
+ packet_put_string(buf, strlen(buf));
+ packet_send();
+ packet_write_wait();
+
+ /* Stop listening for connections. */
+ channel_stop_listening();
+
+ /* Close the connection. */
+ packet_close();
+
+ /* Display the error locally and exit. */
+ fatal("Local: %.100s", buf);
+}
+
+/* Checks if there is any buffered output, and tries to write some of the
+ output. */
+
+void packet_write_poll()
+{
+ int len = buffer_len(&output);
+ if (len > 0)
+ {
+ len = write(connection_out, buffer_ptr(&output), len);
+ if (len <= 0)
+ if (errno == EAGAIN)
+ return;
+ else
+ fatal("Write failed: %.100s", strerror(errno));
+ buffer_consume(&output, len);
+ }
+}
+
+/* Calls packet_write_poll repeatedly until all pending output data has
+ been written. */
+
+void packet_write_wait()
+{
+ packet_write_poll();
+ while (packet_have_data_to_write())
+ {
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(connection_out, &set);
+ select(connection_out + 1, NULL, &set, NULL, NULL);
+ packet_write_poll();
+ }
+}
+
+/* Returns true if there is buffered data to write to the connection. */
+
+int packet_have_data_to_write()
+{
+ return buffer_len(&output) != 0;
+}
+
+/* Returns true if there is not too much data to write to the connection. */
+
+int packet_not_very_much_data_to_write()
+{
+ if (interactive_mode)
+ return buffer_len(&output) < 16384;
+ else
+ return buffer_len(&output) < 128*1024;
+}
+
+/* Informs that the current session is interactive. Sets IP flags for that. */
+
+void packet_set_interactive(int interactive, int keepalives)
+{
+ int on = 1;
+
+ /* Record that we are in interactive mode. */
+ interactive_mode = interactive;
+
+ /* Only set socket options if using a socket (as indicated by the descriptors
+ being the same). */
+ if (connection_in != connection_out)
+ return;
+
+ if (keepalives)
+ {
+ /* Set keepalives if requested. */
+ if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
+ sizeof(on)) < 0)
+ error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
+ }
+
+ if (interactive)
+ {
+ /* Set IP options for an interactive connection. Use IPTOS_LOWDELAY
+ and TCP_NODELAY. */
+#ifdef IPTOS_LOWDELAY
+ int lowdelay = IPTOS_LOWDELAY;
+ if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&lowdelay,
+ sizeof(lowdelay)) < 0)
+ error("setsockopt IPTOS_LOWDELAY: %.100s", strerror(errno));
+#endif /* IPTOS_LOWDELAY */
+ if (setsockopt(connection_in, IPPROTO_TCP, TCP_NODELAY, (void *)&on,
+ sizeof(on)) < 0)
+ error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
+ }
+ else
+ {
+ /* Set IP options for a non-interactive connection. Use
+ IPTOS_THROUGHPUT. */
+#ifdef IPTOS_THROUGHPUT
+ int throughput = IPTOS_THROUGHPUT;
+ if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *)&throughput,
+ sizeof(throughput)) < 0)
+ error("setsockopt IPTOS_THROUGHPUT: %.100s", strerror(errno));
+#endif /* IPTOS_THROUGHPUT */
+ }
+}
+
+/* Returns true if the current connection is interactive. */
+
+int packet_is_interactive()
+{
+ return interactive_mode;
+}
diff --git a/usr.bin/ssh/packet.h b/usr.bin/ssh/packet.h
new file mode 100644
index 00000000000..9a39bb9b637
--- /dev/null
+++ b/usr.bin/ssh/packet.h
@@ -0,0 +1,167 @@
+/*
+
+packet.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 18 02:02:14 1995 ylo
+
+Interface for the packet protocol functions.
+
+*/
+
+/* RCSID("$Id: packet.h,v 1.1 1999/09/26 20:53:36 deraadt Exp $"); */
+
+#ifndef PACKET_H
+#define PACKET_H
+
+#include <gmp.h>
+#include "randoms.h"
+
+/* Sets the socket used for communication. Disables encryption until
+ packet_set_encryption_key is called. It is permissible that fd_in
+ and fd_out are the same descriptor; in that case it is assumed to
+ be a socket. */
+void packet_set_connection(int fd_in, int fd_out, RandomState *state);
+
+/* Puts the connection file descriptors into non-blocking mode. */
+void packet_set_nonblocking(void);
+
+/* Returns the file descriptor used for input. */
+int packet_get_connection_in(void);
+
+/* Returns the file descriptor used for output. */
+int packet_get_connection_out(void);
+
+/* Closes the connection (both descriptors) and clears and frees
+ internal data structures. */
+void packet_close(void);
+
+/* Causes any further packets to be encrypted using the given key. The same
+ key is used for both sending and reception. However, both directions
+ are encrypted independently of each other. Cipher types are
+ defined in ssh.h. */
+void packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
+ int cipher_type, int is_client);
+
+/* Sets remote side protocol flags for the current connection. This can
+ be called at any time. */
+void packet_set_protocol_flags(unsigned int flags);
+
+/* Returns the remote protocol flags set earlier by the above function. */
+unsigned int packet_get_protocol_flags(void);
+
+/* Enables compression in both directions starting from the next packet. */
+void packet_start_compression(int level);
+
+/* Informs that the current session is interactive. Sets IP flags for optimal
+ performance in interactive use. */
+void packet_set_interactive(int interactive, int keepalives);
+
+/* Returns true if the current connection is interactive. */
+int packet_is_interactive(void);
+
+/* Starts constructing a packet to send. */
+void packet_start(int type);
+
+/* Appends a character to the packet data. */
+void packet_put_char(int ch);
+
+/* Appends an integer to the packet data. */
+void packet_put_int(unsigned int value);
+
+/* Appends an arbitrary precision integer to packet data. */
+void packet_put_mp_int(MP_INT *value);
+
+/* Appends a string to packet data. */
+void packet_put_string(const char *buf, unsigned int len);
+
+/* Finalizes and sends the packet. If the encryption key has been set,
+ encrypts the packet before sending. */
+void packet_send(void);
+
+/* Waits until a packet has been received, and returns its type. */
+int packet_read(int *payload_len_ptr);
+
+/* Waits until a packet has been received, verifies that its type matches
+ that given, and gives a fatal error and exits if there is a mismatch. */
+void packet_read_expect(int *payload_len_ptr, int type);
+
+/* Checks if a full packet is available in the data received so far via
+ packet_process_incoming. If so, reads the packet; otherwise returns
+ SSH_MSG_NONE. This does not wait for data from the connection.
+
+ SSH_MSG_DISCONNECT is handled specially here. Also,
+ SSH_MSG_IGNORE messages are skipped by this function and are never returned
+ to higher levels. */
+int packet_read_poll(int *packet_len_ptr);
+
+/* Buffers the given amount of input characters. This is intended to be
+ used together with packet_read_poll. */
+void packet_process_incoming(const char *buf, unsigned int len);
+
+/* Returns a character (0-255) from the packet data. */
+unsigned int packet_get_char(void);
+
+/* Returns an integer from the packet data. */
+unsigned int packet_get_int(void);
+
+/* Returns an arbitrary precision integer from the packet data. The integer
+ must have been initialized before this call. */
+void packet_get_mp_int(MP_INT *value, int *length_ptr);
+
+/* Returns a string from the packet data. The string is allocated using
+ xmalloc; it is the responsibility of the calling program to free it when
+ no longer needed. The length_ptr argument may be NULL, or point to an
+ integer into which the length of the string is stored. */
+char *packet_get_string(unsigned int *length_ptr);
+
+/* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
+ packet, closes the connection, and exits. This function never returns.
+ The error message should not contain a newline. The total length of the
+ message must not exceed 1024 bytes. */
+void packet_disconnect(const char *fmt, ...);
+
+/* Sends a diagnostic message to the other side. This message
+ can be sent at any time (but not while constructing another message).
+ The message is printed immediately, but only if the client is being
+ executed in verbose mode. These messages are primarily intended to
+ ease debugging authentication problems. The total length of the message
+ must not exceed 1024 bytes. This will automatically call
+ packet_write_wait. If the remote side protocol flags do not indicate
+ that it supports SSH_MSG_DEBUG, this will do nothing. */
+void packet_send_debug(const char *fmt, ...);
+
+/* Checks if there is any buffered output, and tries to write some of the
+ output. */
+void packet_write_poll(void);
+
+/* Waits until all pending output data has been written. */
+void packet_write_wait(void);
+
+/* Returns true if there is buffered data to write to the connection. */
+int packet_have_data_to_write(void);
+
+/* Returns true if there is not too much data to write to the connection. */
+int packet_not_very_much_data_to_write(void);
+
+/* Stores tty modes from the fd into current packet. */
+void tty_make_modes(int fd);
+
+/* Parses tty modes for the fd from the current packet. */
+void tty_parse_modes(int fd, int *n_bytes_ptr);
+
+#define packet_integrity_check(payload_len, expected_len, type) \
+do { \
+ int _p = (payload_len), _e = (expected_len); \
+ if (_p != _e) { \
+ log("Packet integrity error (%d != %d) at %s:%d", \
+ _p, _e, __FILE__, __LINE__); \
+ packet_disconnect("Packet integrity error. (%d)", (type)); \
+ } \
+} while (0)
+
+#endif /* PACKET_H */
diff --git a/usr.bin/ssh/pty.c b/usr.bin/ssh/pty.c
new file mode 100644
index 00000000000..189c570bcbf
--- /dev/null
+++ b/usr.bin/ssh/pty.c
@@ -0,0 +1,313 @@
+/*
+
+pty.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Fri Mar 17 04:37:25 1995 ylo
+
+Allocating a pseudo-terminal, and making it the controlling tty.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: pty.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include "pty.h"
+#include "ssh.h"
+
+/* Pty allocated with _getpty gets broken if we do I_PUSH:es to it. */
+#if defined(HAVE__GETPTY) || defined(HAVE_OPENPTY)
+#undef HAVE_DEV_PTMX
+#endif
+
+#ifdef HAVE_DEV_PTMX
+#include <sys/stream.h>
+#include <stropts.h>
+#include <sys/conf.h>
+#endif /* HAVE_DEV_PTMX */
+
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
+/* Allocates and opens a pty. Returns 0 if no pty could be allocated,
+ or nonzero if a pty was successfully allocated. On success, open file
+ descriptors for the pty and tty sides and the name of the tty side are
+ returned (the buffer must be able to hold at least 64 characters). */
+
+int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
+{
+#ifdef HAVE_OPENPTY
+
+ /* openpty(3) exists in OSF/1 and some other os'es */
+
+ int i;
+
+ i = openpty(ptyfd, ttyfd, namebuf, NULL, NULL);
+
+ if (i < 0)
+ {
+ error("openpty: %.100s", strerror(errno));
+ return 0;
+ }
+
+ return 1;
+
+#else /* HAVE_OPENPTY */
+#ifdef HAVE__GETPTY
+
+ /* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
+ pty's automagically when needed */
+
+ char *slave;
+
+ slave = _getpty(ptyfd, O_RDWR, 0622, 0);
+ if (slave == NULL)
+ {
+ error("_getpty: %.100s", strerror(errno));
+ return 0;
+ }
+ strcpy(namebuf, slave);
+ /* Open the slave side. */
+ *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
+ if (*ttyfd < 0)
+ {
+ error("%.200s: %.100s", namebuf, strerror(errno));
+ close(*ptyfd);
+ return 0;
+ }
+ return 1;
+
+#else /* HAVE__GETPTY */
+#ifdef HAVE_DEV_PTMX
+ /* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3 also has
+ bsd-style ptys, but they simply do not work.) */
+
+ int ptm;
+ char *pts;
+
+ ptm = open("/dev/ptmx", O_RDWR|O_NOCTTY);
+ if (ptm < 0)
+ {
+ error("/dev/ptmx: %.100s", strerror(errno));
+ return 0;
+ }
+ if (grantpt(ptm) < 0)
+ {
+ error("grantpt: %.100s", strerror(errno));
+ return 0;
+ }
+ if (unlockpt(ptm) < 0)
+ {
+ error("unlockpt: %.100s", strerror(errno));
+ return 0;
+ }
+ pts = ptsname(ptm);
+ if (pts == NULL)
+ error("Slave pty side name could not be obtained.");
+ strcpy(namebuf, pts);
+ *ptyfd = ptm;
+
+ /* Open the slave side. */
+ *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
+ if (*ttyfd < 0)
+ {
+ error("%.100s: %.100s", namebuf, strerror(errno));
+ close(*ptyfd);
+ return 0;
+ }
+ /* Push the appropriate streams modules, as described in Solaris pts(7). */
+ if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
+ error("ioctl I_PUSH ptem: %.100s", strerror(errno));
+ if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
+ error("ioctl I_PUSH ldterm: %.100s", strerror(errno));
+ if (ioctl(*ttyfd, I_PUSH, "ttcompat") < 0)
+ error("ioctl I_PUSH ttcompat: %.100s", strerror(errno));
+ return 1;
+
+#else /* HAVE_DEV_PTMX */
+#ifdef HAVE_DEV_PTS_AND_PTC
+
+ /* AIX-style pty code. */
+
+ const char *name;
+
+ *ptyfd = open("/dev/ptc", O_RDWR|O_NOCTTY);
+ if (*ptyfd < 0)
+ {
+ error("Could not open /dev/ptc: %.100s", strerror(errno));
+ return 0;
+ }
+ name = ttyname(*ptyfd);
+ if (!name)
+ fatal("Open of /dev/ptc returns device for which ttyname fails.");
+ strcpy(namebuf, name);
+ *ttyfd = open(name, O_RDWR|O_NOCTTY);
+ if (*ttyfd < 0)
+ {
+ error("Could not open pty slave side %.100s: %.100s",
+ name, strerror(errno));
+ close(*ptyfd);
+ return 0;
+ }
+ return 1;
+
+#else /* HAVE_DEV_PTS_AND_PTC */
+#ifdef CRAY
+ char buf[64];
+ int i;
+
+ for (i = 0; i < 128; i++)
+ {
+ sprintf(buf, "/dev/pty/%03d", i);
+ *ptyfd = open(buf, O_RDWR|O_NOCTTY);
+ if (*ptyfd < 0)
+ continue;
+ sprintf(namebuf, "/dev/ttyp%03d", i);
+ /* Open the slave side. */
+ *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
+ if (*ttyfd < 0)
+ {
+ error("%.100s: %.100s", namebuf, strerror(errno));
+ close(*ptyfd);
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+
+#else /* CRAY */
+
+ /* BSD-style pty code. */
+
+ char buf[64];
+ int i;
+ const char *ptymajors =
+ "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const char *ptyminors = "0123456789abcdef";
+ int num_minors = strlen(ptyminors);
+ int num_ptys = strlen(ptymajors) * num_minors;
+
+ for (i = 0; i < num_ptys; i++)
+ {
+ sprintf(buf, "/dev/pty%c%c", ptymajors[i / num_minors],
+ ptyminors[i % num_minors]);
+ *ptyfd = open(buf, O_RDWR|O_NOCTTY);
+ if (*ptyfd < 0)
+ continue;
+ sprintf(namebuf, "/dev/tty%c%c", ptymajors[i / num_minors],
+ ptyminors[i % num_minors]);
+
+ /* Open the slave side. */
+ *ttyfd = open(namebuf, O_RDWR|O_NOCTTY);
+ if (*ttyfd < 0)
+ {
+ error("%.100s: %.100s", namebuf, strerror(errno));
+ close(*ptyfd);
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+#endif /* CRAY */
+#endif /* HAVE_DEV_PTS_AND_PTC */
+#endif /* HAVE_DEV_PTMX */
+#endif /* HAVE__GETPTY */
+#endif /* HAVE_OPENPTY */
+}
+
+/* Releases the tty. Its ownership is returned to root, and permissions to
+ 0666. */
+
+void pty_release(const char *ttyname)
+{
+ if (chown(ttyname, (uid_t)0, (gid_t)0) < 0)
+ debug("chown %.100s 0 0 failed: %.100s", ttyname, strerror(errno));
+ if (chmod(ttyname, (mode_t)0666) < 0)
+ debug("chmod %.100s 0666 failed: %.100s", ttyname, strerror(errno));
+}
+
+/* Makes the tty the processes controlling tty and sets it to sane modes. */
+
+void pty_make_controlling_tty(int *ttyfd, const char *ttyname)
+{
+ int fd;
+
+ /* First disconnect from the old controlling tty. */
+#ifdef TIOCNOTTY
+ fd = open("/dev/tty", O_RDWR|O_NOCTTY);
+ if (fd >= 0)
+ {
+ (void)ioctl(fd, TIOCNOTTY, NULL);
+ close(fd);
+ }
+#endif /* TIOCNOTTY */
+#ifdef HAVE_SETSID
+#ifdef ultrix
+ setpgrp(0, 0);
+#else /* ultrix */
+ if (setsid() < 0)
+ error("setsid: %.100s", strerror(errno));
+#endif /* ultrix */
+#endif /* HAVE_SETSID */
+
+ /* Verify that we are successfully disconnected from the controlling tty. */
+ fd = open("/dev/tty", O_RDWR|O_NOCTTY);
+ if (fd >= 0)
+ {
+ error("Failed to disconnect from controlling tty.");
+ close(fd);
+ }
+
+ /* Make it our controlling tty. */
+#ifdef TIOCSCTTY
+ debug("Setting controlling tty using TIOCSCTTY.");
+ /* We ignore errors from this, because HPSUX defines TIOCSCTTY, but returns
+ EINVAL with these arguments, and there is absolutely no documentation. */
+ ioctl(*ttyfd, TIOCSCTTY, NULL);
+#endif /* TIOCSCTTY */
+ fd = open(ttyname, O_RDWR);
+ if (fd < 0)
+ error("%.100s: %.100s", ttyname, strerror(errno));
+ else
+ close(fd);
+
+ /* Verify that we now have a controlling tty. */
+ fd = open("/dev/tty", O_WRONLY);
+ if (fd < 0)
+ error("open /dev/tty failed - could not set controlling tty: %.100s",
+ strerror(errno));
+ else
+ {
+ close(fd);
+#ifdef HAVE_VHANGUP
+ signal(SIGHUP, SIG_IGN);
+ vhangup();
+ signal(SIGHUP, SIG_DFL);
+ fd = open(ttyname, O_RDWR);
+ if (fd == -1)
+ error("pty_make_controlling_tty: reopening controlling tty after vhangup failed for %.100s",
+ ttyname);
+ close(*ttyfd);
+ *ttyfd = fd;
+#endif /* HAVE_VHANGUP */
+ }
+}
+
+/* Changes the window size associated with the pty. */
+
+void pty_change_window_size(int ptyfd, int row, int col,
+ int xpixel, int ypixel)
+{
+ struct winsize w;
+ w.ws_row = row;
+ w.ws_col = col;
+ w.ws_xpixel = xpixel;
+ w.ws_ypixel = ypixel;
+ (void)ioctl(ptyfd, TIOCSWINSZ, &w);
+}
+
diff --git a/usr.bin/ssh/pty.h b/usr.bin/ssh/pty.h
new file mode 100644
index 00000000000..c88ae92718c
--- /dev/null
+++ b/usr.bin/ssh/pty.h
@@ -0,0 +1,40 @@
+/*
+
+pty.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Fri Mar 17 05:03:28 1995 ylo
+
+Functions for allocating a pseudo-terminal and making it the controlling
+tty.
+
+*/
+
+/* RCSID("$Id: pty.h,v 1.1 1999/09/26 20:53:36 deraadt Exp $"); */
+
+#ifndef PTY_H
+#define PTY_H
+
+/* Allocates and opens a pty. Returns 0 if no pty could be allocated,
+ or nonzero if a pty was successfully allocated. On success, open file
+ descriptors for the pty and tty sides and the name of the tty side are
+ returned (the buffer must be able to hold at least 64 characters). */
+int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname);
+
+/* Releases the tty. Its ownership is returned to root, and permissions to
+ 0666. */
+void pty_release(const char *ttyname);
+
+/* Makes the tty the processes controlling tty and sets it to sane modes.
+ This may need to reopen the tty to get rid of possible eavesdroppers. */
+void pty_make_controlling_tty(int *ttyfd, const char *ttyname);
+
+/* Changes the window size associated with the pty. */
+void pty_change_window_size(int ptyfd, int row, int col,
+ int xpixel, int ypixel);
+
+#endif /* PTY_H */
diff --git a/usr.bin/ssh/radix.c b/usr.bin/ssh/radix.c
new file mode 100644
index 00000000000..ca1b82a72db
--- /dev/null
+++ b/usr.bin/ssh/radix.c
@@ -0,0 +1,259 @@
+/*
+ radix.c
+
+ base-64 encoding pinched from lynx2-7-2, who pinched it from rpem.
+ Originally written by Mark Riordan 12 August 1990 and 17 Feb 1991
+ and placed in the public domain.
+
+ dugsong@UMICH.EDU
+*/
+
+#include "includes.h"
+
+#ifdef AFS
+#include <krb.h>
+#include <kafs.h>
+
+char six2pr[64] = {
+ 'A','B','C','D','E','F','G','H','I','J','K','L','M',
+ 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
+ 'a','b','c','d','e','f','g','h','i','j','k','l','m',
+ 'n','o','p','q','r','s','t','u','v','w','x','y','z',
+ '0','1','2','3','4','5','6','7','8','9','+','/'
+};
+
+unsigned char pr2six[256];
+
+int uuencode(unsigned char *bufin, unsigned int nbytes, char *bufcoded)
+{
+ /* ENC is the basic 1 character encoding function to make a char printing */
+#define ENC(c) six2pr[c]
+
+ register char *outptr = bufcoded;
+ unsigned int i;
+
+ for (i=0; i<nbytes; i += 3) {
+ *(outptr++) = ENC(*bufin >> 2); /* c1 */
+ *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /*c2*/
+ *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03));/*c3*/
+ *(outptr++) = ENC(bufin[2] & 077); /* c4 */
+ bufin += 3;
+ }
+ if (i == nbytes+1) {
+ outptr[-1] = '=';
+ } else if (i == nbytes+2) {
+ outptr[-1] = '=';
+ outptr[-2] = '=';
+ }
+ *outptr = '\0';
+ return(outptr - bufcoded);
+}
+
+int uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
+{
+ /* single character decode */
+#define DEC(c) pr2six[c]
+#define MAXVAL 63
+
+ static int first = 1;
+ int nbytesdecoded, j;
+ const char *bufin = bufcoded;
+ register unsigned char *bufout = bufplain;
+ register int nprbytes;
+
+ /* If this is the first call, initialize the mapping table. */
+ if (first) {
+ first = 0;
+ for(j=0; j<256; j++) pr2six[j] = MAXVAL+1;
+ for(j=0; j<64; j++) pr2six[(unsigned char)six2pr[j]] = (unsigned char)j;
+ }
+
+ /* Strip leading whitespace. */
+ while (*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
+
+ /* Figure out how many characters are in the input buffer.
+ If this would decode into more bytes than would fit into
+ the output buffer, adjust the number of input bytes downwards. */
+ bufin = bufcoded;
+ while (pr2six[(unsigned char)*(bufin++)] <= MAXVAL);
+ nprbytes = bufin - bufcoded - 1;
+ nbytesdecoded = ((nprbytes+3)/4) * 3;
+ if (nbytesdecoded > outbufsize)
+ nprbytes = (outbufsize*4)/3;
+
+ bufin = bufcoded;
+
+ while (nprbytes > 0) {
+ *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4);
+ *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2);
+ *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3]));
+ bufin += 4;
+ nprbytes -= 4;
+ }
+ if (nprbytes & 03) {
+ if (pr2six[bufin[-2]] > MAXVAL)
+ nbytesdecoded -= 2;
+ else
+ nbytesdecoded -= 1;
+ }
+ return(nbytesdecoded);
+}
+
+typedef unsigned char my_u_char;
+typedef unsigned int my_u_int32_t;
+typedef unsigned short my_u_short;
+
+/* Nasty macros from BIND-4.9.2 */
+
+#define GETSHORT(s, cp) { \
+ register my_u_char *t_cp = (my_u_char*)(cp); \
+ (s) = (((my_u_short)t_cp[0]) << 8) \
+ | (((my_u_short)t_cp[1])) \
+ ; \
+ (cp) += 2; \
+}
+
+#define GETLONG(l, cp) { \
+ register my_u_char *t_cp = (my_u_char*)(cp); \
+ (l) = (((my_u_int32_t)t_cp[0]) << 24) \
+ | (((my_u_int32_t)t_cp[1]) << 16) \
+ | (((my_u_int32_t)t_cp[2]) << 8) \
+ | (((my_u_int32_t)t_cp[3])) \
+ ; \
+ (cp) += 4; \
+}
+
+#define PUTSHORT(s, cp) { \
+ register my_u_short t_s = (my_u_short)(s); \
+ register my_u_char *t_cp = (my_u_char*)(cp); \
+ *t_cp++ = t_s >> 8; \
+ *t_cp = t_s; \
+ (cp) += 2; \
+}
+
+#define PUTLONG(l, cp) { \
+ register my_u_int32_t t_l = (my_u_int32_t)(l); \
+ register my_u_char *t_cp = (my_u_char*)(cp); \
+ *t_cp++ = t_l >> 24; \
+ *t_cp++ = t_l >> 16; \
+ *t_cp++ = t_l >> 8; \
+ *t_cp = t_l; \
+ (cp) += 4; \
+}
+
+#define GETSTRING(s, p, p_l) { \
+ register char* p_targ = (p) + p_l; \
+ register char* s_c = (s); \
+ register char* p_c = (p); \
+ while (*p_c && (p_c < p_targ)) { \
+ *s_c++ = *p_c++; \
+ } \
+ if (p_c == p_targ) { \
+ return 1; \
+ } \
+ *s_c = *p_c++; \
+ (p_l) = (p_l) - (p_c - (p)); \
+ (p) = p_c; \
+}
+
+
+int creds_to_radix(CREDENTIALS *creds, unsigned char *buf)
+{
+ char *p, *s;
+ int len;
+ char temp[2048];
+
+ p = temp;
+ *p++ = 1; /* version */
+ s = creds->service; while (*s) *p++ = *s++; *p++ = *s;
+ s = creds->instance; while (*s) *p++ = *s++; *p++ = *s;
+ s = creds->realm; while (*s) *p++ = *s++; *p++ = *s;
+
+ s = creds->pname; while (*s) *p++ = *s++; *p++ = *s;
+ s = creds->pinst; while (*s) *p++ = *s++; *p++ = *s;
+ /* Null string to repeat the realm. */
+ *p++ = '\0';
+
+ PUTLONG(creds->issue_date,p);
+ {
+ unsigned long endTime ;
+ endTime = (unsigned long)krb_life_to_time(creds->issue_date,
+ creds->lifetime);
+ PUTLONG(endTime,p);
+ }
+
+ memcpy(p,&creds->session, sizeof(creds->session));
+ p += sizeof(creds->session);
+
+ PUTSHORT(creds->kvno,p);
+ PUTLONG(creds->ticket_st.length,p);
+
+ memcpy(p,creds->ticket_st.dat, creds->ticket_st.length);
+ p += creds->ticket_st.length;
+ len = p - temp;
+
+ return(uuencode(temp, len, buf));
+}
+
+int radix_to_creds(const char *buf, CREDENTIALS *creds)
+{
+
+ char *p;
+ int len, tl;
+ char version;
+ char temp[2048];
+
+ if (!(len = uudecode(buf, temp, sizeof(temp))))
+ return 0;
+
+ p = temp;
+
+ /* check version and length! */
+ if (len < 1) return 0;
+ version = *p; p++; len--;
+
+ GETSTRING(creds->service, p, len);
+ GETSTRING(creds->instance, p, len);
+ GETSTRING(creds->realm, p, len);
+
+ GETSTRING(creds->pname, p, len);
+ GETSTRING(creds->pinst, p, len);
+ /* Ignore possibly different realm. */
+ while (*p && len) p++, len--;
+ if (len == 0) return 0;
+ p++, len--;
+
+ /* Enough space for remaining fixed-length parts? */
+ if (len < (4 + 4 + sizeof(creds->session) + 2 + 4))
+ return 0;
+
+ GETLONG(creds->issue_date,p);
+ len -= 4;
+ {
+ unsigned long endTime;
+ GETLONG(endTime,p);
+ len -= 4;
+ creds->lifetime = krb_time_to_life(creds->issue_date, endTime);
+ }
+
+ memcpy(&creds->session, p, sizeof(creds->session));
+ p += sizeof(creds->session);
+ len -= sizeof(creds->session);
+
+ GETSHORT(creds->kvno,p);
+ len -= 2;
+ GETLONG(creds->ticket_st.length,p);
+ len -= 4;
+
+ tl = creds->ticket_st.length;
+ if (tl < 0 || tl > len || tl > sizeof(creds->ticket_st.dat))
+ return 0;
+
+ memcpy(creds->ticket_st.dat, p, tl);
+ p += tl;
+ len -= tl;
+
+ return 1;
+}
+
+#endif /* AFS */
diff --git a/usr.bin/ssh/random.c b/usr.bin/ssh/random.c
new file mode 100644
index 00000000000..1487764601b
--- /dev/null
+++ b/usr.bin/ssh/random.c
@@ -0,0 +1,370 @@
+/* Note: file is included because gmp uses functions that use random in its
+ primality testing functions. //ylo */
+
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)random.c 5.9 (Berkeley) 2/23/91";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+/*
+ * random.c:
+ *
+ * An improved random number generation package. In addition to the standard
+ * rand()/srand() like interface, this package also has a special state info
+ * interface. The initstate() routine is called with a seed, an array of
+ * bytes, and a count of how many bytes are being passed in; this array is
+ * then initialized to contain information for random number generation with
+ * that much state information. Good sizes for the amount of state
+ * information are 32, 64, 128, and 256 bytes. The state can be switched by
+ * calling the setstate() routine with the same array as was initiallized
+ * with initstate(). By default, the package runs with 128 bytes of state
+ * information and generates far better random numbers than a linear
+ * congruential generator. If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used.
+ *
+ * Internally, the state information is treated as an array of longs; the
+ * zeroeth element of the array is the type of R.N.G. being used (small
+ * integer); the remainder of the array is the state information for the
+ * R.N.G. Thus, 32 bytes of state information will give 7 longs worth of
+ * state information, which will allow a degree seven polynomial. (Note:
+ * the zeroeth word of state information also has some other information
+ * stored in it -- see setstate() for details).
+ *
+ * The random number generation technique is a linear feedback shift register
+ * approach, employing trinomials (since there are fewer terms to sum up that
+ * way). In this approach, the least significant bit of all the numbers in
+ * the state table will act as a linear feedback shift register, and will
+ * have period 2^deg - 1 (where deg is the degree of the polynomial being
+ * used, assuming that the polynomial is irreducible and primitive). The
+ * higher order bits will have longer periods, since their values are also
+ * influenced by pseudo-random carries out of the lower bits. The total
+ * period of the generator is approximately deg*(2**deg - 1); thus doubling
+ * the amount of state information has a vast influence on the period of the
+ * generator. Note: the deg*(2**deg - 1) is an approximation only good for
+ * large deg, when the period of the shift register is the dominant factor.
+ * With deg equal to seven, the period is actually much longer than the
+ * 7*(2**7 - 1) predicted by this formula.
+ */
+
+/*
+ * For each of the currently supported random number generators, we have a
+ * break value on the amount of state information (you need at least this
+ * many bytes of state info to support this random number generator), a degree
+ * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ * the separation between the two lower order coefficients of the trinomial.
+ */
+#define TYPE_0 0 /* linear congruential */
+#define BREAK_0 8
+#define DEG_0 0
+#define SEP_0 0
+
+#define TYPE_1 1 /* x**7 + x**3 + 1 */
+#define BREAK_1 32
+#define DEG_1 7
+#define SEP_1 3
+
+#define TYPE_2 2 /* x**15 + x + 1 */
+#define BREAK_2 64
+#define DEG_2 15
+#define SEP_2 1
+
+#define TYPE_3 3 /* x**31 + x**3 + 1 */
+#define BREAK_3 128
+#define DEG_3 31
+#define SEP_3 3
+
+#define TYPE_4 4 /* x**63 + x + 1 */
+#define BREAK_4 256
+#define DEG_4 63
+#define SEP_4 1
+
+/*
+ * Array versions of the above information to make code run faster --
+ * relies on fact that TYPE_i == i.
+ */
+#define MAX_TYPES 5 /* max number of types above */
+
+static int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+/*
+ * Initially, everything is set up as if from:
+ *
+ * initstate(1, &randtbl, 128);
+ *
+ * Note that this initialization takes advantage of the fact that srandom()
+ * advances the front and rear pointers 10*rand_deg times, and hence the
+ * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ * element of the state information, which contains info about the current
+ * position of the rear pointer is just
+ *
+ * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
+ */
+
+static long randtbl[DEG_3 + 1] = {
+ TYPE_3,
+ 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
+ 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
+ 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
+ 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
+ 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
+ 0x27fb47b9,
+};
+
+/*
+ * fptr and rptr are two pointers into the state info, a front and a rear
+ * pointer. These two pointers are always rand_sep places aparts, as they
+ * cycle cyclically through the state information. (Yes, this does mean we
+ * could get away with just one pointer, but the code for random() is more
+ * efficient this way). The pointers are left positioned as they would be
+ * from the call
+ *
+ * initstate(1, randtbl, 128);
+ *
+ * (The position of the rear pointer, rptr, is really 0 (as explained above
+ * in the initialization of randtbl) because the state table pointer is set
+ * to point to randtbl[1] (as explained below).
+ */
+static long *fptr = &randtbl[SEP_3 + 1];
+static long *rptr = &randtbl[1];
+
+/*
+ * The following things are the pointer to the state information table, the
+ * type of the current generator, the degree of the current polynomial being
+ * used, and the separation between the two pointers. Note that for efficiency
+ * of random(), we remember the first location of the state information, not
+ * the zeroeth. Hence it is valid to access state[-1], which is used to
+ * store the type of the R.N.G. Also, we remember the last location, since
+ * this is more efficient than indexing every time to find the address of
+ * the last element to see if the front and rear pointers have wrapped.
+ */
+static long *state = &randtbl[1];
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+static long *end_ptr = &randtbl[DEG_3 + 1];
+
+long random();
+
+/*
+ * srandom:
+ *
+ * Initialize the random number generator based on the given seed. If the
+ * type is the trivial no-state-information type, just remember the seed.
+ * Otherwise, initializes state[] based on the given "seed" via a linear
+ * congruential generator. Then, the pointers are set to known locations
+ * that are exactly rand_sep places apart. Lastly, it cycles the state
+ * information a given number of times to get rid of any initial dependencies
+ * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
+ * for default usage relies on values produced by this routine.
+ */
+void
+srandom(x)
+ u_int x;
+{
+ register int i, j;
+
+ if (rand_type == TYPE_0)
+ state[0] = x;
+ else {
+ j = 1;
+ state[0] = x;
+ for (i = 1; i < rand_deg; i++)
+ state[i] = 1103515245 * state[i - 1] + 12345;
+ fptr = &state[rand_sep];
+ rptr = &state[0];
+ for (i = 0; i < 10 * rand_deg; i++)
+ (void)random();
+ }
+}
+
+/*
+ * initstate:
+ *
+ * Initialize the state information in the given array of n bytes for future
+ * random number generation. Based on the number of bytes we are given, and
+ * the break values for the different R.N.G.'s, we choose the best (largest)
+ * one we can and set things up for it. srandom() is then called to
+ * initialize the state information.
+ *
+ * Note that on return from srandom(), we set state[-1] to be the type
+ * multiplexed with the current value of the rear pointer; this is so
+ * successive calls to initstate() won't lose this information and will be
+ * able to restart with setstate().
+ *
+ * Note: the first thing we do is save the current state, if any, just like
+ * setstate() so that it doesn't matter when initstate is called.
+ *
+ * Returns a pointer to the old state.
+ */
+char *
+initstate(seed, arg_state, n)
+ u_int seed; /* seed for R.N.G. */
+ char *arg_state; /* pointer to state array */
+ int n; /* # bytes of state info */
+{
+ register char *ostate = (char *)(&state[-1]);
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ if (n < BREAK_0) {
+ (void)fprintf(stderr,
+ "random: not enough state (%d bytes); ignored.\n", n);
+ return(0);
+ }
+ if (n < BREAK_1) {
+ rand_type = TYPE_0;
+ rand_deg = DEG_0;
+ rand_sep = SEP_0;
+ } else if (n < BREAK_2) {
+ rand_type = TYPE_1;
+ rand_deg = DEG_1;
+ rand_sep = SEP_1;
+ } else if (n < BREAK_3) {
+ rand_type = TYPE_2;
+ rand_deg = DEG_2;
+ rand_sep = SEP_2;
+ } else if (n < BREAK_4) {
+ rand_type = TYPE_3;
+ rand_deg = DEG_3;
+ rand_sep = SEP_3;
+ } else {
+ rand_type = TYPE_4;
+ rand_deg = DEG_4;
+ rand_sep = SEP_4;
+ }
+ state = &(((long *)arg_state)[1]); /* first location */
+ end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
+ srandom(seed);
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES*(rptr - state) + rand_type;
+ return(ostate);
+}
+
+/*
+ * setstate:
+ *
+ * Restore the state from the given state array.
+ *
+ * Note: it is important that we also remember the locations of the pointers
+ * in the current state information, and restore the locations of the pointers
+ * from the old state information. This is done by multiplexing the pointer
+ * location into the zeroeth word of the state information.
+ *
+ * Note that due to the order in which things are done, it is OK to call
+ * setstate() with the same state as the current state.
+ *
+ * Returns a pointer to the old state information.
+ */
+char *
+setstate(arg_state)
+ char *arg_state;
+{
+ register long *new_state = (long *)arg_state;
+ register int type = new_state[0] % MAX_TYPES;
+ register int rear = new_state[0] / MAX_TYPES;
+ char *ostate = (char *)(&state[-1]);
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ switch(type) {
+ case TYPE_0:
+ case TYPE_1:
+ case TYPE_2:
+ case TYPE_3:
+ case TYPE_4:
+ rand_type = type;
+ rand_deg = degrees[type];
+ rand_sep = seps[type];
+ break;
+ default:
+ (void)fprintf(stderr,
+ "random: state info corrupted; not changed.\n");
+ }
+ state = &new_state[1];
+ if (rand_type != TYPE_0) {
+ rptr = &state[rear];
+ fptr = &state[(rear + rand_sep) % rand_deg];
+ }
+ end_ptr = &state[rand_deg]; /* set end_ptr too */
+ return(ostate);
+}
+
+/*
+ * random:
+ *
+ * If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
+ * the same in all the other cases due to all the global variables that have
+ * been set up. The basic operation is to add the number at the rear pointer
+ * into the one at the front pointer. Then both pointers are advanced to
+ * the next location cyclically in the table. The value returned is the sum
+ * generated, reduced to 31 bits by throwing away the "least random" low bit.
+ *
+ * Note: the code takes advantage of the fact that both the front and
+ * rear pointers can't wrap on the same call by not testing the rear
+ * pointer if the front one has wrapped.
+ *
+ * Returns a 31-bit random number.
+ */
+long
+random()
+{
+ long i;
+
+ if (rand_type == TYPE_0)
+ i = state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff;
+ else {
+ *fptr += *rptr;
+ i = (*fptr >> 1) & 0x7fffffff; /* chucking least random bit */
+ if (++fptr >= end_ptr) {
+ fptr = state;
+ ++rptr;
+ } else if (++rptr >= end_ptr)
+ rptr = state;
+ }
+ return(i);
+}
+
diff --git a/usr.bin/ssh/randoms.c b/usr.bin/ssh/randoms.c
new file mode 100644
index 00000000000..249e106293f
--- /dev/null
+++ b/usr.bin/ssh/randoms.c
@@ -0,0 +1,365 @@
+/*
+
+random.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 4 14:55:57 1995 ylo
+
+Cryptographically strong random number generation.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: randoms.c,v 1.1 1999/09/26 20:53:36 deraadt Exp $");
+
+#include "randoms.h"
+#include "getput.h"
+#include "ssh_md5.h"
+
+#ifdef HAVE_GETRUSAGE
+#include <sys/resource.h>
+#ifdef HAVE_RUSAGE_H
+#include <sys/rusage.h>
+#endif /* HAVE_RUSAGE_H */
+#endif /* HAVE_GETRUSAGE */
+
+#ifdef HAVE_TIMES
+#include <sys/times.h>
+#endif /* HAVE_TIMES */
+
+/* Initializes the random number generator, loads any random information
+ from the given file, and acquires as much environmental noise as it
+ can to initialize the random number generator. More noise can be
+ acquired later by calling random_add_noise + random_stir, or by
+ calling random_get_environmental_noise again later when the environmental
+ situation has changed. */
+
+void random_initialize(RandomState *state, const char *filename)
+{
+ char buf[8192];
+ int f, bytes;
+
+ state->add_position = 0;
+ state->next_available_byte = sizeof(state->stir_key);
+
+ /* This isn't strictly necessary, but will keep programs like 3rd degree or
+ purify silent. */
+ memset(state, 0, sizeof(state));
+
+ /* Get noise from the file. */
+ random_add_noise(state, filename, strlen(filename)); /* Use the path. */
+ f = open(filename, O_RDONLY);
+ if (f >= 0)
+ {
+ state->state[0] += f;
+ bytes = read(f, buf, sizeof(buf));
+ close(f);
+ if (bytes > 0)
+ random_add_noise(state, buf, bytes);
+ memset(buf, 0, sizeof(buf));
+ }
+ else
+ {
+ /* Get all possible noise since we have no seed. */
+ random_acquire_environmental_noise(state);
+ random_save(state, filename);
+ }
+
+ /* Get easily available noise from the environment. */
+ random_acquire_light_environmental_noise(state);
+}
+
+void random_xor_noise(RandomState *state, unsigned int i, word32 value)
+{
+ value ^= GET_32BIT(state->state + 4 * i);
+ PUT_32BIT(state->state + 4 * i, value);
+}
+
+/* Acquires as much environmental noise as it can. This is probably quite
+ sufficient on a unix machine, but might be grossly inadequate on a
+ single-user PC or a Macintosh.
+
+ We test the elapsed real time after each command, and abort if we have
+ consumed over 30 seconds. */
+
+void random_acquire_environmental_noise(RandomState *state)
+{
+ time_t start_time;
+
+ /* Record the start time. */
+ start_time = time(NULL);
+
+ /* Run these first so that other statistics accumulate from these. We stop
+ collecting more noise when we have spent 30 seconds real time; on a large
+ system a single executed command is probably enough, whereas on small
+ systems we must use all possible noise sources. */
+ random_get_noise_from_command(state, "ps laxww 2>/dev/null");
+ if (time(NULL) - start_time < 30)
+ random_get_noise_from_command(state, "ps -al 2>/dev/null");
+ if (time(NULL) - start_time < 30)
+ random_get_noise_from_command(state, "ls -alni /tmp/. 2>/dev/null");
+ if (time(NULL) - start_time < 30)
+ random_get_noise_from_command(state, "w 2>/dev/null");
+ if (time(NULL) - start_time < 30)
+ random_get_noise_from_command(state, "netstat -s 2>/dev/null");
+ if (time(NULL) - start_time < 30)
+ random_get_noise_from_command(state, "netstat -an 2>/dev/null");
+ if (time(NULL) - start_time < 30)
+ random_get_noise_from_command(state, "netstat -in 2>/dev/null");
+
+ /* Get other easily available noise. */
+ random_acquire_light_environmental_noise(state);
+}
+
+/* Acquires easily available environmental noise. */
+
+void random_acquire_light_environmental_noise(RandomState *state)
+{
+ int f;
+ char buf[32];
+ int len;
+
+ /* If /dev/random is available, read some data from there in non-blocking
+ mode and mix it into the pool. */
+ f = open("/dev/random", O_RDONLY);
+ if (f >= 0)
+ {
+ /* Set the descriptor into non-blocking mode. */
+#if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN)
+ fcntl(f, F_SETFL, O_NONBLOCK);
+#else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+ fcntl(f, F_SETFL, O_NDELAY);
+#endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+ len = read(f, buf, sizeof(buf));
+ close(f);
+ if (len > 0)
+ random_add_noise(state, buf, len);
+ }
+
+ /* Get miscellaneous noise from various system parameters and statistics. */
+ random_xor_noise(state,
+ (unsigned int)(state->state[0] + 256*state->state[1]) %
+ (RANDOM_STATE_BYTES / 4),
+ (word32)time(NULL));
+
+#ifdef HAVE_GETTIMEOFDAY
+ {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ random_xor_noise(state, 0, (word32)tv.tv_usec);
+ random_xor_noise(state, 1, (word32)tv.tv_sec);
+#ifdef HAVE_CLOCK
+ random_xor_noise(state, 3, (word32)clock());
+#endif /* HAVE_CLOCK */
+ }
+#endif /* HAVE_GETTIMEOFDAY */
+#ifdef HAVE_TIMES
+ {
+ struct tms tm;
+ random_xor_noise(state, 2, (word32)times(&tm));
+ random_xor_noise(state, 4, (word32)(tm.tms_utime ^ (tm.tms_stime << 8) ^
+ (tm.tms_cutime << 16) ^
+ (tm.tms_cstime << 24)));
+ }
+#endif /* HAVE_TIMES */
+#ifdef HAVE_GETRUSAGE
+ {
+ struct rusage ru, cru;
+ getrusage(RUSAGE_SELF, &ru);
+ getrusage(RUSAGE_CHILDREN, &cru);
+ random_xor_noise(state, 0, (word32)(ru.ru_utime.tv_usec +
+ cru.ru_utime.tv_usec));
+ random_xor_noise(state, 2, (word32)(ru.ru_stime.tv_usec +
+ cru.ru_stime.tv_usec));
+ random_xor_noise(state, 5, (word32)(ru.ru_maxrss + cru.ru_maxrss));
+ random_xor_noise(state, 6, (word32)(ru.ru_ixrss + cru.ru_ixrss));
+ random_xor_noise(state, 7, (word32)(ru.ru_idrss + cru.ru_idrss));
+ random_xor_noise(state, 8, (word32)(ru.ru_minflt + cru.ru_minflt));
+ random_xor_noise(state, 9, (word32)(ru.ru_majflt + cru.ru_majflt));
+ random_xor_noise(state, 10, (word32)(ru.ru_nswap + cru.ru_nswap));
+ random_xor_noise(state, 11, (word32)(ru.ru_inblock + cru.ru_inblock));
+ random_xor_noise(state, 12, (word32)(ru.ru_oublock + cru.ru_oublock));
+ random_xor_noise(state, 13, (word32)((ru.ru_msgsnd ^ ru.ru_msgrcv ^
+ ru.ru_nsignals) +
+ (cru.ru_msgsnd ^ cru.ru_msgrcv ^
+ cru.ru_nsignals)));
+ random_xor_noise(state, 14, (word32)(ru.ru_nvcsw + cru.ru_nvcsw));
+ random_xor_noise(state, 15, (word32)(ru.ru_nivcsw + cru.ru_nivcsw));
+ }
+#endif /* HAVE_GETRUSAGE */
+ random_xor_noise(state, 11, (word32)getpid());
+ random_xor_noise(state, 12, (word32)getppid());
+ random_xor_noise(state, 10, (word32)getuid());
+ random_xor_noise(state, 10, (word32)(getgid() << 16));
+#ifdef _POSIX_CHILD_MAX
+ random_xor_noise(state, 13, (word32)(_POSIX_CHILD_MAX << 16));
+#endif /* _POSIX_CHILD_MAX */
+#ifdef CLK_TCK
+ random_xor_noise(state, 14, (word32)(CLK_TCK << 16));
+#endif /* CLK_TCK */
+
+ random_stir(state);
+}
+
+/* Executes the given command, and processes its output as noise. */
+
+void random_get_noise_from_command(RandomState *state, const char *cmd)
+{
+#ifdef HAVE_POPEN
+ char line[1000];
+ FILE *f;
+
+ f = popen(cmd, "r");
+ if (!f)
+ return;
+ while (fgets(line, sizeof(line), f))
+ random_add_noise(state, line, strlen(line));
+ pclose(f);
+ memset(line, 0, sizeof(line));
+#endif /* HAVE_POPEN */
+}
+
+/* Adds the contents of the buffer as noise. */
+
+void random_add_noise(RandomState *state, const void *buf, unsigned int bytes)
+{
+ unsigned int pos = state->add_position;
+ const char *input = buf;
+ while (bytes > 0)
+ {
+ if (pos >= RANDOM_STATE_BYTES)
+ {
+ pos = 0;
+ random_stir(state);
+ }
+ state->state[pos] ^= *input;
+ input++;
+ bytes--;
+ pos++;
+ }
+ state->add_position = pos;
+}
+
+/* Stirs the random pool to consume any newly acquired noise or to get more
+ random numbers.
+
+ This works by encrypting the data in the buffer in CFB mode with MD5 as
+ the cipher. */
+
+void random_stir(RandomState *state)
+{
+ uint32 iv[4];
+ unsigned int i;
+
+ /* Start IV from last block of random pool. */
+ iv[0] = GET_32BIT(state->state);
+ iv[1] = GET_32BIT(state->state + 4);
+ iv[2] = GET_32BIT(state->state + 8);
+ iv[3] = GET_32BIT(state->state + 12);
+
+ /* First CFB pass. */
+ for (i = 0; i < RANDOM_STATE_BYTES; i += 16)
+ {
+ MD5Transform(iv, state->stir_key);
+ iv[0] ^= GET_32BIT(state->state + i);
+ PUT_32BIT(state->state + i, iv[0]);
+ iv[1] ^= GET_32BIT(state->state + i + 4);
+ PUT_32BIT(state->state + i + 4, iv[1]);
+ iv[2] ^= GET_32BIT(state->state + i + 8);
+ PUT_32BIT(state->state + i + 8, iv[2]);
+ iv[3] ^= GET_32BIT(state->state + i + 12);
+ PUT_32BIT(state->state + i + 12, iv[3]);
+ }
+
+ /* Get new key. */
+ memcpy(state->stir_key, state->state, sizeof(state->stir_key));
+
+ /* Second CFB pass. */
+ for (i = 0; i < RANDOM_STATE_BYTES; i += 16)
+ {
+ MD5Transform(iv, state->stir_key);
+ iv[0] ^= GET_32BIT(state->state + i);
+ PUT_32BIT(state->state + i, iv[0]);
+ iv[1] ^= GET_32BIT(state->state + i + 4);
+ PUT_32BIT(state->state + i + 4, iv[1]);
+ iv[2] ^= GET_32BIT(state->state + i + 8);
+ PUT_32BIT(state->state + i + 8, iv[2]);
+ iv[3] ^= GET_32BIT(state->state + i + 12);
+ PUT_32BIT(state->state + i + 12, iv[3]);
+ }
+
+ memset(iv, 0, sizeof(iv));
+
+ state->add_position = 0;
+
+ /* Some data in the beginning is not returned to aboid giving an observer
+ complete knowledge of the contents of our random pool. */
+ state->next_available_byte = sizeof(state->stir_key);
+}
+
+/* Returns a random byte. Stirs the random pool if necessary. Acquires
+ new environmental noise approximately every five minutes. */
+
+unsigned int random_get_byte(RandomState *state)
+{
+ if (state->next_available_byte >= RANDOM_STATE_BYTES)
+ {
+ /* Get some easily available noise. More importantly, this stirs
+ the pool. */
+ random_acquire_light_environmental_noise(state);
+ }
+ assert(state->next_available_byte < RANDOM_STATE_BYTES);
+ return state->state[state->next_available_byte++];
+}
+
+/* Saves random data in a disk file. This is used to create a file that
+ can be used as a random seed on future runs. Only half of the random
+ data in our pool is written to the file to avoid an observer being
+ able to deduce the contents of our random pool from the file. */
+
+void random_save(RandomState *state, const char *filename)
+{
+ char buf[RANDOM_STATE_BYTES / 2]; /* Save only half of its bits. */
+ int i, f;
+
+ /* Get some environmental noise to make it harder to predict previous
+ values from saved bits (besides, we have now probably consumed some
+ resources so the noise may be really useful). This also stirs
+ the pool. */
+ random_acquire_light_environmental_noise(state);
+
+ /* Get as many bytes as is half the size of the pool. I am assuming
+ this will get enough randomness for it to be very useful, but will
+ not reveal enough to make it possible to determine previous or future
+ returns by the generator. */
+ for (i = 0; i < sizeof(buf); i++)
+ buf[i] = random_get_byte(state);
+
+ /* Again get a little noise and stir it to mix the unrevealed half with
+ those bits that have been saved to a file. There should be enough
+ unrevealed bits (plus the new noise) to make it infeasible to try to
+ guess future values from the saved bits. */
+ random_acquire_light_environmental_noise(state);
+
+ /* Create and write the file. Failure to create the file is silently
+ ignored. */
+ f = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0600);
+ if (f >= 0)
+ {
+ /* Creation successful. Write data to the file. */
+ write(f, buf, sizeof(buf));
+ close(f);
+ }
+ memset(buf, 0, sizeof(buf));
+}
+
+/* Clears the random number generator data structures. */
+
+void random_clear(RandomState *state)
+{
+ memset(state, 0, sizeof(*state));
+}
diff --git a/usr.bin/ssh/randoms.h b/usr.bin/ssh/randoms.h
new file mode 100644
index 00000000000..1e99f84a95b
--- /dev/null
+++ b/usr.bin/ssh/randoms.h
@@ -0,0 +1,77 @@
+/*
+
+random.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 4 14:49:05 1995 ylo
+
+Cryptographically strong random number generator.
+
+*/
+
+/* RCSID("$Id: randoms.h,v 1.1 1999/09/26 20:53:37 deraadt Exp $"); */
+
+#ifndef RANDOM_H
+#define RANDOM_H
+
+#include "ssh_md5.h"
+
+#define RANDOM_STATE_BITS 8192
+#define RANDOM_STATE_BYTES (RANDOM_STATE_BITS / 8)
+
+/* Structure for the random state. */
+typedef struct
+{
+ unsigned char state[RANDOM_STATE_BYTES];/* Pool of random data. */
+ unsigned char stir_key[64]; /* Extra data for next stirring. */
+ unsigned int next_available_byte; /* Index of next available byte. */
+ unsigned int add_position; /* Index to add noise. */
+} RandomState;
+
+/* Initializes the random number generator, loads any random information
+ from the given file, and acquires as much environmental noise as it
+ can to initialize the random number generator. More noise can be
+ acquired later by calling random_add_noise + random_stir, or by
+ calling random_get_environmental_noise again later when the environmental
+ situation has changed. */
+void random_initialize(RandomState *state, const char *filename);
+
+/* Acquires as much environmental noise as it can. This is probably quite
+ sufficient on a unix machine, but might be grossly inadequate on a
+ single-user PC or a Macintosh. This call random_stir automatically.
+ This call may take many seconds to complete on a busy system. */
+void random_acquire_environmental_noise(RandomState *state);
+
+/* Acquires easily available noise from the environment. */
+void random_acquire_light_environmental_noise(RandomState *state);
+
+/* Executes the given command, and processes its output as noise.
+ random_stir should be called after this. */
+void random_get_noise_from_command(RandomState *state, const char *cmd);
+
+/* Adds the contents of the buffer as noise. random_stir should be called
+ after this. */
+void random_add_noise(RandomState *state, const void *buf, unsigned int bytes);
+
+/* Stirs the random pool to consume any newly acquired noise or to get more
+ random numbers. This should be called after adding noise to properly
+ mix the noise into the random pool. */
+void random_stir(RandomState *state);
+
+/* Returns a random byte. Stirs the random pool if necessary. Acquires
+ new environmental noise approximately every five minutes. */
+unsigned int random_get_byte(RandomState *state);
+
+/* Saves some random bits in the file so that it can be used as a source
+ of randomness for later runs. */
+void random_save(RandomState *state, const char *filename);
+
+/* Zeroes and frees any data structures associated with the random number
+ generator. */
+void random_clear(RandomState *state);
+
+#endif /* RANDOM_H */
diff --git a/usr.bin/ssh/rc4.c b/usr.bin/ssh/rc4.c
new file mode 100644
index 00000000000..f85038daf68
--- /dev/null
+++ b/usr.bin/ssh/rc4.c
@@ -0,0 +1,72 @@
+/*
+
+Alleged RC4 (based on the Usenet posting in Spring-95)
+
+*/
+
+#include "includes.h"
+RCSID("$Id: rc4.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $");
+
+#include "rc4.h"
+
+void rc4_init(RC4Context *ctx, const unsigned char *key, unsigned int key_len)
+{
+ unsigned int t, u;
+ unsigned int keyindex;
+ unsigned int stateindex;
+ unsigned char* state;
+ unsigned int counter;
+
+ assert(key_len > 0);
+
+ state = &ctx->state[0];
+ ctx->x = 0;
+ ctx->y = 0;
+ for (counter = 0; counter < 256; counter++)
+ state[counter] = counter;
+ keyindex = 0;
+ stateindex = 0;
+ for (counter = 0; counter < 256; counter++)
+ {
+ t = state[counter];
+ stateindex = (stateindex + key[keyindex] + t) & 0xff;
+ u = state[stateindex];
+ state[stateindex] = t;
+ state[counter] = u;
+ if (++keyindex >= key_len)
+ keyindex = 0;
+ }
+}
+
+inline unsigned int rc4_byte(RC4Context *ctx)
+{
+ unsigned int x;
+ unsigned int y;
+ unsigned int sx, sy;
+ unsigned char *state;
+
+ state = ctx->state;
+ x = (ctx->x + 1) & 0xff;
+ sx = state[x];
+ y = (sx + ctx->y) & 0xff;
+ sy = state[y];
+ ctx->x = x;
+ ctx->y = y;
+ state[y] = sx;
+ state[x] = sy;
+ return state[(sx + sy) & 0xff];
+}
+
+void rc4_encrypt(RC4Context *ctx, unsigned char *dest,
+ const unsigned char *src, unsigned int len)
+{
+ unsigned int i;
+ for (i = 0; i < len; i++)
+ dest[i] = src[i] ^ rc4_byte(ctx);
+}
+
+void rc4_decrypt(RC4Context *ctx, unsigned char *dest,
+ const unsigned char *src, unsigned int len)
+{
+ rc4_encrypt(ctx, dest, src, len);
+}
diff --git a/usr.bin/ssh/rc4.h b/usr.bin/ssh/rc4.h
new file mode 100644
index 00000000000..780089f0cb7
--- /dev/null
+++ b/usr.bin/ssh/rc4.h
@@ -0,0 +1,34 @@
+/*
+
+Alleged RC4 (based on the Usenet posting in Spring-95)
+
+*/
+
+/* RCSID("$Id: rc4.h,v 1.1 1999/09/26 20:53:37 deraadt Exp $"); */
+
+#ifndef RC4_H
+#define RC4_H
+
+typedef struct
+{
+ unsigned int x;
+ unsigned int y;
+ unsigned char state[256];
+} RC4Context;
+
+/* Initializes the context and sets the key. */
+void rc4_init(RC4Context *ctx, const unsigned char *key, unsigned int keylen);
+
+/* Returns the next pseudo-random byte from the RC4 (pseudo-random generator)
+ stream. */
+unsigned int rc4_byte(RC4Context *ctx);
+
+/* Encrypts data. */
+void rc4_encrypt(RC4Context *ctx, unsigned char *dest,
+ const unsigned char *src, unsigned int len);
+
+/* Decrypts data. */
+void rc4_decrypt(RC4Context *ctx, unsigned char *dest,
+ const unsigned char *src, unsigned int len);
+
+#endif /* RC4_H */
diff --git a/usr.bin/ssh/readconf.c b/usr.bin/ssh/readconf.c
new file mode 100644
index 00000000000..48bad9714a7
--- /dev/null
+++ b/usr.bin/ssh/readconf.c
@@ -0,0 +1,670 @@
+/*
+
+readconf.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Apr 22 00:03:10 1995 ylo
+
+Functions for reading the configuration files.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: readconf.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $");
+
+#include "ssh.h"
+#include "cipher.h"
+#include "readconf.h"
+#include "xmalloc.h"
+
+/* Format of the configuration file:
+
+ # Configuration data is parsed as follows:
+ # 1. command line options
+ # 2. user-specific file
+ # 3. system-wide file
+ # Any configuration value is only changed the first time it is set.
+ # Thus, host-specific definitions should be at the beginning of the
+ # configuration file, and defaults at the end.
+
+ # Host-specific declarations. These may override anything above. A single
+ # host may match multiple declarations; these are processed in the order
+ # that they are given in.
+
+ Host *.ngs.fi ngs.fi
+ FallBackToRsh no
+
+ Host fake.com
+ HostName another.host.name.real.org
+ User blaah
+ Port 34289
+ ForwardX11 no
+ ForwardAgent no
+
+ Host books.com
+ RemoteForward 9999 shadows.cs.hut.fi:9999
+ Cipher 3des
+
+ Host fascist.blob.com
+ Port 23123
+ User tylonen
+ RhostsAuthentication no
+ PasswordAuthentication no
+
+ Host puukko.hut.fi
+ User t35124p
+ ProxyCommand ssh-proxy %h %p
+
+ Host *.fr
+ UseRsh yes
+
+ Host *.su
+ Cipher none
+ PasswordAuthentication no
+
+ # Defaults for various options
+ Host *
+ ForwardAgent no
+ ForwardX11 yes
+ RhostsAuthentication yes
+ PasswordAuthentication yes
+ RSAAuthentication yes
+ RhostsRSAAuthentication yes
+ FallBackToRsh no
+ UseRsh no
+ StrictHostKeyChecking yes
+ KeepAlives no
+ IdentityFile ~/.ssh/identity
+ Port 22
+ Cipher idea
+ EscapeChar ~
+
+*/
+
+/* Keyword tokens. */
+
+typedef enum
+{
+ oForwardAgent, oForwardX11, oRhostsAuthentication,
+ oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
+#ifdef KRB4
+ oKerberosAuthentication,
+#endif /* KRB4 */
+#ifdef KERBEROS_TGT_PASSING
+ oKerberosTgtPassing,
+#endif
+#ifdef AFS
+ oAFSTokenPassing,
+#endif
+ oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
+ oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
+ oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
+ oBatchMode, oStrictHostKeyChecking, oCompression, oCompressionLevel,
+ oKeepAlives, oTISAuthentication
+} OpCodes;
+
+/* Textual representations of the tokens. */
+
+static struct
+{
+ const char *name;
+ OpCodes opcode;
+} keywords[] =
+{
+ { "forwardagent", oForwardAgent },
+ { "forwardx11", oForwardX11 },
+ { "rhostsauthentication", oRhostsAuthentication },
+ { "passwordauthentication", oPasswordAuthentication },
+ { "rsaauthentication", oRSAAuthentication },
+#ifdef KRB4
+ { "kerberosauthentication", oKerberosAuthentication },
+#endif /* KRB4 */
+#ifdef KERBEROS_TGT_PASSING
+ { "kerberostgtpassing", oKerberosTgtPassing },
+#endif
+#ifdef AFS
+ { "afstokenpassing", oAFSTokenPassing },
+#endif
+ { "fallbacktorsh", oFallBackToRsh },
+ { "usersh", oUseRsh },
+ { "identityfile", oIdentityFile },
+ { "hostname", oHostName },
+ { "proxycommand", oProxyCommand },
+ { "port", oPort },
+ { "cipher", oCipher },
+ { "remoteforward", oRemoteForward },
+ { "localforward", oLocalForward },
+ { "user", oUser },
+ { "host", oHost },
+ { "escapechar", oEscapeChar },
+ { "rhostsrsaauthentication", oRhostsRSAAuthentication },
+ { "globalknownhostsfile", oGlobalKnownHostsFile },
+ { "userknownhostsfile", oUserKnownHostsFile },
+ { "connectionattempts", oConnectionAttempts },
+ { "batchmode", oBatchMode },
+ { "stricthostkeychecking", oStrictHostKeyChecking },
+ { "compression", oCompression },
+ { "compressionlevel", oCompressionLevel },
+ { "keepalive", oKeepAlives },
+ { "tisauthentication", oTISAuthentication },
+ { NULL, 0 }
+};
+
+/* Characters considered whitespace in strtok calls. */
+#define WHITESPACE " \t\r\n"
+
+
+/* Adds a local TCP/IP port forward to options. Never returns if there
+ is an error. */
+
+void add_local_forward(Options *options, int port, const char *host,
+ int host_port)
+{
+ Forward *fwd;
+ if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
+ fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
+ fwd = &options->local_forwards[options->num_local_forwards++];
+ fwd->port = port;
+ fwd->host = xstrdup(host);
+ fwd->host_port = host_port;
+}
+
+/* Adds a remote TCP/IP port forward to options. Never returns if there
+ is an error. */
+
+void add_remote_forward(Options *options, int port, const char *host,
+ int host_port)
+{
+ Forward *fwd;
+ if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
+ fatal("Too many remote forwards (max %d).",
+ SSH_MAX_FORWARDS_PER_DIRECTION);
+ fwd = &options->remote_forwards[options->num_remote_forwards++];
+ fwd->port = port;
+ fwd->host = xstrdup(host);
+ fwd->host_port = host_port;
+}
+
+/* Returns the number of the token pointed to by cp of length len.
+ Never returns if the token is not known. */
+
+static OpCodes parse_token(const char *cp, const char *filename, int linenum)
+{
+ unsigned int i;
+
+ for (i = 0; keywords[i].name; i++)
+ if (strcmp(cp, keywords[i].name) == 0)
+ return keywords[i].opcode;
+
+ fatal("%.200s line %d: Bad configuration option.",
+ filename, linenum);
+ /*NOTREACHED*/
+ return 0;
+}
+
+/* Processes a single option line as used in the configuration files.
+ This only sets those values that have not already been set. */
+
+void process_config_line(Options *options, const char *host,
+ char *line, const char *filename, int linenum,
+ int *activep)
+{
+ char buf[256], *cp, *string, **charptr;
+ int opcode, *intptr, value, fwd_port, fwd_host_port;
+
+ /* Skip leading whitespace. */
+ cp = line + strspn(line, WHITESPACE);
+ if (!*cp || *cp == '\n' || *cp == '#')
+ return;
+
+ /* Get the keyword. (Each line is supposed to begin with a keyword). */
+ cp = strtok(cp, WHITESPACE);
+ {
+ char *t = cp;
+ for (; *t != 0; t++)
+ if ('A' <= *t && *t <= 'Z')
+ *t = *t - 'A' + 'a'; /* tolower */
+
+ }
+ opcode = parse_token(cp, filename, linenum);
+
+ switch (opcode)
+ {
+
+ case oForwardAgent:
+ intptr = &options->forward_agent;
+ parse_flag:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
+ value = 0; /* To avoid compiler warning... */
+ if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
+ value = 1;
+ else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
+ value = 0;
+ else
+ fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
+
+ case oForwardX11:
+ intptr = &options->forward_x11;
+ goto parse_flag;
+
+ case oRhostsAuthentication:
+ intptr = &options->rhosts_authentication;
+ goto parse_flag;
+
+ case oPasswordAuthentication:
+ intptr = &options->password_authentication;
+ goto parse_flag;
+
+ case oRSAAuthentication:
+ intptr = &options->rsa_authentication;
+ goto parse_flag;
+
+ case oRhostsRSAAuthentication:
+ intptr = &options->rhosts_rsa_authentication;
+ goto parse_flag;
+
+#ifdef KRB4
+ case oKerberosAuthentication:
+ intptr = &options->kerberos_authentication;
+ goto parse_flag;
+#endif /* KRB4 */
+
+#ifdef KERBEROS_TGT_PASSING
+ case oKerberosTgtPassing:
+ intptr = &options->kerberos_tgt_passing;
+ goto parse_flag;
+#endif
+
+#ifdef AFS
+ case oAFSTokenPassing:
+ intptr = &options->afs_token_passing;
+ goto parse_flag;
+#endif
+
+ case oFallBackToRsh:
+ intptr = &options->fallback_to_rsh;
+ goto parse_flag;
+
+ case oUseRsh:
+ intptr = &options->use_rsh;
+ goto parse_flag;
+
+ case oBatchMode:
+ intptr = &options->batch_mode;
+ goto parse_flag;
+
+ case oStrictHostKeyChecking:
+ intptr = &options->strict_host_key_checking;
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing yes/no argument.",
+ filename, linenum);
+ value = 0; /* To avoid compiler warning... */
+ if (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0)
+ value = 1;
+ else if (strcmp(cp, "no") == 0 || strcmp(cp, "false") == 0)
+ value = 0;
+ else if (strcmp(cp, "ask") == 0)
+ value = 2;
+ else
+ fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
+
+#ifdef WITH_ZLIB
+ case oCompression:
+ intptr = &options->compression;
+ goto parse_flag;
+#endif /* WITH_ZLIB */
+
+ case oKeepAlives:
+ intptr = &options->keepalives;
+ goto parse_flag;
+
+ case oTISAuthentication:
+ cp = strtok(NULL, WHITESPACE);
+ if (cp != 0 && (strcmp(cp, "yes") == 0 || strcmp(cp, "true") == 0))
+ fprintf(stderr,
+ "%.99s line %d: Warning, TIS is not supported.\n",
+ filename,
+ linenum);
+ break;
+
+#ifdef WITH_ZLIB
+ case oCompressionLevel:
+ intptr = &options->compression_level;
+ goto parse_int;
+#endif /* WITH_ZLIB */
+
+ case oIdentityFile:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (*activep)
+ {
+ if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
+ fatal("%.200s line %d: Too many identity files specified (max %d).",
+ filename, linenum, SSH_MAX_IDENTITY_FILES);
+ options->identity_files[options->num_identity_files++] = xstrdup(cp);
+ }
+ break;
+
+ case oUser:
+ charptr = &options->user;
+ parse_string:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (*activep && *charptr == NULL)
+ *charptr = xstrdup(cp);
+ break;
+
+ case oGlobalKnownHostsFile:
+ charptr = &options->system_hostfile;
+ goto parse_string;
+
+ case oUserKnownHostsFile:
+ charptr = &options->user_hostfile;
+ goto parse_string;
+
+ case oHostName:
+ charptr = &options->hostname;
+ goto parse_string;
+
+ case oProxyCommand:
+ charptr = &options->proxy_command;
+ string = xstrdup("");
+ while ((cp = strtok(NULL, WHITESPACE)) != NULL)
+ {
+ string = xrealloc(string, strlen(string) + strlen(cp) + 2);
+ strcat(string, " ");
+ strcat(string, cp);
+ }
+ if (*activep && *charptr == NULL)
+ *charptr = string;
+ else
+ xfree(string);
+ return;
+
+ case oPort:
+ intptr = &options->port;
+ parse_int:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (cp[0] < '0' || cp[0] > '9')
+ fatal("%.200s line %d: Bad number.", filename, linenum);
+#if 0
+ value = atoi(cp);
+#else
+ {
+ char *ptr;
+ value = strtol(cp, &ptr, 0); /* Octal, decimal, or hex format? */
+ if (cp == ptr)
+ fatal("%.200s line %d: Bad number.", filename, linenum);
+ }
+#endif
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
+
+ case oConnectionAttempts:
+ intptr = &options->connection_attempts;
+ goto parse_int;
+
+ case oCipher:
+ intptr = &options->cipher;
+ cp = strtok(NULL, WHITESPACE);
+ value = cipher_number(cp);
+ if (value == -1)
+ fatal("%.200s line %d: Bad cipher.", filename, linenum);
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
+
+ case oRemoteForward:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (cp[0] < '0' || cp[0] > '9')
+ fatal("%.200s line %d: Badly formatted port number.",
+ filename, linenum);
+ fwd_port = atoi(cp);
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing second argument.",
+ filename, linenum);
+ if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
+ fatal("%.200s line %d: Badly formatted host:port.",
+ filename, linenum);
+ if (*activep)
+ add_remote_forward(options, fwd_port, buf, fwd_host_port);
+ break;
+
+ case oLocalForward:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (cp[0] < '0' || cp[0] > '9')
+ fatal("%.200s line %d: Badly formatted port number.",
+ filename, linenum);
+ fwd_port = atoi(cp);
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing second argument.",
+ filename, linenum);
+ if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
+ fatal("%.200s line %d: Badly formatted host:port.",
+ filename, linenum);
+ if (*activep)
+ add_local_forward(options, fwd_port, buf, fwd_host_port);
+ break;
+
+ case oHost:
+ *activep = 0;
+ while ((cp = strtok(NULL, WHITESPACE)) != NULL)
+ if (match_pattern(host, cp))
+ {
+ debug("Applying options for %.100s", cp);
+ *activep = 1;
+ break;
+ }
+ /* Avoid garbage check below, as strtok already returned NULL. */
+ return;
+
+ case oEscapeChar:
+ intptr = &options->escape_char;
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ fatal("%.200s line %d: Missing argument.", filename, linenum);
+ if (cp[0] == '^' && cp[2] == 0 &&
+ (unsigned char)cp[1] >= 64 && (unsigned char)cp[1] < 128)
+ value = (unsigned char)cp[1] & 31;
+ else
+ if (strlen(cp) == 1)
+ value = (unsigned char)cp[0];
+ else
+ if (strcmp(cp, "none") == 0)
+ value = -2;
+ else
+ {
+ fatal("%.200s line %d: Bad escape character.",
+ filename, linenum);
+ /*NOTREACHED*/
+ value = 0; /* Avoid compiler warning. */
+ }
+ if (*activep && *intptr == -1)
+ *intptr = value;
+ break;
+
+ default:
+ fatal("parse_config_file: Unimplemented opcode %d", opcode);
+ }
+
+ /* Check that there is no garbage at end of line. */
+ if (strtok(NULL, WHITESPACE) != NULL)
+ fatal("%.200s line %d: garbage at end of line.",
+ filename, linenum);
+}
+
+
+/* Reads the config file and modifies the options accordingly. Options should
+ already be initialized before this call. This never returns if there
+ is an error. If the file does not exist, this returns immediately. */
+
+void read_config_file(const char *filename, const char *host, Options *options)
+{
+ FILE *f;
+ char line[1024];
+ int active, linenum;
+
+ /* Open the file. */
+ f = fopen(filename, "r");
+ if (!f)
+ return;
+
+ debug("Reading configuration data %.200s", filename);
+
+ /* Mark that we are now processing the options. This flag is turned on/off
+ by Host specifications. */
+ active = 1;
+ linenum = 0;
+ while (fgets(line, sizeof(line), f))
+ {
+ /* Update line number counter. */
+ linenum++;
+
+ process_config_line(options, host, line, filename, linenum, &active);
+ }
+ fclose(f);
+}
+
+/* Initializes options to special values that indicate that they have not
+ yet been set. Read_config_file will only set options with this value.
+ Options are processed in the following order: command line, user config
+ file, system config file. Last, fill_default_options is called. */
+
+void initialize_options(Options *options)
+{
+ memset(options, 'X', sizeof(*options));
+ options->forward_agent = -1;
+ options->forward_x11 = -1;
+ options->rhosts_authentication = -1;
+ options->rsa_authentication = -1;
+#ifdef KRB4
+ options->kerberos_authentication = -1;
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ options->kerberos_tgt_passing = -1;
+#endif
+#ifdef AFS
+ options->afs_token_passing = -1;
+#endif
+ options->password_authentication = -1;
+ options->rhosts_rsa_authentication = -1;
+ options->fallback_to_rsh = -1;
+ options->use_rsh = -1;
+ options->batch_mode = -1;
+ options->strict_host_key_checking = -1;
+#ifdef WITH_ZLIB
+ options->compression = -1;
+#endif /* WITH_ZLIB */
+ options->keepalives = -1;
+#ifdef WITH_ZLIB
+ options->compression_level = -1;
+#endif /* WITH_ZLIB */
+ options->port = -1;
+ options->connection_attempts = -1;
+ options->cipher = -1;
+ options->num_identity_files = 0;
+ options->hostname = NULL;
+ options->proxy_command = NULL;
+ options->user = NULL;
+ options->escape_char = -1;
+ options->system_hostfile = NULL;
+ options->user_hostfile = NULL;
+ options->num_local_forwards = 0;
+ options->num_remote_forwards = 0;
+}
+
+/* Called after processing other sources of option data, this fills those
+ options for which no value has been specified with their default values. */
+
+void fill_default_options(Options *options)
+{
+ if (options->forward_agent == -1)
+ options->forward_agent = 1;
+ if (options->forward_x11 == -1)
+ options->forward_x11 = 1;
+ if (options->rhosts_authentication == -1)
+ options->rhosts_authentication = 1;
+ if (options->rsa_authentication == -1)
+ options->rsa_authentication = 1;
+#ifdef KRB4
+ if (options->kerberos_authentication == -1)
+ options->kerberos_authentication = 1;
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ if (options->kerberos_tgt_passing == -1)
+ options->kerberos_tgt_passing = 1;
+#endif
+#ifdef AFS
+ if (options->afs_token_passing == -1)
+ options->afs_token_passing = 1;
+#endif
+ if (options->password_authentication == -1)
+ options->password_authentication = 1;
+ if (options->rhosts_rsa_authentication == -1)
+ options->rhosts_rsa_authentication = 1;
+ if (options->fallback_to_rsh == -1)
+ options->fallback_to_rsh = 1;
+ if (options->use_rsh == -1)
+ options->use_rsh = 0;
+ if (options->batch_mode == -1)
+ options->batch_mode = 0;
+ if (options->strict_host_key_checking == -1)
+ options->strict_host_key_checking = 2; /* 2 is default */
+#ifdef WITH_ZLIB
+ if (options->compression == -1)
+ options->compression = 0;
+#endif /* WITH_ZLIB */
+ if (options->keepalives == -1)
+ options->keepalives = 1;
+#ifdef WITH_ZLIB
+ if (options->compression_level == -1)
+ options->compression_level = 6;
+#endif /* WITH_ZLIB */
+ if (options->port == -1)
+ options->port = 0; /* Filled in ssh_connect. */
+ if (options->connection_attempts == -1)
+ options->connection_attempts = 4;
+ if (options->cipher == -1)
+ options->cipher = SSH_CIPHER_NOT_SET; /* Selected in ssh_login(). */
+ if (options->num_identity_files == 0)
+ {
+ options->identity_files[0] =
+ xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
+ sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
+ options->num_identity_files = 1;
+ }
+ if (options->escape_char == -1)
+ options->escape_char = '~';
+ if (options->system_hostfile == NULL)
+ options->system_hostfile = SSH_SYSTEM_HOSTFILE;
+ if (options->user_hostfile == NULL)
+ options->user_hostfile = SSH_USER_HOSTFILE;
+ /* options->proxy_command should not be set by default */
+ /* options->user will be set in the main program if appropriate */
+ /* options->hostname will be set in the main program if appropriate */
+}
+
diff --git a/usr.bin/ssh/readconf.h b/usr.bin/ssh/readconf.h
new file mode 100644
index 00000000000..2ad83aec67b
--- /dev/null
+++ b/usr.bin/ssh/readconf.h
@@ -0,0 +1,116 @@
+/*
+
+readconf.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Apr 22 00:25:29 1995 ylo
+
+Functions for reading the configuration file.
+
+*/
+
+/* RCSID("$Id: readconf.h,v 1.1 1999/09/26 20:53:37 deraadt Exp $"); */
+
+#ifndef READCONF_H
+#define READCONF_H
+
+/* Data structure for representing a forwarding request. */
+
+typedef struct
+{
+ int port; /* Port to forward. */
+ char *host; /* Host to connect. */
+ int host_port; /* Port to connect on host. */
+} Forward;
+
+/* Data structure for representing option data. */
+
+typedef struct
+{
+ int forward_agent; /* Forward authentication agent. */
+ int forward_x11; /* Forward X11 display. */
+ int rhosts_authentication; /* Try rhosts authentication. */
+ int rhosts_rsa_authentication;/* Try rhosts with RSA authentication. */
+ int rsa_authentication; /* Try RSA authentication. */
+#ifdef KRB4
+ int kerberos_authentication; /* Try Kerberos authentication. */
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ int kerberos_tgt_passing; /* Try Kerberos tgt passing. */
+#endif
+#ifdef AFS
+ int afs_token_passing; /* Try AFS token passing. */
+#endif
+ int password_authentication; /* Try password authentication. */
+ int fallback_to_rsh; /* Use rsh if cannot connect with ssh. */
+ int use_rsh; /* Always use rsh (don\'t try ssh). */
+ int batch_mode; /* Batch mode: do not ask for passwords. */
+ int strict_host_key_checking; /* Strict host key checking. */
+#ifdef WITH_ZLIB
+ int compression; /* Compress packets in both directions. */
+ int compression_level; /* Compression level 1 (fast) to 9 (best). */
+#endif /* WITH_ZLIB */
+ int keepalives; /* Set SO_KEEPALIVE. */
+
+ int port; /* Port to connect. */
+ int connection_attempts; /* Max attempts (seconds) before giving up */
+ int cipher; /* Cipher to use. */
+ char *hostname; /* Real host to connect. */
+ char *proxy_command; /* Proxy command for connecting the host. */
+ char *user; /* User to log in as. */
+ int escape_char; /* Escape character; -2 = none */
+
+ char *system_hostfile; /* Path for /etc/ssh_known_hosts. */
+ char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
+
+ int num_identity_files; /* Number of files for RSA identities. */
+ char *identity_files[SSH_MAX_IDENTITY_FILES];
+
+ /* Local TCP/IP forward requests. */
+ int num_local_forwards;
+ Forward local_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
+
+ /* Remote TCP/IP forward requests. */
+ int num_remote_forwards;
+ Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
+} Options;
+
+
+/* Initializes options to special values that indicate that they have not
+ yet been set. Read_config_file will only set options with this value.
+ Options are processed in the following order: command line, user config
+ file, system config file. Last, fill_default_options is called. */
+void initialize_options(Options *options);
+
+/* Called after processing other sources of option data, this fills those
+ options for which no value has been specified with their default values. */
+void fill_default_options(Options *options);
+
+/* Processes a single option line as used in the configuration files.
+ This only sets those values that have not already been set. */
+void process_config_line(Options *options, const char *host,
+ char *line, const char *filename, int linenum,
+ int *activep);
+
+/* Reads the config file and modifies the options accordingly. Options should
+ already be initialized before this call. This never returns if there
+ is an error. If the file does not exist, this returns immediately. */
+void read_config_file(const char *filename, const char *host,
+ Options *options);
+
+/* Adds a local TCP/IP port forward to options. Never returns if there
+ is an error. */
+void add_local_forward(Options *options, int port, const char *host,
+ int host_port);
+
+/* Adds a remote TCP/IP port forward to options. Never returns if there
+ is an error. */
+void add_remote_forward(Options *options, int port, const char *host,
+ int host_port);
+
+
+#endif /* READCONF_H */
diff --git a/usr.bin/ssh/readpass.c b/usr.bin/ssh/readpass.c
new file mode 100644
index 00000000000..c9b37dd9b5f
--- /dev/null
+++ b/usr.bin/ssh/readpass.c
@@ -0,0 +1,171 @@
+/*
+
+readpass.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Jul 10 22:08:59 1995 ylo
+
+Functions for reading passphrases and passwords.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: readpass.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $");
+
+#include "xmalloc.h"
+#include "ssh.h"
+
+/* Saved old terminal mode for read_passphrase. */
+#ifdef USING_TERMIOS
+static struct termios saved_tio;
+#endif
+#ifdef USING_SGTTY
+static struct sgttyb saved_tio;
+#endif
+
+/* Old interrupt signal handler for read_passphrase. */
+static RETSIGTYPE (*old_handler)(int sig) = NULL;
+
+/* Interrupt signal handler for read_passphrase. */
+
+RETSIGTYPE intr_handler(int sig)
+{
+ /* Restore terminal modes. */
+#ifdef USING_TERMIOS
+ tcsetattr(fileno(stdin), TCSANOW, &saved_tio);
+#endif
+#ifdef USING_SGTTY
+ ioctl(fileno(stdin), TIOCSETP, &saved_tio);
+#endif
+ /* Restore the old signal handler. */
+ signal(sig, old_handler);
+ /* Resend the signal, with the old handler. */
+ kill(getpid(), sig);
+}
+
+/* Reads a passphrase from /dev/tty with echo turned off. Returns the
+ passphrase (allocated with xmalloc). Exits if EOF is encountered.
+ The passphrase if read from stdin if from_stdin is true (as is the
+ case with ssh-keygen). */
+
+char *read_passphrase(const char *prompt, int from_stdin)
+{
+ char buf[1024], *cp;
+#ifdef USING_TERMIOS
+ struct termios tio;
+#endif
+#ifdef USING_SGTTY
+ struct sgttyb tio;
+#endif
+ FILE *f;
+
+ if (from_stdin)
+ f = stdin;
+ else
+ {
+ /* Read the passphrase from /dev/tty to make it possible to ask it even
+ when stdin has been redirected. */
+ f = fopen("/dev/tty", "r");
+ if (!f)
+ {
+ if (getenv("DISPLAY"))
+ {
+ char command[512];
+ fprintf(stderr,
+ "Executing ssh-askpass to query the password...\n");
+ fflush(stdout);
+ fflush(stderr);
+ sprintf(command, "ssh-askpass '%.400s'", prompt);
+ f = popen(command, "r");
+ if (!fgets(buf, sizeof(buf), f))
+ {
+ pclose(f);
+ fprintf(stderr, "No passphrase supplied. Exiting.\n");
+ exit(1);
+ }
+ pclose(f);
+ if (strchr(buf, '\n'))
+ *strchr(buf, '\n') = 0;
+ return xstrdup(buf);
+ }
+
+ /* No controlling terminal and no DISPLAY. Nowhere to read. */
+ fprintf(stderr, "You have no controlling tty and no DISPLAY. Cannot read passphrase.\n");
+ exit(1);
+ }
+ }
+
+ /* Display the prompt (on stderr because stdout might be redirected). */
+ fflush(stdout);
+ fprintf(stderr, "%s", prompt);
+ fflush(stderr);
+
+ /* Get terminal modes. */
+#ifdef USING_TERMIOS
+ tcgetattr(fileno(f), &tio);
+#endif
+#ifdef USING_SGTTY
+ ioctl(fileno(f), TIOCGETP, &tio);
+#endif
+ saved_tio = tio;
+ /* Save signal handler and set the new handler. */
+ old_handler = signal(SIGINT, intr_handler);
+
+ /* Set new terminal modes disabling all echo. */
+#ifdef USING_TERMIOS
+ tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
+ tcsetattr(fileno(f), TCSANOW, &tio);
+#endif
+#ifdef USING_SGTTY
+ tio.sg_flags &= ~(ECHO);
+ ioctl(fileno(f), TIOCSETP, &tio);
+#endif
+
+ /* Read the passphrase from the terminal. */
+ if (fgets(buf, sizeof(buf), f) == NULL)
+ {
+ /* Got EOF. Just exit. */
+ /* Restore terminal modes. */
+#ifdef USING_TERMIOS
+ tcsetattr(fileno(f), TCSANOW, &saved_tio);
+#endif
+#ifdef USING_SGTTY
+ ioctl(fileno(f), TIOCSETP, &saved_tio);
+#endif
+ /* Restore the signal handler. */
+ signal(SIGINT, old_handler);
+ /* Print a newline (the prompt probably didn\'t have one). */
+ fprintf(stderr, "\n");
+ /* Close the file. */
+ if (f != stdin)
+ fclose(f);
+ exit(1);
+ }
+ /* Restore terminal modes. */
+#ifdef USING_TERMIOS
+ tcsetattr(fileno(f), TCSANOW, &saved_tio);
+#endif
+#ifdef USING_SGTTY
+ ioctl(fileno(f), TIOCSETP, &saved_tio);
+#endif
+ /* Restore the signal handler. */
+ (void)signal(SIGINT, old_handler);
+ /* Remove newline from the passphrase. */
+ if (strchr(buf, '\n'))
+ *strchr(buf, '\n') = 0;
+ /* Allocate a copy of the passphrase. */
+ cp = xstrdup(buf);
+ /* Clear the buffer so we don\'t leave copies of the passphrase laying
+ around. */
+ memset(buf, 0, sizeof(buf));
+ /* Print a newline since the prompt probably didn\'t have one. */
+ fprintf(stderr, "\n");
+ /* Close the file. */
+ if (f != stdin)
+ fclose(f);
+ return cp;
+}
diff --git a/usr.bin/ssh/remove.c b/usr.bin/ssh/remove.c
new file mode 100644
index 00000000000..7366ed2366b
--- /dev/null
+++ b/usr.bin/ssh/remove.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int remove(const char *filename)
+{
+ return unlink(filename);
+}
diff --git a/usr.bin/ssh/rfc-pg.c b/usr.bin/ssh/rfc-pg.c
new file mode 100644
index 00000000000..20d9b483908
--- /dev/null
+++ b/usr.bin/ssh/rfc-pg.c
@@ -0,0 +1,49 @@
+/*
+
+rfc-pg.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Fri Jul 7 02:14:16 1995 ylo
+
+*/
+
+/* RCSID("$Id: rfc-pg.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $"); */
+
+#include <stdio.h>
+
+int main()
+{
+ int add_formfeed = 0;
+ int skipping = 0;
+ int ch;
+
+ while ((ch = getc(stdin)) != EOF)
+ {
+ if (ch == '\n')
+ {
+ if (add_formfeed)
+ {
+ putc('\n', stdout);
+ putc('\014', stdout);
+ putc('\n', stdout);
+ add_formfeed = 0;
+ skipping = 1;
+ continue;
+ }
+ if (skipping)
+ continue;
+ }
+ skipping = 0;
+ if (ch == '\014')
+ {
+ add_formfeed = 1;
+ continue;
+ }
+ putc(ch, stdout);
+ }
+ exit(0);
+}
diff --git a/usr.bin/ssh/scp.1 b/usr.bin/ssh/scp.1
new file mode 100644
index 00000000000..16be9b9439f
--- /dev/null
+++ b/usr.bin/ssh/scp.1
@@ -0,0 +1,127 @@
+.\" -*- nroff -*-
+.\"
+.\" scp.1
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\"
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" Created: Sun May 7 00:14:37 1995 ylo
+.\"
+.\" $Id: scp.1,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+.\"
+.TH SCP 1 "November 8, 1995" SSH SSH
+
+.SH NAME
+scp \- secure copy (remote file copy program)
+
+.SH SYNOPSIS
+.LP
+.B scp
+[\c
+.B \-prvC\c
+]
+[\c
+.BI \-P "\ port\c
+]
+[\c
+.BI \-c "\ cipher\c
+]
+[\c
+.BI \-i "\ identity\c
+]
+.if n .ti +5
+[[\c
+.B user@\c
+]\c
+.B host1:\c
+]\c
+.B filename1\c
+\&.\|.\|.
+[[\c
+.B user@\c
+]\c
+.B host2:\c
+]\c
+.B filename2
+
+.SH DESCRIPTION
+.LP
+.B Scp
+copies files between hosts on a network. It uses
+.B ssh
+for data transfer, and uses the same authentication and provides the
+same security as
+.B ssh.
+Unlike
+.BR rcp ",
+.B ssh
+will ask for passwords or passphrases if they are needed for
+authentication.
+.LP
+Any file name may contain a host and user specification to indicate
+that the file is to be copied to/from that host. Copies between two
+remote hosts are permitted.
+
+.SH OPTIONS
+
+.TP 0.6i
+.BI \-c "\ cipher
+Selects the cipher to use for encrypting the data transfer. This
+option is directly passed to
+.B ssh.
+.TP
+.BI \-i "\ identity_file
+Selects the file from which the identity (private key) for RSA
+authentication is read. This option is directly passed to
+.B ssh.
+.TP
+.B \-p
+Preserves modification times, access times, and modes from the
+original file.
+.TP
+.B \-r
+Recursively copy entire directories.
+.TP
+.B \-v
+Verbose mode. Causes
+.B scp
+and
+.B ssh
+to print debugging messages about their progress. This is helpful in
+debugging connection, authentication, and configuration problems.
+.TP
+.B \-B
+Selects batch mode (prevents asking for passwords or passphrases).
+.TP
+.B \-C
+Compression enable. Passes the -C flag to
+.B ssh
+to enable compression.
+.TP
+.BI \-P "\ port
+Specifies the port to connect to on the remote host. Note that this
+option is written with a capital P, because \-p is already reserved for
+preserving the times and modes of the file in rcp.
+
+.SH AUTHORS
+.LP
+Timo Rinne <tri@iki.fi> and Tatu Ylonen <ylo@cs.hut.fi>
+
+.SH DERIVATION
+.LP
+.B Scp
+is based on the
+.B rcp
+program in BSD source code from the Regents of the University of
+California.
+
+.SH SEE ALSO
+.LP
+.BR ssh (1),
+.BR sshd (8),
+.BR ssh-keygen (1),
+.BR ssh-agent (1),
+.BR ssh-add (1),
+.BR rcp (1)
diff --git a/usr.bin/ssh/scp.c b/usr.bin/ssh/scp.c
new file mode 100644
index 00000000000..8ab7174840f
--- /dev/null
+++ b/usr.bin/ssh/scp.c
@@ -0,0 +1,1071 @@
+/*
+
+scp - secure remote copy. This is basically patched BSD rcp which uses ssh
+to do the data transfer (instead of using rcmd).
+
+NOTE: This version should NOT be suid root. (This uses ssh to do the transfer
+and ssh has the necessary privileges.)
+
+1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi>
+
+*/
+
+/*
+ * Copyright (c) 1983, 1990, 1992, 1993, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: scp.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+ */
+
+#include "includes.h"
+RCSID("$Id: scp.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $");
+
+#include "ssh.h"
+#include "xmalloc.h"
+#ifdef HAVE_UTIME_H
+#include <utime.h>
+#ifdef _NEXT_SOURCE
+struct utimbuf {
+ time_t actime;
+ time_t modtime;
+};
+#endif /* _NEXT_SOURCE */
+#else
+struct utimbuf
+{
+ long actime;
+ long modtime;
+};
+#endif
+
+#define _PATH_CP "cp"
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#if defined(KERBEROS_TGT_PASSING) || defined(AFS)
+/* This is set to non-zero to disable authentication forwarding. */
+int nofwd = 0;
+#endif
+
+/* This is set to non-zero to enable verbose mode. */
+int verbose = 0;
+
+/* This is set to non-zero if compression is desired. */
+int compress = 0;
+
+/* This is set to non-zero if running in batch mode (that is, password
+ and passphrase queries are not allowed). */
+int batchmode = 0;
+
+/* This is set to the cipher type string if given on the command line. */
+char *cipher = NULL;
+
+/* This is set to the RSA authentication identity file name if given on
+ the command line. */
+char *identity = NULL;
+
+/* This is the port to use in contacting the remote site (is non-NULL). */
+char *port = NULL;
+
+/* This function executes the given command as the specified user on the given
+ host. This returns < 0 if execution fails, and >= 0 otherwise.
+ This assigns the input and output file descriptors on success. */
+
+int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
+{
+ int pin[2], pout[2], reserved[2];
+
+ if (verbose)
+ fprintf(stderr, "Executing: host %s, user %s, command %s\n",
+ host, remuser ? remuser : "(unspecified)", cmd);
+
+ /* Reserve two descriptors so that the real pipes won't get descriptors
+ 0 and 1 because that will screw up dup2 below. */
+ pipe(reserved);
+
+ /* Create a socket pair for communicating with ssh. */
+ if (pipe(pin) < 0)
+ fatal("pipe: %s", strerror(errno));
+ if (pipe(pout) < 0)
+ fatal("pipe: %s", strerror(errno));
+
+ /* Free the reserved descriptors. */
+ close(reserved[0]);
+ close(reserved[1]);
+
+ /* For a child to execute the command on the remote host using ssh. */
+ if (fork() == 0)
+ {
+ char *args[100];
+ unsigned int i;
+
+ /* Child. */
+ close(pin[1]);
+ close(pout[0]);
+ dup2(pin[0], 0);
+ dup2(pout[1], 1);
+ close(pin[0]);
+ close(pout[1]);
+
+ i = 0;
+ args[i++] = SSH_PROGRAM;
+ args[i++] = "-x";
+ args[i++] = "-oFallBackToRsh no";
+ if (verbose)
+ args[i++] = "-v";
+ if (compress)
+ args[i++] = "-C";
+ if (batchmode)
+ args[i++] = "-oBatchMode yes";
+#if defined(KERBEROS_TGT_PASSING) || defined(AFS)
+ if (nofwd)
+ args[i++] = "-k";
+#endif
+ if (cipher != NULL)
+ {
+ args[i++] = "-c";
+ args[i++] = cipher;
+ }
+ if (identity != NULL)
+ {
+ args[i++] = "-i";
+ args[i++] = identity;
+ }
+ if (port != NULL)
+ {
+ args[i++] = "-p";
+ args[i++] = port;
+ }
+ if (remuser != NULL)
+ {
+ args[i++] = "-l";
+ args[i++] = remuser;
+ }
+ args[i++] = host;
+ args[i++] = cmd;
+ args[i++] = NULL;
+
+ execvp(SSH_PROGRAM, args);
+ perror(SSH_PROGRAM);
+ exit(1);
+ }
+ /* Parent. Close the other side, and return the local side. */
+ close(pin[0]);
+ *fdout = pin[1];
+ close(pout[1]);
+ *fdin = pout[0];
+ return 0;
+}
+
+void fatal(const char *fmt, ...)
+{
+ va_list ap;
+ char buf[1024];
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ va_end(ap);
+ fprintf(stderr, "%s\n", buf);
+ exit(255);
+}
+
+/* This stuff used to be in BSD rcp extern.h. */
+
+typedef struct {
+ int cnt;
+ char *buf;
+} BUF;
+
+extern int iamremote;
+
+BUF *allocbuf(BUF *, int, int);
+char *colon(char *);
+void lostconn(int);
+void nospace(void);
+int okname(char *);
+void run_err(const char *, ...);
+void verifydir(char *);
+
+/* Stuff from BSD rcp.c continues. */
+
+struct passwd *pwd;
+uid_t userid;
+int errs, remin, remout;
+int pflag, iamremote, iamrecursive, targetshouldbedirectory;
+
+#define CMDNEEDS 64
+char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
+
+int response(void);
+void rsource(char *, struct stat *);
+void sink(int, char *[]);
+void source(int, char *[]);
+void tolocal(int, char *[]);
+void toremote(char *, int, char *[]);
+void usage(void);
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int ch, fflag, tflag;
+ char *targ;
+ extern char *optarg;
+ extern int optind;
+
+ fflag = tflag = 0;
+#if defined(KERBEROS_TGT_PASSING) || defined(AFS)
+ while ((ch = getopt(argc, argv, "kdfprtvBCc:i:P:")) != EOF)
+#else
+ while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:")) != EOF)
+#endif
+ switch(ch) { /* User-visible flags. */
+ case 'p':
+ pflag = 1;
+ break;
+ case 'P':
+ port = optarg;
+ break;
+ case 'r':
+ iamrecursive = 1;
+ break;
+ /* Server options. */
+#if defined(KERBEROS_TGT_PASSING) || defined(AFS)
+ case 'k':
+ nofwd = 1;
+ break;
+#endif
+ case 'd':
+ targetshouldbedirectory = 1;
+ break;
+ case 'f': /* "from" */
+ iamremote = 1;
+ fflag = 1;
+ break;
+ case 't': /* "to" */
+ iamremote = 1;
+ tflag = 1;
+ break;
+ case 'c':
+ cipher = optarg;
+ break;
+ case 'i':
+ identity = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'B':
+ batchmode = 1;
+ break;
+ case 'C':
+ compress = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if ((pwd = getpwuid(userid = getuid())) == NULL)
+ fatal("unknown user %d", (int)userid);
+
+ remin = STDIN_FILENO;
+ remout = STDOUT_FILENO;
+
+ if (fflag) { /* Follow "protocol", send data. */
+ (void)response();
+ source(argc, argv);
+ exit(errs != 0);
+ }
+
+ if (tflag) { /* Receive data. */
+ sink(argc, argv);
+ exit(errs != 0);
+ }
+
+ if (argc < 2)
+ usage();
+ if (argc > 2)
+ targetshouldbedirectory = 1;
+
+ remin = remout = -1;
+ /* Command to be executed on remote system using "ssh". */
+ (void)sprintf(cmd, "scp%s%s%s%s", verbose ? " -v" : "",
+ iamrecursive ? " -r" : "", pflag ? " -p" : "",
+ targetshouldbedirectory ? " -d" : "");
+
+ (void)signal(SIGPIPE, lostconn);
+
+ if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */
+ toremote(targ, argc, argv);
+ else {
+ tolocal(argc, argv); /* Dest is local host. */
+ if (targetshouldbedirectory)
+ verifydir(argv[argc - 1]);
+ }
+ exit(errs != 0);
+}
+
+void
+toremote(targ, argc, argv)
+ char *targ, *argv[];
+ int argc;
+{
+ int i, len;
+ char *bp, *host, *src, *suser, *thost, *tuser;
+
+ *targ++ = 0;
+ if (*targ == 0)
+ targ = ".";
+
+ if ((thost = strchr(argv[argc - 1], '@'))) {
+ /* user@host */
+ *thost++ = 0;
+ tuser = argv[argc - 1];
+ if (*tuser == '\0')
+ tuser = NULL;
+ else if (!okname(tuser))
+ exit(1);
+ } else {
+ thost = argv[argc - 1];
+ tuser = NULL;
+ }
+
+ for (i = 0; i < argc - 1; i++) {
+ src = colon(argv[i]);
+ if (src) { /* remote to remote */
+ *src++ = 0;
+ if (*src == 0)
+ src = ".";
+ host = strchr(argv[i], '@');
+ len = strlen(SSH_PROGRAM) + strlen(argv[i]) +
+ strlen(src) + (tuser ? strlen(tuser) : 0) +
+ strlen(thost) + strlen(targ) + CMDNEEDS + 32;
+ bp = xmalloc(len);
+ if (host) {
+ *host++ = 0;
+ suser = argv[i];
+ if (*suser == '\0')
+ suser = pwd->pw_name;
+ else if (!okname(suser))
+ continue;
+ (void)sprintf(bp,
+ "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'",
+ SSH_PROGRAM, verbose ? " -v" : "",
+ suser, host, cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
+ } else
+ (void)sprintf(bp,
+ "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'",
+ SSH_PROGRAM, verbose ? " -v" : "",
+ argv[i], cmd, src,
+ tuser ? tuser : "", tuser ? "@" : "",
+ thost, targ);
+ if (verbose)
+ fprintf(stderr, "Executing: %s\n", bp);
+ (void)system(bp);
+ (void)xfree(bp);
+ } else { /* local to remote */
+ if (remin == -1) {
+ len = strlen(targ) + CMDNEEDS + 20;
+ bp = xmalloc(len);
+ (void)sprintf(bp, "%s -t %s", cmd, targ);
+ host = thost;
+ if (do_cmd(host, tuser,
+ bp, &remin, &remout) < 0)
+ exit(1);
+ if (response() < 0)
+ exit(1);
+ (void)xfree(bp);
+ }
+ source(1, argv+i);
+ }
+ }
+}
+
+void
+tolocal(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int i, len;
+ char *bp, *host, *src, *suser;
+
+ for (i = 0; i < argc - 1; i++) {
+ if (!(src = colon(argv[i]))) { /* Local to local. */
+ len = strlen(_PATH_CP) + strlen(argv[i]) +
+ strlen(argv[argc - 1]) + 20;
+ bp = xmalloc(len);
+ (void)sprintf(bp, "exec %s%s%s %s %s", _PATH_CP,
+ iamrecursive ? " -r" : "", pflag ? " -p" : "",
+ argv[i], argv[argc - 1]);
+ if (verbose)
+ fprintf(stderr, "Executing: %s\n", bp);
+ if (system(bp))
+ ++errs;
+ (void)xfree(bp);
+ continue;
+ }
+ *src++ = 0;
+ if (*src == 0)
+ src = ".";
+ if ((host = strchr(argv[i], '@')) == NULL) {
+ host = argv[i];
+ suser = NULL;
+ } else {
+ *host++ = 0;
+ suser = argv[i];
+ if (*suser == '\0')
+ suser = pwd->pw_name;
+ else if (!okname(suser))
+ continue;
+ }
+ len = strlen(src) + CMDNEEDS + 20;
+ bp = xmalloc(len);
+ (void)sprintf(bp, "%s -f %s", cmd, src);
+ if (do_cmd(host, suser, bp, &remin, &remout) < 0) {
+ (void)xfree(bp);
+ ++errs;
+ continue;
+ }
+ xfree(bp);
+ sink(1, argv + argc - 1);
+ (void)close(remin);
+ remin = remout = -1;
+ }
+}
+
+void
+source(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct stat stb;
+ static BUF buffer;
+ BUF *bp;
+ off_t i;
+ int amt, fd, haderr, indx, result;
+ char *last, *name, buf[2048];
+
+ for (indx = 0; indx < argc; ++indx) {
+ name = argv[indx];
+ if ((fd = open(name, O_RDONLY, 0)) < 0)
+ goto syserr;
+ if (fstat(fd, &stb) < 0) {
+syserr: run_err("%s: %s", name, strerror(errno));
+ goto next;
+ }
+ switch (stb.st_mode & S_IFMT) {
+ case S_IFREG:
+ break;
+ case S_IFDIR:
+ if (iamrecursive) {
+ rsource(name, &stb);
+ goto next;
+ }
+ /* FALLTHROUGH */
+ default:
+ run_err("%s: not a regular file", name);
+ goto next;
+ }
+ if ((last = strrchr(name, '/')) == NULL)
+ last = name;
+ else
+ ++last;
+ if (pflag) {
+ /*
+ * Make it compatible with possible future
+ * versions expecting microseconds.
+ */
+ (void)sprintf(buf, "T%lu 0 %lu 0\n",
+ (unsigned long)stb.st_mtime,
+ (unsigned long)stb.st_atime);
+ (void)write(remout, buf, strlen(buf));
+ if (response() < 0)
+ goto next;
+ }
+#define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+ (void)sprintf(buf, "C%04o %lu %s\n",
+ (unsigned int)(stb.st_mode & FILEMODEMASK),
+ (unsigned long)stb.st_size,
+ last);
+ if (verbose)
+ {
+ fprintf(stderr, "Sending file modes: %s", buf);
+ fflush(stderr);
+ }
+ (void)write(remout, buf, strlen(buf));
+ if (response() < 0)
+ goto next;
+ if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) {
+next: (void)close(fd);
+ continue;
+ }
+
+ /* Keep writing after an error so that we stay sync'd up. */
+ for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
+ amt = bp->cnt;
+ if (i + amt > stb.st_size)
+ amt = stb.st_size - i;
+ if (!haderr) {
+ result = read(fd, bp->buf, amt);
+ if (result != amt)
+ haderr = result >= 0 ? EIO : errno;
+ }
+ if (haderr)
+ (void)write(remout, bp->buf, amt);
+ else {
+ result = write(remout, bp->buf, amt);
+ if (result != amt)
+ haderr = result >= 0 ? EIO : errno;
+ }
+ }
+ if (close(fd) < 0 && !haderr)
+ haderr = errno;
+ if (!haderr)
+ (void)write(remout, "", 1);
+ else
+ run_err("%s: %s", name, strerror(haderr));
+ (void)response();
+ }
+}
+
+void
+rsource(name, statp)
+ char *name;
+ struct stat *statp;
+{
+ DIR *dirp;
+ struct dirent *dp;
+ char *last, *vect[1], path[1100];
+
+ if (!(dirp = opendir(name))) {
+ run_err("%s: %s", name, strerror(errno));
+ return;
+ }
+ last = strrchr(name, '/');
+ if (last == 0)
+ last = name;
+ else
+ last++;
+ if (pflag) {
+ (void)sprintf(path, "T%lu 0 %lu 0\n",
+ (unsigned long)statp->st_mtime,
+ (unsigned long)statp->st_atime);
+ (void)write(remout, path, strlen(path));
+ if (response() < 0) {
+ closedir(dirp);
+ return;
+ }
+ }
+ (void)sprintf(path,
+ "D%04o %d %.1024s\n", (unsigned int)(statp->st_mode & FILEMODEMASK),
+ 0, last);
+ if (verbose)
+ fprintf(stderr, "Entering directory: %s", path);
+ (void)write(remout, path, strlen(path));
+ if (response() < 0) {
+ closedir(dirp);
+ return;
+ }
+ while ((dp = readdir(dirp))) {
+ if (dp->d_ino == 0)
+ continue;
+ if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+ continue;
+ if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
+ run_err("%s/%s: name too long", name, dp->d_name);
+ continue;
+ }
+ (void)sprintf(path, "%s/%s", name, dp->d_name);
+ vect[0] = path;
+ source(1, vect);
+ }
+ (void)closedir(dirp);
+ (void)write(remout, "E\n", 2);
+ (void)response();
+}
+
+void
+sink(argc, argv)
+ int argc;
+ char *argv[];
+{
+ static BUF buffer;
+ struct stat stb;
+ enum { YES, NO, DISPLAYED } wrerr;
+ BUF *bp;
+ off_t i, j;
+ int amt, count, exists, first, mask, mode, ofd, omode;
+ int setimes, size, targisdir, wrerrno = 0;
+ char ch, *cp, *np, *targ, *why, *vect[1], buf[2048];
+ struct utimbuf ut;
+ int dummy_usec;
+
+#define SCREWUP(str) { why = str; goto screwup; }
+
+ setimes = targisdir = 0;
+ mask = umask(0);
+ if (!pflag)
+ (void)umask(mask);
+ if (argc != 1) {
+ run_err("ambiguous target");
+ exit(1);
+ }
+ targ = *argv;
+ if (targetshouldbedirectory)
+ verifydir(targ);
+
+ (void)write(remout, "", 1);
+ if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
+ targisdir = 1;
+ for (first = 1;; first = 0) {
+ cp = buf;
+ if (read(remin, cp, 1) <= 0)
+ return;
+ if (*cp++ == '\n')
+ SCREWUP("unexpected <newline>");
+ do {
+ if (read(remin, &ch, sizeof(ch)) != sizeof(ch))
+ SCREWUP("lost connection");
+ *cp++ = ch;
+ } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
+ *cp = 0;
+
+ if (buf[0] == '\01' || buf[0] == '\02') {
+ if (iamremote == 0)
+ (void)write(STDERR_FILENO,
+ buf + 1, strlen(buf + 1));
+ if (buf[0] == '\02')
+ exit(1);
+ ++errs;
+ continue;
+ }
+ if (buf[0] == 'E') {
+ (void)write(remout, "", 1);
+ return;
+ }
+
+ if (ch == '\n')
+ *--cp = 0;
+
+#define getnum(t) (t) = 0; \
+ while (*cp >= '0' && *cp <= '9') (t) = (t) * 10 + (*cp++ - '0');
+ cp = buf;
+ if (*cp == 'T') {
+ setimes++;
+ cp++;
+ getnum(ut.modtime);
+ if (*cp++ != ' ')
+ SCREWUP("mtime.sec not delimited");
+ getnum(dummy_usec);
+ if (*cp++ != ' ')
+ SCREWUP("mtime.usec not delimited");
+ getnum(ut.actime);
+ if (*cp++ != ' ')
+ SCREWUP("atime.sec not delimited");
+ getnum(dummy_usec);
+ if (*cp++ != '\0')
+ SCREWUP("atime.usec not delimited");
+ (void)write(remout, "", 1);
+ continue;
+ }
+ if (*cp != 'C' && *cp != 'D') {
+ /*
+ * Check for the case "rcp remote:foo\* local:bar".
+ * In this case, the line "No match." can be returned
+ * by the shell before the rcp command on the remote is
+ * executed so the ^Aerror_message convention isn't
+ * followed.
+ */
+ if (first) {
+ run_err("%s", cp);
+ exit(1);
+ }
+ SCREWUP("expected control record");
+ }
+ mode = 0;
+ for (++cp; cp < buf + 5; cp++) {
+ if (*cp < '0' || *cp > '7')
+ SCREWUP("bad mode");
+ mode = (mode << 3) | (*cp - '0');
+ }
+ if (*cp++ != ' ')
+ SCREWUP("mode not delimited");
+
+ for (size = 0; *cp >= '0' && *cp <= '9';)
+ size = size * 10 + (*cp++ - '0');
+ if (*cp++ != ' ')
+ SCREWUP("size not delimited");
+ if (targisdir) {
+ static char *namebuf;
+ static int cursize;
+ size_t need;
+
+ need = strlen(targ) + strlen(cp) + 250;
+ if (need > cursize)
+ namebuf = xmalloc(need);
+ (void)sprintf(namebuf, "%s%s%s", targ,
+ *targ ? "/" : "", cp);
+ np = namebuf;
+ } else
+ np = targ;
+ exists = stat(np, &stb) == 0;
+ if (buf[0] == 'D') {
+ int mod_flag = pflag;
+ if (exists) {
+ if (!S_ISDIR(stb.st_mode)) {
+ errno = ENOTDIR;
+ goto bad;
+ }
+ if (pflag)
+ (void)chmod(np, mode);
+ } else {
+ /* Handle copying from a read-only directory */
+ mod_flag = 1;
+ if (mkdir(np, mode | S_IRWXU) < 0)
+ goto bad;
+ }
+ vect[0] = np;
+ sink(1, vect);
+ if (setimes) {
+ setimes = 0;
+ if (utime(np, &ut) < 0)
+ run_err("%s: set times: %s",
+ np, strerror(errno));
+ }
+ if (mod_flag)
+ (void)chmod(np, mode);
+ continue;
+ }
+ omode = mode;
+ mode |= S_IWRITE;
+ if ((ofd = open(np, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0) {
+bad: run_err("%s: %s", np, strerror(errno));
+ continue;
+ }
+ (void)write(remout, "", 1);
+ if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) {
+ (void)close(ofd);
+ continue;
+ }
+ cp = bp->buf;
+ wrerr = NO;
+ for (count = i = 0; i < size; i += 4096) {
+ amt = 4096;
+ if (i + amt > size)
+ amt = size - i;
+ count += amt;
+ do {
+ j = read(remin, cp, amt);
+ if (j <= 0) {
+ run_err("%s", j ? strerror(errno) :
+ "dropped connection");
+ exit(1);
+ }
+ amt -= j;
+ cp += j;
+ } while (amt > 0);
+ if (count == bp->cnt) {
+ /* Keep reading so we stay sync'd up. */
+ if (wrerr == NO) {
+ j = write(ofd, bp->buf, count);
+ if (j != count) {
+ wrerr = YES;
+ wrerrno = j >= 0 ? EIO : errno;
+ }
+ }
+ count = 0;
+ cp = bp->buf;
+ }
+ }
+ if (count != 0 && wrerr == NO &&
+ (j = write(ofd, bp->buf, count)) != count) {
+ wrerr = YES;
+ wrerrno = j >= 0 ? EIO : errno;
+ }
+#if 0
+ if (ftruncate(ofd, size)) {
+ run_err("%s: truncate: %s", np, strerror(errno));
+ wrerr = DISPLAYED;
+ }
+#endif
+ if (pflag) {
+ if (exists || omode != mode)
+#ifdef HAVE_FCHMOD
+ if (fchmod(ofd, omode))
+#else /* HAVE_FCHMOD */
+ if (chmod(np, omode))
+#endif /* HAVE_FCHMOD */
+ run_err("%s: set mode: %s",
+ np, strerror(errno));
+ } else {
+ if (!exists && omode != mode)
+#ifdef HAVE_FCHMOD
+ if (fchmod(ofd, omode & ~mask))
+#else /* HAVE_FCHMOD */
+ if (chmod(np, omode & ~mask))
+#endif /* HAVE_FCHMOD */
+ run_err("%s: set mode: %s",
+ np, strerror(errno));
+ }
+ (void)close(ofd);
+ (void)response();
+ if (setimes && wrerr == NO) {
+ setimes = 0;
+ if (utime(np, &ut) < 0) {
+ run_err("%s: set times: %s",
+ np, strerror(errno));
+ wrerr = DISPLAYED;
+ }
+ }
+ switch(wrerr) {
+ case YES:
+ run_err("%s: %s", np, strerror(wrerrno));
+ break;
+ case NO:
+ (void)write(remout, "", 1);
+ break;
+ case DISPLAYED:
+ break;
+ }
+ }
+screwup:
+ run_err("protocol error: %s", why);
+ exit(1);
+}
+
+int
+response()
+{
+ char ch, *cp, resp, rbuf[2048];
+
+ if (read(remin, &resp, sizeof(resp)) != sizeof(resp))
+ lostconn(0);
+
+ cp = rbuf;
+ switch(resp) {
+ case 0: /* ok */
+ return (0);
+ default:
+ *cp++ = resp;
+ /* FALLTHROUGH */
+ case 1: /* error, followed by error msg */
+ case 2: /* fatal error, "" */
+ do {
+ if (read(remin, &ch, sizeof(ch)) != sizeof(ch))
+ lostconn(0);
+ *cp++ = ch;
+ } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
+
+ if (!iamremote)
+ (void)write(STDERR_FILENO, rbuf, cp - rbuf);
+ ++errs;
+ if (resp == 1)
+ return (-1);
+ exit(1);
+ }
+ /* NOTREACHED */
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: scp [-p] f1 f2; or: scp [-pr] f1 ... fn directory\n");
+ exit(1);
+}
+
+void
+run_err(const char *fmt, ...)
+{
+ static FILE *fp;
+ va_list ap;
+ va_start(ap, fmt);
+
+ ++errs;
+ if (fp == NULL && !(fp = fdopen(remout, "w")))
+ return;
+ (void)fprintf(fp, "%c", 0x01);
+ (void)fprintf(fp, "scp: ");
+ (void)vfprintf(fp, fmt, ap);
+ (void)fprintf(fp, "\n");
+ (void)fflush(fp);
+
+ if (!iamremote)
+ {
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ }
+
+ va_end(ap);
+}
+
+/* Stuff below is from BSD rcp util.c. */
+
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: scp.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+ */
+
+char *
+colon(cp)
+ char *cp;
+{
+ if (*cp == ':') /* Leading colon is part of file name. */
+ return (0);
+
+ for (; *cp; ++cp) {
+ if (*cp == ':')
+ return (cp);
+ if (*cp == '/')
+ return (0);
+ }
+ return (0);
+}
+
+void
+verifydir(cp)
+ char *cp;
+{
+ struct stat stb;
+
+ if (!stat(cp, &stb)) {
+ if (S_ISDIR(stb.st_mode))
+ return;
+ errno = ENOTDIR;
+ }
+ run_err("%s: %s", cp, strerror(errno));
+ exit(1);
+}
+
+int
+okname(cp0)
+ char *cp0;
+{
+ int c;
+ char *cp;
+
+ cp = cp0;
+ do {
+ c = *cp;
+ if (c & 0200)
+ goto bad;
+ if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
+ goto bad;
+ } while (*++cp);
+ return (1);
+
+bad: fprintf(stderr, "%s: invalid user name", cp0);
+ return (0);
+}
+
+BUF *
+allocbuf(bp, fd, blksize)
+ BUF *bp;
+ int fd, blksize;
+{
+ size_t size;
+#ifdef HAVE_ST_BLKSIZE
+ struct stat stb;
+
+ if (fstat(fd, &stb) < 0) {
+ run_err("fstat: %s", strerror(errno));
+ return (0);
+ }
+ if (stb.st_blksize == 0)
+ size = blksize;
+ else
+ size = blksize + (stb.st_blksize - blksize % stb.st_blksize) %
+ stb.st_blksize;
+#else /* HAVE_ST_BLKSIZE */
+ size = blksize;
+#endif /* HAVE_ST_BLKSIZE */
+ if (bp->cnt >= size)
+ return (bp);
+ if (bp->buf == NULL)
+ bp->buf = xmalloc(size);
+ else
+ bp->buf = xrealloc(bp->buf, size);
+ bp->cnt = size;
+ return (bp);
+}
+
+void
+lostconn(signo)
+ int signo;
+{
+ if (!iamremote)
+ fprintf(stderr, "lost connection\n");
+ exit(1);
+}
diff --git a/usr.bin/ssh/servconf.c b/usr.bin/ssh/servconf.c
new file mode 100644
index 00000000000..4a70624d18a
--- /dev/null
+++ b/usr.bin/ssh/servconf.c
@@ -0,0 +1,499 @@
+/*
+
+servconf.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Aug 21 15:48:58 1995 ylo
+
+*/
+
+#include "includes.h"
+RCSID("$Id: servconf.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $");
+
+#include "ssh.h"
+#include "servconf.h"
+#include "xmalloc.h"
+
+/* Initializes the server options to their default values. */
+
+void initialize_server_options(ServerOptions *options)
+{
+ memset(options, 0, sizeof(*options));
+ options->port = -1;
+ options->listen_addr.s_addr = INADDR_ANY;
+ options->host_key_file = NULL;
+ options->random_seed_file = NULL;
+ options->server_key_bits = -1;
+ options->login_grace_time = -1;
+ options->key_regeneration_time = -1;
+ options->permit_root_login = -1;
+ options->ignore_rhosts = -1;
+ options->quiet_mode = -1;
+ options->fascist_logging = -1;
+ options->print_motd = -1;
+ options->x11_forwarding = -1;
+ options->strict_modes = -1;
+ options->keepalives = -1;
+ options->log_facility = (SyslogFacility)-1;
+ options->rhosts_authentication = -1;
+ options->rhosts_rsa_authentication = -1;
+ options->rsa_authentication = -1;
+#ifdef KRB4
+ options->kerberos_authentication = -1;
+ options->kerberos_or_local_passwd = -1;
+#endif
+#if defined(KRB4) || defined(AFS)
+ options->kerberos_ticket_cleanup = -1;
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ options->kerberos_tgt_passing = -1;
+#endif
+#ifdef AFS
+ options->afs_token_passing = -1;
+#endif
+ options->password_authentication = -1;
+ options->permit_empty_passwd = -1;
+ options->num_allow_hosts = 0;
+ options->num_deny_hosts = 0;
+}
+
+void fill_default_server_options(ServerOptions *options)
+{
+ if (options->port == -1)
+ {
+ struct servent *sp;
+
+ sp = getservbyname(SSH_SERVICE_NAME, "tcp");
+ if (sp)
+ options->port = ntohs(sp->s_port);
+ else
+ options->port = SSH_DEFAULT_PORT;
+ endservent();
+ }
+ if (options->host_key_file == NULL)
+ options->host_key_file = HOST_KEY_FILE;
+ if (options->random_seed_file == NULL)
+ options->random_seed_file = SSH_DAEMON_SEED_FILE;
+ if (options->server_key_bits == -1)
+ options->server_key_bits = 768;
+ if (options->login_grace_time == -1)
+ options->login_grace_time = 600;
+ if (options->key_regeneration_time == -1)
+ options->key_regeneration_time = 3600;
+ if (options->permit_root_login == -1)
+ options->permit_root_login = 1;
+ if (options->ignore_rhosts == -1)
+ options->ignore_rhosts = 0;
+ if (options->quiet_mode == -1)
+ options->quiet_mode = 0;
+ if (options->fascist_logging == -1)
+ options->fascist_logging = 1;
+ if (options->print_motd == -1)
+ options->print_motd = 1;
+ if (options->x11_forwarding == -1)
+ options->x11_forwarding = 1;
+ if (options->strict_modes == -1)
+ options->strict_modes = 1;
+ if (options->keepalives == -1)
+ options->keepalives = 1;
+ if (options->log_facility == (SyslogFacility)(-1))
+ options->log_facility = SYSLOG_FACILITY_DAEMON;
+ if (options->rhosts_authentication == -1)
+ options->rhosts_authentication = 0;
+ if (options->rhosts_rsa_authentication == -1)
+ options->rhosts_rsa_authentication = 1;
+ if (options->rsa_authentication == -1)
+ options->rsa_authentication = 1;
+#ifdef KRB4
+ if (options->kerberos_authentication == -1)
+ options->kerberos_authentication = 1;
+ if (options->kerberos_or_local_passwd == -1)
+ options->kerberos_or_local_passwd = 0;
+#endif
+#if defined(KRB4) || defined(AFS)
+ if (options->kerberos_ticket_cleanup == -1)
+ options->kerberos_ticket_cleanup = 1;
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ if (options->kerberos_tgt_passing == -1)
+ options->kerberos_tgt_passing = 0;
+#endif
+#ifdef AFS
+ if (options->afs_token_passing == -1)
+ options->afs_token_passing = 1;
+#endif
+ if (options->password_authentication == -1)
+ options->password_authentication = 1;
+ if (options->permit_empty_passwd == -1)
+ options->permit_empty_passwd = 1;
+}
+
+#define WHITESPACE " \t\r\n"
+
+/* Keyword tokens. */
+typedef enum
+{
+ sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
+ sPermitRootLogin, sQuietMode, sFascistLogging, sLogFacility,
+ sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
+#ifdef KRB4
+ sKerberosAuthentication, sKerberosOrLocalPasswd,
+#endif
+#if defined(KRB4) || defined(AFS)
+ sKerberosTicketCleanup,
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ sKerberosTgtPassing,
+#endif
+#ifdef AFS
+ sAFSTokenPassing,
+#endif
+ sPasswordAuthentication, sAllowHosts, sDenyHosts, sListenAddress,
+ sPrintMotd, sIgnoreRhosts, sX11Forwarding,
+ sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives
+} ServerOpCodes;
+
+/* Textual representation of the tokens. */
+static struct
+{
+ const char *name;
+ ServerOpCodes opcode;
+} keywords[] =
+{
+ { "port", sPort },
+ { "hostkey", sHostKeyFile },
+ { "serverkeybits", sServerKeyBits },
+ { "logingracetime", sLoginGraceTime },
+ { "keyregenerationinterval", sKeyRegenerationTime },
+ { "permitrootlogin", sPermitRootLogin },
+ { "quietmode", sQuietMode },
+ { "fascistlogging", sFascistLogging },
+ { "syslogfacility", sLogFacility },
+ { "rhostsauthentication", sRhostsAuthentication },
+ { "rhostsrsaauthentication", sRhostsRSAAuthentication },
+ { "rsaauthentication", sRSAAuthentication },
+#ifdef KRB4
+ { "kerberosauthentication", sKerberosAuthentication },
+ { "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
+#endif
+#if defined(KRB4) || defined(AFS)
+ { "kerberosticketcleanup", sKerberosTicketCleanup },
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ { "kerberostgtpassing", sKerberosTgtPassing },
+#endif
+#ifdef AFS
+ { "afstokenpassing", sAFSTokenPassing },
+#endif
+ { "passwordauthentication", sPasswordAuthentication },
+ { "allowhosts", sAllowHosts },
+ { "denyhosts", sDenyHosts },
+ { "listenaddress", sListenAddress },
+ { "printmotd", sPrintMotd },
+ { "ignorerhosts", sIgnoreRhosts },
+ { "x11forwarding", sX11Forwarding },
+ { "strictmodes", sStrictModes },
+ { "permitemptypasswords", sEmptyPasswd },
+ { "randomseed", sRandomSeedFile },
+ { "keepalive", sKeepAlives },
+ { NULL, 0 }
+};
+
+static struct
+{
+ const char *name;
+ SyslogFacility facility;
+} log_facilities[] =
+{
+ { "DAEMON", SYSLOG_FACILITY_DAEMON },
+ { "USER", SYSLOG_FACILITY_USER },
+ { "AUTH", SYSLOG_FACILITY_AUTH },
+ { "LOCAL0", SYSLOG_FACILITY_LOCAL0 },
+ { "LOCAL1", SYSLOG_FACILITY_LOCAL1 },
+ { "LOCAL2", SYSLOG_FACILITY_LOCAL2 },
+ { "LOCAL3", SYSLOG_FACILITY_LOCAL3 },
+ { "LOCAL4", SYSLOG_FACILITY_LOCAL4 },
+ { "LOCAL5", SYSLOG_FACILITY_LOCAL5 },
+ { "LOCAL6", SYSLOG_FACILITY_LOCAL6 },
+ { "LOCAL7", SYSLOG_FACILITY_LOCAL7 },
+ { NULL, 0 }
+};
+
+/* Returns the number of the token pointed to by cp of length len.
+ Never returns if the token is not known. */
+
+static ServerOpCodes parse_token(const char *cp, const char *filename,
+ int linenum)
+{
+ unsigned int i;
+
+ for (i = 0; keywords[i].name; i++)
+ if (strcmp(cp, keywords[i].name) == 0)
+ return keywords[i].opcode;
+
+ fprintf(stderr, "%s line %d: Bad configuration option: %s\n",
+ filename, linenum, cp);
+ exit(1);
+}
+
+/* Reads the server configuration file. */
+
+void read_server_config(ServerOptions *options, const char *filename)
+{
+ FILE *f;
+ char line[1024];
+ char *cp, **charptr;
+ int linenum, *intptr, i, value;
+ ServerOpCodes opcode;
+
+ f = fopen(filename, "r");
+ if (!f)
+ {
+ perror(filename);
+ return;
+ }
+
+ linenum = 0;
+ while (fgets(line, sizeof(line), f))
+ {
+ linenum++;
+ cp = line + strspn(line, WHITESPACE);
+ if (!*cp || *cp == '#')
+ continue;
+ cp = strtok(cp, WHITESPACE);
+ {
+ char *t = cp;
+ for (; *t != 0; t++)
+ if ('A' <= *t && *t <= 'Z')
+ *t = *t - 'A' + 'a'; /* tolower */
+
+ }
+ opcode = parse_token(cp, filename, linenum);
+ switch (opcode)
+ {
+ case sPort:
+ intptr = &options->port;
+ parse_int:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ {
+ fprintf(stderr, "%s line %d: missing integer value.\n",
+ filename, linenum);
+ exit(1);
+ }
+ value = atoi(cp);
+ if (*intptr == -1)
+ *intptr = value;
+ break;
+
+ case sServerKeyBits:
+ intptr = &options->server_key_bits;
+ goto parse_int;
+
+ case sLoginGraceTime:
+ intptr = &options->login_grace_time;
+ goto parse_int;
+
+ case sKeyRegenerationTime:
+ intptr = &options->key_regeneration_time;
+ goto parse_int;
+
+ case sListenAddress:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ {
+ fprintf(stderr, "%s line %d: missing inet addr.\n",
+ filename, linenum);
+ exit(1);
+ }
+#ifdef BROKEN_INET_ADDR
+ options->listen_addr.s_addr = inet_network(cp);
+#else /* BROKEN_INET_ADDR */
+ options->listen_addr.s_addr = inet_addr(cp);
+#endif /* BROKEN_INET_ADDR */
+ break;
+
+ case sHostKeyFile:
+ charptr = &options->host_key_file;
+ parse_pathname:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ {
+ fprintf(stderr, "%s line %d: missing file name.\n",
+ filename, linenum);
+ exit(1);
+ }
+ if (*charptr == NULL)
+ *charptr = tilde_expand_filename(cp, getuid());
+ break;
+
+ case sRandomSeedFile:
+ charptr = &options->random_seed_file;
+ goto parse_pathname;
+
+ case sPermitRootLogin:
+ intptr = &options->permit_root_login;
+ parse_flag:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ {
+ fprintf(stderr, "%s line %d: missing yes/no argument.\n",
+ filename, linenum);
+ exit(1);
+ }
+ if (strcmp(cp, "yes") == 0)
+ value = 1;
+ else
+ if (strcmp(cp, "no") == 0)
+ value = 0;
+ else
+ {
+ fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
+ filename, linenum, cp);
+ exit(1);
+ }
+ if (*intptr == -1)
+ *intptr = value;
+ break;
+
+ case sIgnoreRhosts:
+ intptr = &options->ignore_rhosts;
+ goto parse_flag;
+
+ case sQuietMode:
+ intptr = &options->quiet_mode;
+ goto parse_flag;
+
+ case sFascistLogging:
+ intptr = &options->fascist_logging;
+ goto parse_flag;
+
+ case sRhostsAuthentication:
+ intptr = &options->rhosts_authentication;
+ goto parse_flag;
+
+ case sRhostsRSAAuthentication:
+ intptr = &options->rhosts_rsa_authentication;
+ goto parse_flag;
+
+ case sRSAAuthentication:
+ intptr = &options->rsa_authentication;
+ goto parse_flag;
+
+#ifdef KRB4
+ case sKerberosAuthentication:
+ intptr = &options->kerberos_authentication;
+ goto parse_flag;
+
+ case sKerberosOrLocalPasswd:
+ intptr = &options->kerberos_or_local_passwd;
+ goto parse_flag;
+#endif
+
+#if defined(KRB4) || defined(AFS)
+ case sKerberosTicketCleanup:
+ intptr = &options->kerberos_ticket_cleanup;
+ goto parse_flag;
+#endif
+
+#ifdef KERBEROS_TGT_PASSING
+ case sKerberosTgtPassing:
+ intptr = &options->kerberos_tgt_passing;
+ goto parse_flag;
+#endif
+
+#ifdef AFS
+ case sAFSTokenPassing:
+ intptr = &options->afs_token_passing;
+ goto parse_flag;
+#endif
+
+ case sPasswordAuthentication:
+ intptr = &options->password_authentication;
+ goto parse_flag;
+
+ case sPrintMotd:
+ intptr = &options->print_motd;
+ goto parse_flag;
+
+ case sX11Forwarding:
+ intptr = &options->x11_forwarding;
+ goto parse_flag;
+
+ case sStrictModes:
+ intptr = &options->strict_modes;
+ goto parse_flag;
+
+ case sKeepAlives:
+ intptr = &options->keepalives;
+ goto parse_flag;
+
+ case sEmptyPasswd:
+ intptr = &options->permit_empty_passwd;
+ goto parse_flag;
+
+ case sLogFacility:
+ cp = strtok(NULL, WHITESPACE);
+ if (!cp)
+ {
+ fprintf(stderr, "%s line %d: missing facility name.\n",
+ filename, linenum);
+ exit(1);
+ }
+ for (i = 0; log_facilities[i].name; i++)
+ if (strcmp(log_facilities[i].name, cp) == 0)
+ break;
+ if (!log_facilities[i].name)
+ {
+ fprintf(stderr, "%s line %d: unsupported log facility %s\n",
+ filename, linenum, cp);
+ exit(1);
+ }
+ if (options->log_facility == (SyslogFacility)(-1))
+ options->log_facility = log_facilities[i].facility;
+ break;
+
+ case sAllowHosts:
+ while ((cp = strtok(NULL, WHITESPACE)))
+ {
+ if (options->num_allow_hosts >= MAX_ALLOW_HOSTS)
+ {
+ fprintf(stderr, "%s line %d: too many allow hosts.\n",
+ filename, linenum);
+ exit(1);
+ }
+ options->allow_hosts[options->num_allow_hosts++] = xstrdup(cp);
+ }
+ break;
+
+ case sDenyHosts:
+ while ((cp = strtok(NULL, WHITESPACE)))
+ {
+ if (options->num_deny_hosts >= MAX_DENY_HOSTS)
+ {
+ fprintf(stderr, "%s line %d: too many deny hosts.\n",
+ filename, linenum);
+ exit(1);
+ }
+ options->deny_hosts[options->num_deny_hosts++] = xstrdup(cp);
+ }
+ break;
+
+ default:
+ fprintf(stderr, "%s line %d: Missing handler for opcode %s (%d)\n",
+ filename, linenum, cp, opcode);
+ exit(1);
+ }
+ if (strtok(NULL, WHITESPACE) != NULL)
+ {
+ fprintf(stderr, "%s line %d: garbage at end of line.\n",
+ filename, linenum);
+ exit(1);
+ }
+ }
+ fclose(f);
+}
diff --git a/usr.bin/ssh/servconf.h b/usr.bin/ssh/servconf.h
new file mode 100644
index 00000000000..2807218c1ad
--- /dev/null
+++ b/usr.bin/ssh/servconf.h
@@ -0,0 +1,77 @@
+/*
+
+servconf.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Aug 21 15:35:03 1995 ylo
+
+Definitions for server configuration data and for the functions reading it.
+
+*/
+
+/* RCSID("$Id: servconf.h,v 1.1 1999/09/26 20:53:37 deraadt Exp $"); */
+
+#ifndef SERVCONF_H
+#define SERVCONF_H
+
+#define MAX_ALLOW_HOSTS 256 /* Max # hosts on allow list. */
+#define MAX_DENY_HOSTS 256 /* Max # hosts on deny list. */
+
+typedef struct
+{
+ int port; /* Port number to listen on. */
+ struct in_addr listen_addr; /* Address on which the server listens. */
+ char *host_key_file; /* File containing host key. */
+ char *random_seed_file; /* File containing random seed. */
+ int server_key_bits; /* Size of the server key. */
+ int login_grace_time; /* Disconnect if no auth in this time (sec). */
+ int key_regeneration_time; /* Server key lifetime (seconds). */
+ int permit_root_login; /* If true, permit root login. */
+ int ignore_rhosts; /* Ignore .rhosts and .shosts. */
+ int quiet_mode; /* If true, don't log anything but fatals. */
+ int fascist_logging; /* Perform very verbose logging. */
+ int print_motd; /* If true, print /etc/motd. */
+ int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
+ int strict_modes; /* If true, require string home dir modes. */
+ int keepalives; /* If true, set SO_KEEPALIVE. */
+ SyslogFacility log_facility; /* Facility for system logging. */
+ int rhosts_authentication; /* If true, permit rhosts authentication. */
+ int rhosts_rsa_authentication;/* If true, permit rhosts RSA authentication.*/
+ int rsa_authentication; /* If true, permit RSA authentication. */
+#ifdef KRB4
+ int kerberos_authentication; /* If true, permit Kerberos authentication. */
+ int kerberos_or_local_passwd;
+#endif
+#if defined(KRB4) || defined(AFS)
+ int kerberos_ticket_cleanup; /* If true, destroy ticket file on logout. */
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ int kerberos_tgt_passing; /* If true, permit Kerberos tgt passing. */
+#endif
+#ifdef AFS
+ int afs_token_passing; /* If true, permit AFS token passing. */
+#endif
+ int password_authentication; /* If true, permit password authentication. */
+ int permit_empty_passwd; /* If false, do not permit empty passwords. */
+ unsigned int num_allow_hosts;
+ char *allow_hosts[MAX_ALLOW_HOSTS];
+ unsigned int num_deny_hosts;
+ char *deny_hosts[MAX_DENY_HOSTS];
+} ServerOptions;
+
+/* Initializes the server options to special values that indicate that they
+ have not yet been set. */
+void initialize_server_options(ServerOptions *options);
+
+/* Reads the server configuration file. This only sets the values for those
+ options that have the special value indicating they have not been set. */
+void read_server_config(ServerOptions *options, const char *filename);
+
+/* Sets values for those values that have not yet been set. */
+void fill_default_server_options(ServerOptions *options);
+
+#endif /* SERVCONF_H */
diff --git a/usr.bin/ssh/server_config.sample b/usr.bin/ssh/server_config.sample
new file mode 100644
index 00000000000..54deaa6251a
--- /dev/null
+++ b/usr.bin/ssh/server_config.sample
@@ -0,0 +1,38 @@
+# This is ssh server systemwide configuration file.
+
+Port 22
+ListenAddress 0.0.0.0
+HostKey _ETCDIR_/ssh_host_key
+RandomSeed _ETCDIR_/ssh_random_seed
+ServerKeyBits 768
+LoginGraceTime 600
+KeyRegenerationInterval 3600
+PermitRootLogin yes
+#
+# Don't read ~/.rhosts and ~/.shosts files
+IgnoreRhosts yes
+StrictModes yes
+QuietMode no
+X11Forwarding yes
+FascistLogging no
+PrintMotd yes
+KeepAlive yes
+SyslogFacility DAEMON
+RhostsAuthentication no
+#
+# For this to work you will also need host keys in _ETCDIR_/ssh_known_hosts
+RhostsRSAAuthentication yes
+#
+# Changed RSAAuthentication to no/bg
+RSAAuthentication no
+#
+# To enable tunneled clear text passwords, change to yes here!
+PasswordAuthentication no
+PermitEmptyPasswords no
+#KerberosOrLocalPasswd yes
+
+# Kerberos TGT Passing does only work with the AFS kaserver
+#KerberosTgtPassing yes
+
+# AllowHosts *.our.com friend.other.com
+# DenyHosts lowsecurity.theirs.com *.evil.org evil.org
diff --git a/usr.bin/ssh/serverloop.c b/usr.bin/ssh/serverloop.c
new file mode 100644
index 00000000000..731914d73e1
--- /dev/null
+++ b/usr.bin/ssh/serverloop.c
@@ -0,0 +1,628 @@
+/*
+
+serverloop.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sun Sep 10 00:30:37 1995 ylo
+
+Server main loop for handling the interactive session.
+
+*/
+
+#include "includes.h"
+#include "xmalloc.h"
+#include "ssh.h"
+#include "packet.h"
+#include "buffer.h"
+#include "servconf.h"
+#include "pty.h"
+
+static Buffer stdin_buffer; /* Buffer for stdin data. */
+static Buffer stdout_buffer; /* Buffer for stdout data. */
+static Buffer stderr_buffer; /* Buffer for stderr data. */
+static int fdin; /* Descriptor for stdin (for writing) */
+static int fdout; /* Descriptor for stdout (for reading);
+ May be same number as fdin. */
+static int fderr; /* Descriptor for stderr. May be -1. */
+static long stdin_bytes = 0; /* Number of bytes written to stdin. */
+static long stdout_bytes = 0; /* Number of stdout bytes sent to client. */
+static long stderr_bytes = 0; /* Number of stderr bytes sent to client. */
+static long fdout_bytes = 0; /* Number of stdout bytes read from program. */
+static int stdin_eof = 0; /* EOF message received from client. */
+static int fdout_eof = 0; /* EOF encountered reading from fdout. */
+static int fderr_eof = 0; /* EOF encountered readung from fderr. */
+static int connection_in; /* Connection to client (input). */
+static int connection_out; /* Connection to client (output). */
+static unsigned int buffer_high;/* "Soft" max buffer size. */
+static int max_fd; /* Max file descriptor number for select(). */
+
+/* This SIGCHLD kludge is used to detect when the child exits. The server
+ will exit after that, as soon as forwarded connections have terminated. */
+
+static int child_pid; /* Pid of the child. */
+static volatile int child_terminated; /* The child has terminated. */
+static volatile int child_wait_status; /* Status from wait(). */
+
+RETSIGTYPE sigchld_handler(int sig)
+{
+ int wait_pid;
+ debug("Received SIGCHLD.");
+ wait_pid = wait((int *)&child_wait_status);
+ if (wait_pid != -1)
+ {
+ if (wait_pid != child_pid)
+ error("Strange, got SIGCHLD and wait returned pid %d but child is %d",
+ wait_pid, child_pid);
+ if (WIFEXITED(child_wait_status) ||
+ WIFSIGNALED(child_wait_status))
+ child_terminated = 1;
+ }
+ signal(SIGCHLD, sigchld_handler);
+}
+
+/* Process any buffered packets that have been received from the client. */
+
+void process_buffered_input_packets()
+{
+ int type;
+ char *data;
+ unsigned int data_len;
+ int row, col, xpixel, ypixel;
+ int payload_len;
+
+ /* Process buffered packets from the client. */
+ while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE)
+ {
+ switch (type)
+ {
+ case SSH_CMSG_STDIN_DATA:
+ /* Stdin data from the client. Append it to the buffer. */
+ if (fdin == -1)
+ break; /* Ignore any data if the client has closed stdin. */
+ data = packet_get_string(&data_len);
+ packet_integrity_check(payload_len, (4 + data_len), type);
+ buffer_append(&stdin_buffer, data, data_len);
+ memset(data, 0, data_len);
+ xfree(data);
+ break;
+
+ case SSH_CMSG_EOF:
+ /* Eof from the client. The stdin descriptor to the program
+ will be closed when all buffered data has drained. */
+ debug("EOF received for stdin.");
+ packet_integrity_check(payload_len, 0, type);
+ stdin_eof = 1;
+ break;
+
+ case SSH_CMSG_WINDOW_SIZE:
+ debug("Window change received.");
+ packet_integrity_check(payload_len, 4*4, type);
+ row = packet_get_int();
+ col = packet_get_int();
+ xpixel = packet_get_int();
+ ypixel = packet_get_int();
+ if (fdin != -1)
+ pty_change_window_size(fdin, row, col, xpixel, ypixel);
+ break;
+
+ case SSH_MSG_PORT_OPEN:
+ debug("Received port open request.");
+ channel_input_port_open(payload_len);
+ break;
+
+ case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
+ debug("Received channel open confirmation.");
+ packet_integrity_check(payload_len, 4 + 4, type);
+ channel_input_open_confirmation();
+ break;
+
+ case SSH_MSG_CHANNEL_OPEN_FAILURE:
+ debug("Received channel open failure.");
+ packet_integrity_check(payload_len, 4, type);
+ channel_input_open_failure();
+ break;
+
+ case SSH_MSG_CHANNEL_DATA:
+ channel_input_data(payload_len);
+ break;
+
+ case SSH_MSG_CHANNEL_CLOSE:
+ debug("Received channel close.");
+ packet_integrity_check(payload_len, 4, type);
+ channel_input_close();
+ break;
+
+ case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
+ debug("Received channel close confirmation.");
+ packet_integrity_check(payload_len, 4, type);
+ channel_input_close_confirmation();
+ break;
+
+ default:
+ /* In this phase, any unexpected messages cause a protocol
+ error. This is to ease debugging; also, since no
+ confirmations are sent messages, unprocessed unknown
+ messages could cause strange problems. Any compatible
+ protocol extensions must be negotiated before entering the
+ interactive session. */
+ packet_disconnect("Protocol error during session: type %d",
+ type);
+ }
+ }
+}
+
+/* Make packets from buffered stderr data, and buffer it for sending
+ to the client. */
+
+void make_packets_from_stderr_data()
+{
+ int len;
+
+ /* Send buffered stderr data to the client. */
+ while (buffer_len(&stderr_buffer) > 0 &&
+ packet_not_very_much_data_to_write())
+ {
+ len = buffer_len(&stderr_buffer);
+ if (packet_is_interactive())
+ {
+ if (len > 512)
+ len = 512;
+ }
+ else
+ {
+ if (len > 32768)
+ len = 32768; /* Keep the packets at reasonable size. */
+ }
+ packet_start(SSH_SMSG_STDERR_DATA);
+ packet_put_string(buffer_ptr(&stderr_buffer), len);
+ packet_send();
+ buffer_consume(&stderr_buffer, len);
+ stderr_bytes += len;
+ }
+}
+
+/* Make packets from buffered stdout data, and buffer it for sending to the
+ client. */
+
+void make_packets_from_stdout_data()
+{
+ int len;
+
+ /* Send buffered stdout data to the client. */
+ while (buffer_len(&stdout_buffer) > 0 &&
+ packet_not_very_much_data_to_write())
+ {
+ len = buffer_len(&stdout_buffer);
+ if (packet_is_interactive())
+ {
+ if (len > 512)
+ len = 512;
+ }
+ else
+ {
+ if (len > 32768)
+ len = 32768; /* Keep the packets at reasonable size. */
+ }
+ packet_start(SSH_SMSG_STDOUT_DATA);
+ packet_put_string(buffer_ptr(&stdout_buffer), len);
+ packet_send();
+ buffer_consume(&stdout_buffer, len);
+ stdout_bytes += len;
+ }
+}
+
+/* Sleep in select() until we can do something. This will initialize the
+ select masks. Upon return, the masks will indicate which descriptors
+ have data or can accept data. Optionally, a maximum time can be specified
+ for the duration of the wait (0 = infinite). */
+
+void wait_until_can_do_something(fd_set *readset, fd_set *writeset,
+ unsigned int max_time_milliseconds)
+{
+ struct timeval tv, *tvp;
+ int ret;
+
+ /* When select fails we restart from here. */
+retry_select:
+
+ /* Initialize select() masks. */
+ FD_ZERO(readset);
+
+ /* Read packets from the client unless we have too much buffered stdin
+ or channel data. */
+ if (buffer_len(&stdin_buffer) < 4096 &&
+ channel_not_very_much_buffered_data())
+ FD_SET(connection_in, readset);
+
+ /* If there is not too much data already buffered going to the client,
+ try to get some more data from the program. */
+ if (packet_not_very_much_data_to_write())
+ {
+ if (!fdout_eof)
+ FD_SET(fdout, readset);
+ if (!fderr_eof)
+ FD_SET(fderr, readset);
+ }
+
+ FD_ZERO(writeset);
+
+ /* Set masks for channel descriptors. */
+ channel_prepare_select(readset, writeset);
+
+ /* If we have buffered packet data going to the client, mark that
+ descriptor. */
+ if (packet_have_data_to_write())
+ FD_SET(connection_out, writeset);
+
+ /* If we have buffered data, try to write some of that data to the
+ program. */
+ if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
+ FD_SET(fdin, writeset);
+
+ /* Update the maximum descriptor number if appropriate. */
+ if (channel_max_fd() > max_fd)
+ max_fd = channel_max_fd();
+
+ /* If child has terminated, read as much as is available and then exit. */
+ if (child_terminated)
+ if (max_time_milliseconds == 0)
+ max_time_milliseconds = 100;
+
+ if (max_time_milliseconds == 0)
+ tvp = NULL;
+ else
+ {
+ tv.tv_sec = max_time_milliseconds / 1000;
+ tv.tv_usec = 1000 * (max_time_milliseconds % 1000);
+ tvp = &tv;
+ }
+
+ /* Wait for something to happen, or the timeout to expire. */
+ ret = select(max_fd + 1, readset, writeset, NULL, tvp);
+
+ if (ret < 0)
+ {
+ if (errno != EINTR)
+ error("select: %.100s", strerror(errno));
+ else
+ goto retry_select;
+ }
+}
+
+/* Processes input from the client and the program. Input data is stored
+ in buffers and processed later. */
+
+void process_input(fd_set *readset)
+{
+ int len;
+ char buf[16384];
+
+ /* Read and buffer any input data from the client. */
+ if (FD_ISSET(connection_in, readset))
+ {
+ len = read(connection_in, buf, sizeof(buf));
+ if (len == 0)
+ fatal("Connection closed by remote host.");
+
+ /* There is a kernel bug on Solaris that causes select to sometimes
+ wake up even though there is no data available. */
+ if (len < 0 && errno == EAGAIN)
+ len = 0;
+
+ if (len < 0)
+ fatal("Read error from remote host: %.100s", strerror(errno));
+
+ /* Buffer any received data. */
+ packet_process_incoming(buf, len);
+ }
+
+ /* Read and buffer any available stdout data from the program. */
+ if (!fdout_eof && FD_ISSET(fdout, readset))
+ {
+ len = read(fdout, buf, sizeof(buf));
+ if (len <= 0)
+ fdout_eof = 1;
+ else
+ {
+ buffer_append(&stdout_buffer, buf, len);
+ fdout_bytes += len;
+ }
+ }
+
+ /* Read and buffer any available stderr data from the program. */
+ if (!fderr_eof && FD_ISSET(fderr, readset))
+ {
+ len = read(fderr, buf, sizeof(buf));
+ if (len <= 0)
+ fderr_eof = 1;
+ else
+ buffer_append(&stderr_buffer, buf, len);
+ }
+}
+
+/* Sends data from internal buffers to client program stdin. */
+
+void process_output(fd_set *writeset)
+{
+ int len;
+
+ /* Write buffered data to program stdin. */
+ if (fdin != -1 && FD_ISSET(fdin, writeset))
+ {
+ len = write(fdin, buffer_ptr(&stdin_buffer),
+ buffer_len(&stdin_buffer));
+ if (len <= 0)
+ {
+ shutdown(fdin, 1); /* We will no longer send. */
+ fdin = -1;
+ }
+ else
+ {
+ /* Successful write. Consume the data from the buffer. */
+ buffer_consume(&stdin_buffer, len);
+ /* Update the count of bytes written to the program. */
+ stdin_bytes += len;
+ }
+ }
+
+ /* Send any buffered packet data to the client. */
+ if (FD_ISSET(connection_out, writeset))
+ packet_write_poll();
+}
+
+/* Wait until all buffered output has been sent to the client.
+ This is used when the program terminates. */
+
+void drain_output()
+{
+ /* Send any buffered stdout data to the client. */
+ if (buffer_len(&stdout_buffer) > 0)
+ {
+ packet_start(SSH_SMSG_STDOUT_DATA);
+ packet_put_string(buffer_ptr(&stdout_buffer),
+ buffer_len(&stdout_buffer));
+ packet_send();
+ /* Update the count of sent bytes. */
+ stdout_bytes += buffer_len(&stdout_buffer);
+ }
+
+ /* Send any buffered stderr data to the client. */
+ if (buffer_len(&stderr_buffer) > 0)
+ {
+ packet_start(SSH_SMSG_STDERR_DATA);
+ packet_put_string(buffer_ptr(&stderr_buffer),
+ buffer_len(&stderr_buffer));
+ packet_send();
+ /* Update the count of sent bytes. */
+ stderr_bytes += buffer_len(&stderr_buffer);
+ }
+
+ /* Wait until all buffered data has been written to the client. */
+ packet_write_wait();
+}
+
+/* Performs the interactive session. This handles data transmission between
+ the client and the program. Note that the notion of stdin, stdout, and
+ stderr in this function is sort of reversed: this function writes to
+ stdin (of the child program), and reads from stdout and stderr (of the
+ child program). */
+
+void server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
+{
+ int wait_status, wait_pid; /* Status and pid returned by wait(). */
+ int waiting_termination = 0; /* Have displayed waiting close message. */
+ unsigned int max_time_milliseconds;
+ unsigned int previous_stdout_buffer_bytes;
+ unsigned int stdout_buffer_bytes;
+ int type;
+
+ debug("Entering interactive session.");
+
+ /* Initialize the SIGCHLD kludge. */
+ child_pid = pid;
+ child_terminated = 0;
+ signal(SIGCHLD, sigchld_handler);
+
+ /* Initialize our global variables. */
+ fdin = fdin_arg;
+ fdout = fdout_arg;
+ fderr = fderr_arg;
+ connection_in = packet_get_connection_in();
+ connection_out = packet_get_connection_out();
+
+ previous_stdout_buffer_bytes = 0;
+
+ /* Set approximate I/O buffer size. */
+ if (packet_is_interactive())
+ buffer_high = 4096;
+ else
+ buffer_high = 64 * 1024;
+
+ /* Initialize max_fd to the maximum of the known file descriptors. */
+ max_fd = fdin;
+ if (fdout > max_fd)
+ max_fd = fdout;
+ if (fderr != -1 && fderr > max_fd)
+ max_fd = fderr;
+ if (connection_in > max_fd)
+ max_fd = connection_in;
+ if (connection_out > max_fd)
+ max_fd = connection_out;
+
+ /* Initialize Initialize buffers. */
+ buffer_init(&stdin_buffer);
+ buffer_init(&stdout_buffer);
+ buffer_init(&stderr_buffer);
+
+ /* If we have no separate fderr (which is the case when we have a pty - there
+ we cannot make difference between data sent to stdout and stderr),
+ indicate that we have seen an EOF from stderr. This way we don\'t
+ need to check the descriptor everywhere. */
+ if (fderr == -1)
+ fderr_eof = 1;
+
+ /* Main loop of the server for the interactive session mode. */
+ for (;;)
+ {
+ fd_set readset, writeset;
+
+ /* Process buffered packets from the client. */
+ process_buffered_input_packets();
+
+ /* If we have received eof, and there is no more pending input data,
+ cause a real eof by closing fdin. */
+ if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0)
+ {
+ shutdown(fdin, 1); /* We will no longer send. */
+ fdin = -1;
+ }
+
+ /* Make packets from buffered stderr data to send to the client. */
+ make_packets_from_stderr_data();
+
+ /* Make packets from buffered stdout data to send to the client.
+ If there is very little to send, this arranges to not send them
+ now, but to wait a short while to see if we are getting more data.
+ This is necessary, as some systems wake up readers from a pty after
+ each separate character. */
+ max_time_milliseconds = 0;
+ stdout_buffer_bytes = buffer_len(&stdout_buffer);
+ if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
+ stdout_buffer_bytes != previous_stdout_buffer_bytes)
+ max_time_milliseconds = 10; /* try again after a while */
+ else
+ make_packets_from_stdout_data(); /* Send it now. */
+ previous_stdout_buffer_bytes = buffer_len(&stdout_buffer);
+
+ /* Send channel data to the client. */
+ if (packet_not_very_much_data_to_write())
+ channel_output_poll();
+
+ /* Bail out of the loop if the program has closed its output descriptors,
+ and we have no more data to send to the client, and there is no
+ pending buffered data. */
+ if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
+ buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0)
+ {
+ if (!channel_still_open())
+ goto quit;
+ if (!waiting_termination)
+ {
+ const char *s =
+ "Waiting for forwarded connections to terminate...\r\n";
+ char *cp;
+ waiting_termination = 1;
+ buffer_append(&stderr_buffer, s, strlen(s));
+
+ /* Display list of open channels. */
+ cp = channel_open_message();
+ buffer_append(&stderr_buffer, cp, strlen(cp));
+ xfree(cp);
+ }
+ }
+
+ /* Sleep in select() until we can do something. */
+ wait_until_can_do_something(&readset, &writeset,
+ max_time_milliseconds);
+
+ /* Process any channel events. */
+ channel_after_select(&readset, &writeset);
+
+ /* Process input from the client and from program stdout/stderr. */
+ process_input(&readset);
+
+ /* Process output to the client and to program stdin. */
+ process_output(&writeset);
+ }
+
+ quit:
+ /* Cleanup and termination code. */
+
+ /* Wait until all output has been sent to the client. */
+ drain_output();
+
+ debug("End of interactive session; stdin %ld, stdout (read %ld, sent %ld), stderr %ld bytes.",
+ stdin_bytes, fdout_bytes, stdout_bytes, stderr_bytes);
+
+ /* Free and clear the buffers. */
+ buffer_free(&stdin_buffer);
+ buffer_free(&stdout_buffer);
+ buffer_free(&stderr_buffer);
+
+ /* Close the file descriptors. */
+ if (fdout != -1)
+ shutdown(fdout, 0);
+ fdout = -1;
+ fdout_eof = 1;
+ if (fderr != -1)
+ shutdown(fderr, 0);
+ fderr = -1;
+ fderr_eof = 1;
+ if (fdin != -1)
+ shutdown(fdin, 1);
+ fdin = -1;
+
+ /* Stop listening for channels; this removes unix domain sockets. */
+ channel_stop_listening();
+
+ /* Wait for the child to exit. Get its exit status. */
+ wait_pid = wait(&wait_status);
+ if (wait_pid < 0)
+ {
+ /* It is possible that the wait was handled by SIGCHLD handler. This
+ may result in either: this call returning with EINTR, or: this
+ call returning ECHILD. */
+ if (child_terminated)
+ wait_status = child_wait_status;
+ else
+ packet_disconnect("wait: %.100s", strerror(errno));
+ }
+ else
+ {
+ /* Check if it matches the process we forked. */
+ if (wait_pid != pid)
+ error("Strange, wait returned pid %d, expected %d", wait_pid, pid);
+ }
+
+ /* We no longer want our SIGCHLD handler to be called. */
+ signal(SIGCHLD, SIG_DFL);
+
+ /* Check if it exited normally. */
+ if (WIFEXITED(wait_status))
+ {
+ /* Yes, normal exit. Get exit status and send it to the client. */
+ debug("Command exited with status %d.", WEXITSTATUS(wait_status));
+ packet_start(SSH_SMSG_EXITSTATUS);
+ packet_put_int(WEXITSTATUS(wait_status));
+ packet_send();
+ packet_write_wait();
+
+ /* Wait for exit confirmation. Note that there might be other
+ packets coming before it; however, the program has already died
+ so we just ignore them. The client is supposed to respond with
+ the confirmation when it receives the exit status. */
+ do
+ {
+ int plen;
+ type = packet_read(&plen);
+ }
+ while (type != SSH_CMSG_EXIT_CONFIRMATION);
+
+ debug("Received exit confirmation.");
+ return;
+ }
+
+ /* Check if the program terminated due to a signal. */
+ if (WIFSIGNALED(wait_status))
+ packet_disconnect("Command terminated on signal %d.",
+ WTERMSIG(wait_status));
+
+ /* Some weird exit cause. Just exit. */
+ packet_disconnect("wait returned status %04x.", wait_status);
+ /*NOTREACHED*/
+}
+
diff --git a/usr.bin/ssh/ssh-add.1 b/usr.bin/ssh/ssh-add.1
new file mode 100644
index 00000000000..99a1312e2cd
--- /dev/null
+++ b/usr.bin/ssh/ssh-add.1
@@ -0,0 +1,98 @@
+.\" -*- nroff -*-
+.\"
+.\" ssh-add.1
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\"
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" Created: Sat Apr 22 23:55:14 1995 ylo
+.\"
+.\" $Id: ssh-add.1,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+.\"
+.TH SSH-ADD 1 "November 8, 1995" "SSH" "SSH"
+
+.SH NAME
+ssh-add \- adds identities for the authentication agent
+
+.SH SYNOPSIS
+.B ssh-add
+[\c
+.B \-l\c
+]
+[\c
+.B \-d\c
+]
+[\c
+.B \-D\c
+]
+[\c
+.B file\c
+\&.\|.\|.\|]
+
+.SH DESCRIPTION
+.LP
+.B Ssh-add
+adds identities to the authentication agent,
+.B ssh-agent.
+When run without arguments, it adds the file
+.IR $HOME/\s+2.\s0ssh/identity ".
+Alternative file names can be given on the
+command line. If any file requires a passphrase,
+.B ssh-add
+asks for the passphrase from the user. If the user is using X11, the
+passphrase is requested using a small X11 program; otherwise it is
+read from the user's tty. (Note: it may be necessary to redirect
+stdin from /dev/null to get the passphrase requested using X11.)
+.LP
+The authentication agent must be running and must be an ancestor of
+the current process for
+.B ssh-add
+to work.
+
+.SH OPTIONS
+.TP 0.5i
+.B \-l
+Lists all identities currently represented by the agent.
+.TP
+.B \-d
+Instead of adding the identity, removes the identity from the agent.
+.TP
+.B \-D
+Deletes all identities from the agent.
+
+.SH FILES
+.TP
+.I \&$HOME/\s+2.\s0ssh/identity
+Contains the RSA authentication identity of the user. This file
+should not be readable by anyone but the user. It is possible to
+specify a passphrase when generating the key; that passphrase will be
+used to encrypt the private part of this file. This is the
+default file added by
+.B ssh-add
+when no other files have been specified.
+.IP
+If
+.B ssh-add
+needs a passphrase, it will read the passphrase from the current
+terminal if it was run from a terminal. If
+.B ssh-add
+does not have a terminal associated with it but
+.SM DISPLAY\s0
+is set, it
+will open an X11 window to read the passphrase. This is particularly
+useful when calling
+.B ssh-add
+from a .Xsession or related script. (Note that on some machines it
+may be necessary to redirect the input from /dev/null to make this work.)
+
+.SH AUTHOR
+.LP
+Tatu Ylonen <ylo@cs.hut.fi>
+
+.SH SEE ALSO
+.BR ssh-agent (1),
+.BR ssh-keygen (1),
+.BR ssh (1),
+.BR sshd (8)
diff --git a/usr.bin/ssh/ssh-add.c b/usr.bin/ssh/ssh-add.c
new file mode 100644
index 00000000000..99a8ada1c9a
--- /dev/null
+++ b/usr.bin/ssh/ssh-add.c
@@ -0,0 +1,247 @@
+/*
+
+ssh-add.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Thu Apr 6 00:52:24 1995 ylo
+
+Adds an identity to the authentication server, or removes an identity.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: ssh-add.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $");
+
+#include "randoms.h"
+#include "rsa.h"
+#include "ssh.h"
+#include "xmalloc.h"
+#include "authfd.h"
+
+void delete_file(const char *filename)
+{
+ RSAPublicKey key;
+ char *comment;
+ AuthenticationConnection *ac;
+
+ if (!load_public_key(filename, &key, &comment))
+ {
+ printf("Bad key file %s: %s\n", filename, strerror(errno));
+ return;
+ }
+
+ /* Send the request to the authentication agent. */
+ ac = ssh_get_authentication_connection();
+ if (!ac)
+ {
+ fprintf(stderr,
+ "Could not open a connection to your authentication agent.\n");
+ rsa_clear_public_key(&key);
+ xfree(comment);
+ return;
+ }
+ if (ssh_remove_identity(ac, &key))
+ fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
+ else
+ fprintf(stderr, "Could not remove identity: %s\n", filename);
+ rsa_clear_public_key(&key);
+ xfree(comment);
+ ssh_close_authentication_connection(ac);
+}
+
+void delete_all()
+{
+ AuthenticationConnection *ac;
+
+ /* Get a connection to the agent. */
+ ac = ssh_get_authentication_connection();
+ if (!ac)
+ {
+ fprintf(stderr,
+ "Could not open a connection to your authentication agent.\n");
+ return;
+ }
+
+ /* Send a request to remove all identities. */
+ if (ssh_remove_all_identities(ac))
+ fprintf(stderr, "All identities removed.\n");
+ else
+ fprintf(stderr, "Failed to remove all identitities.\n");
+
+ /* Close the connection to the agent. */
+ ssh_close_authentication_connection(ac);
+}
+
+void add_file(const char *filename)
+{
+ RSAPrivateKey key;
+ RSAPublicKey public_key;
+ AuthenticationConnection *ac;
+ char *saved_comment, *comment, *pass;
+ int first;
+
+ if (!load_public_key(filename, &public_key, &saved_comment))
+ {
+ printf("Bad key file %s: %s\n", filename, strerror(errno));
+ return;
+ }
+ rsa_clear_public_key(&public_key);
+
+ pass = xstrdup("");
+ first = 1;
+ while (!load_private_key(filename, pass, &key, &comment))
+ {
+ char buf[1024];
+ FILE *f;
+
+ /* Free the old passphrase. */
+ memset(pass, 0, strlen(pass));
+ xfree(pass);
+
+ /* Ask for a passphrase. */
+ if (getenv("DISPLAY") && !isatty(fileno(stdin)))
+ {
+ sprintf(buf, "ssh-askpass '%sEnter passphrase for %.100s'",
+ first ? "" : "You entered wrong passphrase. ",
+ saved_comment);
+ f = popen(buf, "r");
+ if (!fgets(buf, sizeof(buf), f))
+ {
+ pclose(f);
+ xfree(saved_comment);
+ return;
+ }
+ pclose(f);
+ if (strchr(buf, '\n'))
+ *strchr(buf, '\n') = 0;
+ pass = xstrdup(buf);
+ }
+ else
+ {
+ if (first)
+ printf("Need passphrase for %s (%s).\n", filename, saved_comment);
+ else
+ printf("Bad passphrase.\n");
+ pass = read_passphrase("Enter passphrase: ", 1);
+ if (strcmp(pass, "") == 0)
+ {
+ xfree(saved_comment);
+ xfree(pass);
+ return;
+ }
+ }
+ first = 0;
+ }
+ memset(pass, 0, strlen(pass));
+ xfree(pass);
+
+ xfree(saved_comment);
+
+ /* Send the key to the authentication agent. */
+ ac = ssh_get_authentication_connection();
+ if (!ac)
+ {
+ fprintf(stderr,
+ "Could not open a connection to your authentication agent.\n");
+ rsa_clear_private_key(&key);
+ xfree(comment);
+ return;
+ }
+ if (ssh_add_identity(ac, &key, comment))
+ fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
+ else
+ fprintf(stderr, "Could not add identity: %s\n", filename);
+ rsa_clear_private_key(&key);
+ xfree(comment);
+ ssh_close_authentication_connection(ac);
+}
+
+void list_identities()
+{
+ AuthenticationConnection *ac;
+ MP_INT e, n;
+ int bits, status;
+ char *comment;
+ int had_identities;
+
+ ac = ssh_get_authentication_connection();
+ if (!ac)
+ {
+ fprintf(stderr, "Could not connect to authentication server.\n");
+ return;
+ }
+ mpz_init(&e);
+ mpz_init(&n);
+ had_identities = 0;
+ for (status = ssh_get_first_identity(ac, &bits, &e, &n, &comment);
+ status;
+ status = ssh_get_next_identity(ac, &bits, &e, &n, &comment))
+ {
+ had_identities = 1;
+ printf("%d ", bits);
+ mpz_out_str(stdout, 10, &e);
+ printf(" ");
+ mpz_out_str(stdout, 10, &n);
+ printf(" %s\n", comment);
+ xfree(comment);
+ }
+ mpz_clear(&e);
+ mpz_clear(&n);
+ if (!had_identities)
+ printf("The agent has no identities.\n");
+ ssh_close_authentication_connection(ac);
+}
+
+int main(int ac, char **av)
+{
+ struct passwd *pw;
+ char buf[1024];
+ int no_files = 1;
+ int i;
+ int deleting = 0;
+
+ for (i = 1; i < ac; i++)
+ {
+ if (strcmp(av[i], "-l") == 0)
+ {
+ list_identities();
+ no_files = 0; /* Don't default-add/delete if -l. */
+ continue;
+ }
+ if (strcmp(av[i], "-d") == 0)
+ {
+ deleting = 1;
+ continue;
+ }
+ if (strcmp(av[i], "-D") == 0)
+ {
+ delete_all();
+ no_files = 0;
+ continue;
+ }
+ no_files = 0;
+ if (deleting)
+ delete_file(av[i]);
+ else
+ add_file(av[i]);
+ }
+ if (no_files)
+ {
+ pw = getpwuid(getuid());
+ if (!pw)
+ {
+ fprintf(stderr, "No user found with uid %d\n", (int)getuid());
+ exit(1);
+ }
+ sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
+ if (deleting)
+ delete_file(buf);
+ else
+ add_file(buf);
+ }
+ exit(0);
+}
diff --git a/usr.bin/ssh/ssh-agent.1 b/usr.bin/ssh/ssh-agent.1
new file mode 100644
index 00000000000..4b396431ae1
--- /dev/null
+++ b/usr.bin/ssh/ssh-agent.1
@@ -0,0 +1,113 @@
+.\" -*- nroff -*-
+.\"
+.\" ssh-agent.1
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\"
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" Created: Sat Apr 23 20:10:43 1995 ylo
+.\"
+.\" $Id: ssh-agent.1,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+.\"
+.TH SSH-AGENT 1 "November 8, 1995" "SSH" "SSH"
+
+.SH NAME
+ssh-agent \- authentication agent
+
+.SH SYNOPSIS
+.LP
+.B ssh-agent
+.I command
+
+.SH DESCRIPTION
+.LP
+.B Ssh-agent
+is a program to hold authentication private keys. The
+idea is that
+.B ssh-agent
+is started in the beginning of an X-session or a login session, and
+all other windows or programs are started as children of the ssh-agent
+program (the
+.IR command
+normally starts X or is the user shell). Programs started under
+the agent inherit a connection to the agent, and the agent is
+automatically used for RSA authentication when logging to other
+machines using
+.B ssh.
+.LP
+The agent initially does not have any private keys. Keys are added
+using
+.B ssh-add.
+When executed without arguments,
+.B ssh-add
+adds the
+.I \&$HOME/\s+2.\s0ssh/identity
+file. If the identity has a passphrase,
+.B ssh-add
+asks for the passphrase (using a small X11 application if running
+under X11, or from the terminal if running without X). It then sends
+the identity to the agent. Several identities can be stored in the
+agent; the agent can automatically use any of these identities.
+.B "Ssh-add \-l
+displays the identities currently held by the agent.
+.LP
+The idea is that the agent is run in the user's local PC, laptop, or
+terminal. Authentication data need not be stored on any other
+machine, and authentication passphrases never go over the network.
+However, the connection to the agent is forwarded over
+.B ssh
+remote logins, and the user can thus use the privileges given by the
+identities anywhere in the network in a secure way.
+.LP
+A connection to the agent is inherited by child programs.
+There are two alternative
+methods for inheriting the agent. The preferred method is to have an
+open file descriptor which is inherited, and have an environment
+variable (\fB\s-1SSH_AUTHENTICATION_FD\s0\fR) contain the number of this
+descriptor. This restricts access to the authentication agent to only
+those programs that are siblings of the agent, and it is fairly
+difficult even for root to get unauthorized access to the agent.
+.LP
+On some machines, an alternative method is used. A unix-domain
+socket is created (\fI/tmp/ssh_agent.*\fR), and the name of this
+socket is stored in the
+.B \s-1SSH_AUTHENTICATION_SOCKET\s0
+environment
+variable. The socket is made accessible only to the current user.
+This method is easily abused by root or another instance of the same
+user. The socket is only used if ssh is unable to find a file
+descriptor that would not be closed by shells.
+.LP
+The agent exits automatically when the command given on the command
+line terminates.
+
+.SH FILES
+.TP
+.I \&$HOME/\s+2.\s0ssh/identity
+Contains the RSA authentication identity of the user. This file
+should not be readable by anyone but the user. It is possible to
+specify a passphrase when generating the key; that passphrase will be
+used to encrypt the private part of this file. This file
+is not used by
+.B ssh-agent,
+but is normally added to the agent using
+.B ssh-add
+at login time.
+.TP
+.I \&/tmp/ssh_agent.<pid>
+Unix-domain sockets used to contain the connection to the
+authentication agent. These sockets should only be readable by the
+owner. The sockets should get automatically removed when the agent
+exits.
+
+.SH AUTHOR
+.LP
+Tatu Ylonen <ylo@cs.hut.fi>
+
+.SH SEE ALSO
+.BR ssh-add (1),
+.BR ssh-keygen (1),
+.BR ssh (1),
+.BR sshd (8)
diff --git a/usr.bin/ssh/ssh-agent.c b/usr.bin/ssh/ssh-agent.c
new file mode 100644
index 00000000000..f038178ed5f
--- /dev/null
+++ b/usr.bin/ssh/ssh-agent.c
@@ -0,0 +1,629 @@
+/*
+
+ssh-agent.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Mar 29 03:46:59 1995 ylo
+
+The authentication agent program.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: ssh-agent.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $");
+
+#include "ssh.h"
+#include "rsa.h"
+#include "randoms.h"
+#include "authfd.h"
+#include "buffer.h"
+#include "bufaux.h"
+#include "xmalloc.h"
+#include "packet.h"
+#include "ssh_md5.h"
+#include "getput.h"
+#include "mpaux.h"
+
+typedef struct
+{
+ int fd;
+ enum { AUTH_UNUSED, AUTH_FD, AUTH_SOCKET, AUTH_SOCKET_FD,
+ AUTH_CONNECTION } type;
+ Buffer input;
+ Buffer output;
+} SocketEntry;
+
+unsigned int sockets_alloc = 0;
+SocketEntry *sockets = NULL;
+
+typedef struct
+{
+ RSAPrivateKey key;
+ char *comment;
+} Identity;
+
+unsigned int num_identities = 0;
+Identity *identities = NULL;
+
+int max_fd = 0;
+
+void process_request_identity(SocketEntry *e)
+{
+ Buffer msg;
+ int i;
+
+ buffer_init(&msg);
+ buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
+ buffer_put_int(&msg, num_identities);
+ for (i = 0; i < num_identities; i++)
+ {
+ buffer_put_int(&msg, identities[i].key.bits);
+ buffer_put_mp_int(&msg, &identities[i].key.e);
+ buffer_put_mp_int(&msg, &identities[i].key.n);
+ buffer_put_string(&msg, identities[i].comment,
+ strlen(identities[i].comment));
+ }
+ buffer_put_int(&e->output, buffer_len(&msg));
+ buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
+ buffer_free(&msg);
+}
+
+void process_authentication_challenge(SocketEntry *e)
+{
+ int i, pub_bits;
+ MP_INT pub_e, pub_n, challenge;
+ Buffer msg;
+ struct MD5Context md;
+ unsigned char buf[32], mdbuf[16], session_id[16];
+ unsigned int response_type;
+
+ buffer_init(&msg);
+ mpz_init(&pub_e);
+ mpz_init(&pub_n);
+ mpz_init(&challenge);
+ pub_bits = buffer_get_int(&e->input);
+ buffer_get_mp_int(&e->input, &pub_e);
+ buffer_get_mp_int(&e->input, &pub_n);
+ buffer_get_mp_int(&e->input, &challenge);
+ if (buffer_len(&e->input) == 0)
+ {
+ /* Compatibility code for old servers. */
+ memset(session_id, 0, 16);
+ response_type = 0;
+ }
+ else
+ {
+ /* New code. */
+ buffer_get(&e->input, (char *)session_id, 16);
+ response_type = buffer_get_int(&e->input);
+ }
+ for (i = 0; i < num_identities; i++)
+ if (pub_bits == identities[i].key.bits &&
+ mpz_cmp(&pub_e, &identities[i].key.e) == 0 &&
+ mpz_cmp(&pub_n, &identities[i].key.n) == 0)
+ {
+ /* Decrypt the challenge using the private key. */
+ rsa_private_decrypt(&challenge, &challenge, &identities[i].key);
+
+ /* Compute the desired response. */
+ switch (response_type)
+ {
+ case 0: /* As of protocol 1.0 */
+ /* This response type is no longer supported. */
+ log("Compatibility with ssh protocol 1.0 no longer supported.");
+ buffer_put_char(&msg, SSH_AGENT_FAILURE);
+ goto send;
+
+ case 1: /* As of protocol 1.1 */
+ /* The response is MD5 of decrypted challenge plus session id. */
+ mp_linearize_msb_first(buf, 32, &challenge);
+ MD5Init(&md);
+ MD5Update(&md, buf, 32);
+ MD5Update(&md, session_id, 16);
+ MD5Final(mdbuf, &md);
+ break;
+
+ default:
+ fatal("process_authentication_challenge: bad response_type %d",
+ response_type);
+ break;
+ }
+
+ /* Send the response. */
+ buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
+ for (i = 0; i < 16; i++)
+ buffer_put_char(&msg, mdbuf[i]);
+
+ goto send;
+ }
+ /* Unknown identity. Send failure. */
+ buffer_put_char(&msg, SSH_AGENT_FAILURE);
+ send:
+ buffer_put_int(&e->output, buffer_len(&msg));
+ buffer_append(&e->output, buffer_ptr(&msg),
+ buffer_len(&msg));
+ buffer_free(&msg);
+ mpz_clear(&pub_e);
+ mpz_clear(&pub_n);
+ mpz_clear(&challenge);
+}
+
+void process_remove_identity(SocketEntry *e)
+{
+ unsigned int bits;
+ MP_INT dummy, n;
+ unsigned int i;
+
+ mpz_init(&dummy);
+ mpz_init(&n);
+
+ /* Get the key from the packet. */
+ bits = buffer_get_int(&e->input);
+ buffer_get_mp_int(&e->input, &dummy);
+ buffer_get_mp_int(&e->input, &n);
+
+ /* Check if we have the key. */
+ for (i = 0; i < num_identities; i++)
+ if (mpz_cmp(&identities[i].key.n, &n) == 0)
+ {
+ /* We have this key. Free the old key. Since we don\'t want to leave
+ empty slots in the middle of the array, we actually free the
+ key there and copy data from the last entry. */
+ rsa_clear_private_key(&identities[i].key);
+ xfree(identities[i].comment);
+ if (i < num_identities - 1)
+ identities[i] = identities[num_identities - 1];
+ num_identities--;
+ mpz_clear(&dummy);
+ mpz_clear(&n);
+
+ /* Send success. */
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
+ return;
+ }
+ /* We did not have the key. */
+ mpz_clear(&dummy);
+ mpz_clear(&n);
+
+ /* Send failure. */
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output, SSH_AGENT_FAILURE);
+}
+
+/* Removes all identities from the agent. */
+
+void process_remove_all_identities(SocketEntry *e)
+{
+ unsigned int i;
+
+ /* Loop over all identities and clear the keys. */
+ for (i = 0; i < num_identities; i++)
+ {
+ rsa_clear_private_key(&identities[i].key);
+ xfree(identities[i].comment);
+ }
+
+ /* Mark that there are no identities. */
+ num_identities = 0;
+
+ /* Send success. */
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
+ return;
+}
+
+/* Adds an identity to the agent. */
+
+void process_add_identity(SocketEntry *e)
+{
+ RSAPrivateKey *k;
+ int i;
+
+ if (num_identities == 0)
+ identities = xmalloc(sizeof(Identity));
+ else
+ identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));
+ k = &identities[num_identities].key;
+ k->bits = buffer_get_int(&e->input);
+ mpz_init(&k->n);
+ buffer_get_mp_int(&e->input, &k->n);
+ mpz_init(&k->e);
+ buffer_get_mp_int(&e->input, &k->e);
+ mpz_init(&k->d);
+ buffer_get_mp_int(&e->input, &k->d);
+ mpz_init(&k->u);
+ buffer_get_mp_int(&e->input, &k->u);
+ mpz_init(&k->p);
+ buffer_get_mp_int(&e->input, &k->p);
+ mpz_init(&k->q);
+ buffer_get_mp_int(&e->input, &k->q);
+ identities[num_identities].comment = buffer_get_string(&e->input, NULL);
+
+ /* Check if we already have the key. */
+ for (i = 0; i < num_identities; i++)
+ if (mpz_cmp(&identities[i].key.n, &k->n) == 0)
+ {
+ /* We already have this key. Clear and free the new data and
+ return success. */
+ rsa_clear_private_key(k);
+ xfree(identities[num_identities].comment);
+
+ /* Send success. */
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
+ return;
+ }
+
+ /* Increment the number of identities. */
+ num_identities++;
+
+ /* Send a success message. */
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
+}
+
+void process_message(SocketEntry *e)
+{
+ unsigned int msg_len;
+ unsigned int type;
+ unsigned char *cp;
+ if (buffer_len(&e->input) < 5)
+ return; /* Incomplete message. */
+ cp = (unsigned char *)buffer_ptr(&e->input);
+ msg_len = GET_32BIT(cp);
+ if (msg_len > 256 * 1024)
+ {
+ shutdown(e->fd, 2);
+ close(e->fd);
+ e->type = AUTH_UNUSED;
+ return;
+ }
+ if (buffer_len(&e->input) < msg_len + 4)
+ return;
+ buffer_consume(&e->input, 4);
+ type = buffer_get_char(&e->input);
+ switch (type)
+ {
+ case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
+ process_request_identity(e);
+ break;
+ case SSH_AGENTC_RSA_CHALLENGE:
+ process_authentication_challenge(e);
+ break;
+ case SSH_AGENTC_ADD_RSA_IDENTITY:
+ process_add_identity(e);
+ break;
+ case SSH_AGENTC_REMOVE_RSA_IDENTITY:
+ process_remove_identity(e);
+ break;
+ case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
+ process_remove_all_identities(e);
+ break;
+ default:
+ /* Unknown message. Respond with failure. */
+ error("Unknown message %d", type);
+ buffer_clear(&e->input);
+ buffer_put_int(&e->output, 1);
+ buffer_put_char(&e->output, SSH_AGENT_FAILURE);
+ break;
+ }
+}
+
+void new_socket(int type, int fd)
+{
+ unsigned int i, old_alloc;
+#if defined(O_NONBLOCK) && !defined(O_NONBLOCK_BROKEN)
+ if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
+ error("fcntl O_NONBLOCK: %s", strerror(errno));
+#else /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+ if (fcntl(fd, F_SETFL, O_NDELAY) < 0)
+ error("fcntl O_NDELAY: %s", strerror(errno));
+#endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */
+
+ if (fd > max_fd)
+ max_fd = fd;
+
+ for (i = 0; i < sockets_alloc; i++)
+ if (sockets[i].type == AUTH_UNUSED)
+ {
+ sockets[i].fd = fd;
+ sockets[i].type = type;
+ buffer_init(&sockets[i].input);
+ buffer_init(&sockets[i].output);
+ return;
+ }
+ old_alloc = sockets_alloc;
+ sockets_alloc += 10;
+ if (sockets)
+ sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
+ else
+ sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
+ for (i = old_alloc; i < sockets_alloc; i++)
+ sockets[i].type = AUTH_UNUSED;
+ sockets[old_alloc].type = type;
+ sockets[old_alloc].fd = fd;
+ buffer_init(&sockets[old_alloc].input);
+ buffer_init(&sockets[old_alloc].output);
+}
+
+void prepare_select(fd_set *readset, fd_set *writeset)
+{
+ unsigned int i;
+ for (i = 0; i < sockets_alloc; i++)
+ switch (sockets[i].type)
+ {
+ case AUTH_FD:
+ case AUTH_CONNECTION:
+ case AUTH_SOCKET:
+ case AUTH_SOCKET_FD:
+ FD_SET(sockets[i].fd, readset);
+ if (buffer_len(&sockets[i].output) > 0)
+ FD_SET(sockets[i].fd, writeset);
+ break;
+ case AUTH_UNUSED:
+ break;
+ default:
+ fatal("Unknown socket type %d", sockets[i].type);
+ break;
+ }
+}
+
+void after_select(fd_set *readset, fd_set *writeset)
+{
+ unsigned int i;
+ int len, sock, port;
+ char buf[1024];
+ struct sockaddr_in sin;
+ struct sockaddr_un sunaddr;
+
+ for (i = 0; i < sockets_alloc; i++)
+ switch (sockets[i].type)
+ {
+ case AUTH_UNUSED:
+ break;
+ case AUTH_FD:
+ if (FD_ISSET(sockets[i].fd, readset))
+ {
+ len = recv(sockets[i].fd, buf, sizeof(buf), 0);
+ if (len <= 0)
+ { /* All instances of the other side have been closed. */
+ log("Authentication agent exiting.");
+ exit(0);
+ }
+ process_auth_fd_input:
+ if (len != 3 || (unsigned char)buf[0] != SSH_AUTHFD_CONNECT)
+ break; /* Incorrect message; ignore it. */
+ /* It is a connection request message. */
+ port = (unsigned char)buf[1] * 256 + (unsigned char)buf[2];
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(0x7f000001); /* localhost */
+ sin.sin_port = htons(port);
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ perror("socket");
+ break;
+ }
+ if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ {
+ perror("connecting to port requested in authfd message");
+ close(sock);
+ break;
+ }
+ new_socket(AUTH_CONNECTION, sock);
+ }
+ break;
+ case AUTH_SOCKET:
+ if (FD_ISSET(sockets[i].fd, readset))
+ {
+ len = sizeof(sunaddr);
+ sock = accept(sockets[i].fd, (struct sockaddr *)&sunaddr, &len);
+ if (sock < 0)
+ {
+ perror("accept from AUTH_SOCKET");
+ break;
+ }
+ new_socket(AUTH_SOCKET_FD, sock);
+ }
+ break;
+ case AUTH_SOCKET_FD:
+ if (FD_ISSET(sockets[i].fd, readset))
+ {
+ len = recv(sockets[i].fd, buf, sizeof(buf), 0);
+ if (len <= 0)
+ { /* The other side has closed the socket. */
+ shutdown(sockets[i].fd, 2);
+ close(sockets[i].fd);
+ sockets[i].type = AUTH_UNUSED;
+ break;
+ }
+ goto process_auth_fd_input;
+ }
+ break;
+ case AUTH_CONNECTION:
+ if (buffer_len(&sockets[i].output) > 0 &&
+ FD_ISSET(sockets[i].fd, writeset))
+ {
+ len = write(sockets[i].fd, buffer_ptr(&sockets[i].output),
+ buffer_len(&sockets[i].output));
+ if (len <= 0)
+ {
+ shutdown(sockets[i].fd, 2);
+ close(sockets[i].fd);
+ sockets[i].type = AUTH_UNUSED;
+ break;
+ }
+ buffer_consume(&sockets[i].output, len);
+ }
+ if (FD_ISSET(sockets[i].fd, readset))
+ {
+ len = read(sockets[i].fd, buf, sizeof(buf));
+ if (len <= 0)
+ {
+ shutdown(sockets[i].fd, 2);
+ close(sockets[i].fd);
+ sockets[i].type = AUTH_UNUSED;
+ break;
+ }
+ buffer_append(&sockets[i].input, buf, len);
+ process_message(&sockets[i]);
+ }
+ break;
+ default:
+ fatal("Unknown type %d", sockets[i].type);
+ }
+}
+
+int parent_pid = -1;
+char socket_name[1024];
+
+RETSIGTYPE check_parent_exists(int sig)
+{
+ if (kill(parent_pid, 0) < 0)
+ {
+ remove(socket_name);
+ /* printf("Parent has died - Authentication agent exiting.\n"); */
+ exit(1);
+ }
+ signal(SIGALRM, check_parent_exists);
+ alarm(10);
+}
+
+int main(int ac, char **av)
+{
+ fd_set readset, writeset;
+ char buf[1024];
+ int pfd;
+ int sock;
+ struct sockaddr_un sunaddr;
+
+ int sockets[2], i;
+ int *dups;
+
+ if (ac < 2)
+ {
+ fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
+ fprintf(stderr, "Usage: %s command\n", av[0]);
+ exit(1);
+ }
+
+ pfd = get_permanent_fd(NULL);
+ if (pfd < 0)
+ {
+ /* The agent uses SSH_AUTHENTICATION_SOCKET. */
+
+ parent_pid = getpid();
+
+ sprintf(socket_name, SSH_AGENT_SOCKET, parent_pid);
+
+ /* Fork, and have the parent execute the command. The child continues as
+ the authentication agent. */
+ if (fork() != 0)
+ { /* Parent - execute the given command. */
+ sprintf(buf, "SSH_AUTHENTICATION_SOCKET=%s", socket_name);
+ putenv(buf);
+ execvp(av[1], av + 1);
+ perror(av[1]);
+ exit(1);
+ }
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0)
+ {
+ perror("socket");
+ exit(1);
+ }
+ memset(&sunaddr, 0, sizeof(sunaddr));
+ sunaddr.sun_family = AF_UNIX;
+ strncpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
+ if (bind(sock, (struct sockaddr *)&sunaddr, AF_UNIX_SIZE(sunaddr)) < 0)
+ {
+ perror("bind");
+ exit(1);
+ }
+ if (chmod(socket_name, 0700) < 0)
+ {
+ perror("chmod");
+ exit(1);
+ }
+ if (listen(sock, 5) < 0)
+ {
+ perror("listen");
+ exit(1);
+ }
+ new_socket(AUTH_SOCKET, sock);
+ signal(SIGALRM, check_parent_exists);
+ alarm(10);
+ }
+ else
+ {
+ /* The agent uses SSH_AUTHENTICATION_FD. */
+ int cnt, newfd;
+
+ dups = xmalloc(sizeof (int) * (1 + pfd));
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
+ {
+ perror("socketpair");
+ exit(1);
+ }
+
+ /* Dup some descriptors to get the authentication fd to pfd,
+ because some shells arbitrarily close descriptors below that.
+ Don't use dup2 because maybe some systems don't have it?? */
+ for (cnt = 0;; cnt++) {
+ if ((dups[cnt] = dup(0)) < 0)
+ fatal("auth_input_request_forwarding: dup failed");
+ if (dups[cnt] == pfd)
+ break;
+ }
+ close(dups[cnt]);
+
+ /* Move the file descriptor we pass to children up high where
+ the shell won't close it. */
+ newfd = dup(sockets[1]);
+ if (newfd != pfd)
+ fatal("auth_input_request_forwarding: dup didn't return %d.", pfd);
+ close(sockets[1]);
+ sockets[1] = newfd;
+ /* Close duped descriptors. */
+ for (i = 0; i < cnt; i++)
+ close(dups[i]);
+ free(dups);
+
+ if (fork() != 0)
+ { /* Parent - execute the given command. */
+ close(sockets[0]);
+ sprintf(buf, "SSH_AUTHENTICATION_FD=%d", sockets[1]);
+ putenv(buf);
+ execvp(av[1], av + 1);
+ perror(av[1]);
+ exit(1);
+ }
+ close(sockets[1]);
+ new_socket(AUTH_FD, sockets[0]);
+ }
+
+ signal(SIGINT, SIG_IGN);
+ while (1)
+ {
+ FD_ZERO(&readset);
+ FD_ZERO(&writeset);
+ prepare_select(&readset, &writeset);
+ if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ perror("select");
+ exit(1);
+ }
+ after_select(&readset, &writeset);
+ }
+ /*NOTREACHED*/
+}
diff --git a/usr.bin/ssh/ssh-askpass.wish b/usr.bin/ssh/ssh-askpass.wish
new file mode 100644
index 00000000000..5e8d3d897d3
--- /dev/null
+++ b/usr.bin/ssh/ssh-askpass.wish
@@ -0,0 +1,48 @@
+# This file (ssh-askpass.wish) will be used to create ssh-askpass by-*- tcl -*-
+# prepending the header line that executes wish.
+#
+# $Id: ssh-askpass.wish,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+#
+
+global result
+
+wm title . "Authentication Password Entry"
+
+# Use the first argument as a prompt (if given).
+if {$argv==""} {
+ label .header -text "Please enter your authentication password"
+} {
+ label .header -text "[lindex $argv 0]"
+}
+
+entry .pass -relief sunken -textvariable password
+set bgcolor [lindex [.pass configure -bg] 3]
+.pass configure -fg $bgcolor -selectforeground $bgcolor \
+ -selectbackground $bgcolor
+
+bind .pass <Return> { set result ok }
+frame .b
+frame .b.ok_f -borderwidth 2 -relief sunken
+button .b.ok -text OK -width 6 -command { set result ok }
+button .b.cancel -text Cancel -width 6 -command { set result cancel }
+pack .b.ok -in .b.ok_f -padx 2 -pady 2
+pack .b.ok_f -side left -padx 5m -pady 3m
+pack .b.cancel -side right -padx 5m -pady 3m
+pack .header .pass .b
+wm protocol . WM_DELETE_WINDOW { set result cancel }
+
+set old_focus [focus]
+grab set .
+focus .pass
+
+set result "none"
+
+while {"$result" == "none"} {
+ tkwait variable result
+}
+
+if {$old_focus!=""} {
+ focus $old_focus
+}
+
+if {"$result" == "ok"} {puts "$password"; exit 0} {exit 1}
diff --git a/usr.bin/ssh/ssh-keygen.1 b/usr.bin/ssh/ssh-keygen.1
new file mode 100644
index 00000000000..2bf44eec33c
--- /dev/null
+++ b/usr.bin/ssh/ssh-keygen.1
@@ -0,0 +1,143 @@
+.\" -*- nroff -*-
+.\"
+.\" ssh-keygen.1
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\"
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" Created: Sat Apr 22 23:55:14 1995 ylo
+.\"
+.\" $Id: ssh-keygen.1,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+.\"
+.TH SSH-KEYGEN 1 "November 8, 1995" "SSH" "SSH"
+
+.SH NAME
+ssh-keygen \- authentication key generation
+
+.SH SYNOPSIS
+.LP
+.B ssh-keygen
+[\c
+.BI \-b \ bits\c
+]
+[\c
+.BI \-N \ new_passphrase\c
+]
+[\c
+.BI \-C \ comment\c
+]
+
+.B "ssh-keygen \-p
+[\c
+.BI \-P \ old_passphrase\c
+]
+[\c
+.BI \-N \ new_passphrase\c
+]
+
+.B "ssh-keygen \-c
+[\c
+.BI \-P \ passphrase\c
+]
+[\c
+.BI \-C \ comment\c
+]
+
+.SH DESCRIPTION
+.LP
+.B Ssh-keygen
+generates and manages authentication keys for
+.BR ssh (1).
+Normally each user wishing to use
+.B ssh
+with RSA authentication runs this once to create the authentication
+key in
+.IR \&$HOME/\s+2.\s0ssh/identity ".
+Additionally, the system administrator may use this to generate host keys.
+.LP
+Normally this program generates the key and asks for a file in which
+to store the private key. The public key is stored in a file with the
+same name but ".pub" appended. The program also asks for a
+passphrase. The passphrase may be empty to indicate no passphrase
+(host keys must have empty passphrase), or it may be a string of
+arbitrary length. Good passphrases are 10-30 characters long and are
+not simple sentences or otherwise easily guessable (English
+prose has only 1-2 bits of entropy per word, and provides very bad
+passphrases). The passphrase can be changed later by using the
+.B \-p
+option.
+.LP
+There is no way to recover a lost passphrase. If the passphrase is
+lost or forgotten, you will have to generate a new key and copy the
+corresponding public key to other machines.
+.LP
+There is also a comment field in the key file that is only for
+convenience to the user to help identify the key. The comment can
+tell what the key is for, or whatever is useful. The comment is
+initialized to user@host when the key is created, but can be changed
+using the
+.B \-c
+option.
+
+.SH OPTIONS
+.TP 0.6i
+.BI \-b \ bits
+Specifies the number of bits in the key to create. Minimum is 512
+bits. Generally 1024 bits is considered sufficient, and key sizes
+above that no longer improve security but make things slower. The
+default is 1024 bits.
+.TP
+.B \-c
+Requests changing the comment in the private and public key files.
+The program will prompt for the file containing the private keys, for
+passphrase if the key has one, and for the new comment.
+.TP
+.B \-p
+Requests changing the passphrase of a private key file instead of
+creating a new private key. The program will prompt for the file
+containing the private key, for the old passphrase, and twice for the
+new passphrase.
+.TP
+.B \-C
+Provides the new comment.
+.TP
+.B \-N
+Provides the new passphrase.
+.TP
+.B \-P
+Provides the (old) passphrase.
+
+.SH FILES
+.TP 0.6i
+.I \&$HOME/\s+2.\s0ssh/random_seed
+Used for seeding the random number generator. This file should not be
+readable by anyone but the user. This file is created the first time
+the program is run, and is updated every time.
+.TP
+.I \&$HOME/\s+2.\s0ssh/identity
+Contains the RSA authentication identity of the user. This file
+should not be readable by anyone but the user. It is possible to
+specify a passphrase when generating the key; that passphrase will be
+used to encrypt the private part of this file using IDEA. This file
+is not automatically accessed by
+.BR ssh-keygen ",
+but it is offered as the default file for the private key.
+.TP
+.I \&$HOME/\s+2.\s0ssh/identity.pub
+Contains the public key for authentication. The contents of this file
+should be added to \f4$HOME/\s+2.\s0ssh/authorized_keys\f1 on all machines
+where you wish to log in using RSA authentication. There is no
+need to keep the contents of this file secret.
+
+.SH AUTHOR
+.LP
+Tatu Ylonen <ylo@cs.hut.fi>
+
+.SH SEE ALSO
+.LP
+.BR ssh (1),
+.BR sshd (8),
+.BR ssh-agent (1),
+.BR ssh-add (1)
diff --git a/usr.bin/ssh/ssh-keygen.c b/usr.bin/ssh/ssh-keygen.c
new file mode 100644
index 00000000000..0ff98cde1cc
--- /dev/null
+++ b/usr.bin/ssh/ssh-keygen.c
@@ -0,0 +1,552 @@
+/*
+
+ssh-keygen.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Mar 27 02:26:40 1995 ylo
+
+Identity and host key generation and maintenance.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: ssh-keygen.c,v 1.1 1999/09/26 20:53:37 deraadt Exp $");
+
+#ifndef HAVE_GETHOSTNAME
+#include <sys/utsname.h>
+#endif
+#include "randoms.h"
+#include "rsa.h"
+#include "ssh.h"
+#include "xmalloc.h"
+
+/* Generated private key. */
+RSAPrivateKey private_key;
+
+/* Generated public key. */
+RSAPublicKey public_key;
+
+/* Random number generator state. */
+RandomState state;
+
+/* Number of bits in the RSA key. This value can be changed on the command
+ line. */
+int bits = 1024;
+
+/* Flag indicating that we just want to change the passphrase. This can be
+ set on the command line. */
+int change_passphrase = 0;
+
+/* Flag indicating that we just want to change the comment. This can be set
+ on the command line. */
+int change_comment = 0;
+
+/* This is set to the identity file name if given on the command line. */
+char *identity_file = NULL;
+
+/* This is set to the passphrase if given on the command line. */
+char *identity_passphrase = NULL;
+
+/* This is set to the new passphrase if given on the command line. */
+char *identity_new_passphrase = NULL;
+
+/* This is set to the new comment if given on the command line. */
+char *identity_comment = NULL;
+
+/* Perform changing a passphrase. The argument is the passwd structure
+ for the current user. */
+
+void do_change_passphrase(struct passwd *pw)
+{
+ char buf[1024], *comment;
+ RSAPrivateKey private_key;
+ char *old_passphrase, *passphrase1, *passphrase2;
+ struct stat st;
+
+ /* Read key file name. */
+ if (identity_file != NULL)
+ {
+ strncpy(buf, identity_file, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ }
+ else
+ {
+ printf("Enter file in which the key is ($HOME/%s): ",
+ SSH_CLIENT_IDENTITY);
+ fflush(stdout);
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ exit(1);
+ if (strchr(buf, '\n'))
+ *strchr(buf, '\n') = 0;
+ if (strcmp(buf, "") == 0)
+ sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
+ }
+
+ /* Check if the file exists. */
+ if (stat(buf, &st) < 0)
+ {
+ perror(buf);
+ exit(1);
+ }
+
+ /* Try to load the public key from the file the verify that it is
+ readable and of the proper format. */
+ if (!load_public_key(buf, &public_key, NULL))
+ {
+ printf("%s is not a valid key file.\n", buf);
+ exit(1);
+ }
+ /* Clear the public key since we are just about to load the whole file. */
+ rsa_clear_public_key(&public_key);
+
+ /* Try to load the file with empty passphrase. */
+ if (!load_private_key(buf, "", &private_key, &comment))
+ {
+ /* Read passphrase from the user. */
+ if (identity_passphrase)
+ old_passphrase = xstrdup(identity_passphrase);
+ else
+ old_passphrase = read_passphrase("Enter old passphrase: ", 1);
+ /* Try to load using the passphrase. */
+ if (!load_private_key(buf, old_passphrase, &private_key, &comment))
+ {
+ memset(old_passphrase, 0, strlen(old_passphrase));
+ xfree(old_passphrase);
+ printf("Bad passphrase.\n");
+ exit(1);
+ }
+ /* Destroy the passphrase. */
+ memset(old_passphrase, 0, strlen(old_passphrase));
+ xfree(old_passphrase);
+ }
+ printf("Key has comment '%s'\n", comment);
+
+ /* Ask the new passphrase (twice). */
+ if (identity_new_passphrase)
+ {
+ passphrase1 = xstrdup(identity_new_passphrase);
+ passphrase2 = NULL;
+ }
+ else
+ {
+ passphrase1 =
+ read_passphrase("Enter new passphrase (empty for no passphrase): ", 1);
+ passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
+
+ /* Verify that they are the same. */
+ if (strcmp(passphrase1, passphrase2) != 0)
+ {
+ memset(passphrase1, 0, strlen(passphrase1));
+ memset(passphrase2, 0, strlen(passphrase2));
+ xfree(passphrase1);
+ xfree(passphrase2);
+ printf("Pass phrases do not match. Try again.\n");
+ exit(1);
+ }
+ /* Destroy the other copy. */
+ memset(passphrase2, 0, strlen(passphrase2));
+ xfree(passphrase2);
+ }
+
+ /* Save the file using the new passphrase. */
+ if (!save_private_key(buf, passphrase1, &private_key, comment, &state))
+ {
+ printf("Saving the key failed: %s: %s.\n",
+ buf, strerror(errno));
+ memset(passphrase1, 0, strlen(passphrase1));
+ xfree(passphrase1);
+ rsa_clear_private_key(&private_key);
+ xfree(comment);
+ exit(1);
+ }
+ /* Destroy the passphrase and the copy of the key in memory. */
+ memset(passphrase1, 0, strlen(passphrase1));
+ xfree(passphrase1);
+ rsa_clear_private_key(&private_key);
+ xfree(comment);
+
+ printf("Your identification has been saved with the new passphrase.\n");
+ exit(0);
+}
+
+/* Change the comment of a private key file. */
+
+void do_change_comment(struct passwd *pw)
+{
+ char buf[1024], new_comment[1024], *comment;
+ RSAPrivateKey private_key;
+ char *passphrase;
+ struct stat st;
+ FILE *f;
+
+ /* Read key file name. */
+ if (identity_file)
+ {
+ strncpy(buf, identity_file, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ }
+ else
+ {
+ printf("Enter file in which the key is ($HOME/%s): ",
+ SSH_CLIENT_IDENTITY);
+ fflush(stdout);
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ exit(1);
+ if (strchr(buf, '\n'))
+ *strchr(buf, '\n') = 0;
+ if (strcmp(buf, "") == 0)
+ sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
+ }
+
+ /* Check if the file exists. */
+ if (stat(buf, &st) < 0)
+ {
+ perror(buf);
+ exit(1);
+ }
+
+ /* Try to load the public key from the file the verify that it is
+ readable and of the proper format. */
+ if (!load_public_key(buf, &public_key, NULL))
+ {
+ printf("%s is not a valid key file.\n", buf);
+ exit(1);
+ }
+
+ /* Try to load the file with empty passphrase. */
+ if (load_private_key(buf, "", &private_key, &comment))
+ passphrase = xstrdup("");
+ else
+ {
+ /* Read passphrase from the user. */
+ if (identity_passphrase)
+ passphrase = xstrdup(identity_passphrase);
+ else
+ if (identity_new_passphrase)
+ passphrase = xstrdup(identity_new_passphrase);
+ else
+ passphrase = read_passphrase("Enter passphrase: ", 1);
+ /* Try to load using the passphrase. */
+ if (!load_private_key(buf, passphrase, &private_key, &comment))
+ {
+ memset(passphrase, 0, strlen(passphrase));
+ xfree(passphrase);
+ printf("Bad passphrase.\n");
+ exit(1);
+ }
+ }
+ printf("Key now has comment '%s'\n", comment);
+
+ if (identity_comment)
+ {
+ strncpy(new_comment, identity_comment, sizeof(new_comment));
+ new_comment[sizeof(new_comment) - 1] = '\0';
+ }
+ else
+ {
+ printf("Enter new comment: ");
+ fflush(stdout);
+ if (!fgets(new_comment, sizeof(new_comment), stdin))
+ {
+ memset(passphrase, 0, strlen(passphrase));
+ rsa_clear_private_key(&private_key);
+ exit(1);
+ }
+
+ /* Remove terminating newline from comment. */
+ if (strchr(new_comment, '\n'))
+ *strchr(new_comment, '\n') = 0;
+ }
+
+ /* Save the file using the new passphrase. */
+ if (!save_private_key(buf, passphrase, &private_key, new_comment,
+ &state))
+ {
+ printf("Saving the key failed: %s: %s.\n",
+ buf, strerror(errno));
+ memset(passphrase, 0, strlen(passphrase));
+ xfree(passphrase);
+ rsa_clear_private_key(&private_key);
+ xfree(comment);
+ exit(1);
+ }
+
+ /* Destroy the passphrase and the private key in memory. */
+ memset(passphrase, 0, strlen(passphrase));
+ xfree(passphrase);
+ rsa_clear_private_key(&private_key);
+
+ /* Save the public key in text format in a file with the same name but
+ .pub appended. */
+ strcat(buf, ".pub");
+ f = fopen(buf, "w");
+ if (!f)
+ {
+ printf("Could not save your public key in %s\n", buf);
+ exit(1);
+ }
+ fprintf(f, "%d ", public_key.bits);
+ mpz_out_str(f, 10, &public_key.e);
+ fprintf(f, " ");
+ mpz_out_str(f, 10, &public_key.n);
+ fprintf(f, " %s\n", new_comment);
+ fclose(f);
+
+ xfree(comment);
+
+ printf("The comment in your key file has been changed.\n");
+ exit(0);
+}
+
+/* Main program for key management. */
+
+int main(int ac, char **av)
+{
+ char buf[16384], buf2[1024], *passphrase1, *passphrase2;
+ struct passwd *pw;
+ int opt;
+ struct stat st;
+ FILE *f;
+#ifdef HAVE_GETHOSTNAME
+ char hostname[257];
+#else
+ struct utsname uts;
+#endif
+ extern int optind;
+ extern char *optarg;
+
+ /* Get user\'s passwd structure. We need this for the home directory. */
+ pw = getpwuid(getuid());
+ if (!pw)
+ {
+ printf("You don't exist, go away!\n");
+ exit(1);
+ }
+
+ /* Create ~/.ssh directory if it doesn\'t already exist. */
+ sprintf(buf, "%s/%s", pw->pw_dir, SSH_USER_DIR);
+ if (stat(buf, &st) < 0)
+ if (mkdir(buf, 0755) < 0)
+ error("Could not create directory '%s'.", buf);
+
+ /* Parse command line arguments. */
+ while ((opt = getopt(ac, av, "pcb:f:P:N:C:")) != EOF)
+ {
+ switch (opt)
+ {
+ case 'b':
+ bits = atoi(optarg);
+ if (bits < 512 || bits > 32768)
+ {
+ printf("Bits has bad value.\n");
+ exit(1);
+ }
+ break;
+
+ case 'p':
+ change_passphrase = 1;
+ break;
+
+ case 'c':
+ change_comment = 1;
+ break;
+
+ case 'f':
+ identity_file = optarg;
+ break;
+
+ case 'P':
+ identity_passphrase = optarg;
+ break;
+
+ case 'N':
+ identity_new_passphrase = optarg;
+ break;
+
+ case 'C':
+ identity_comment = optarg;
+ break;
+
+ case '?':
+ default:
+ printf("ssh-keygen version %s\n", SSH_VERSION);
+ printf("Usage: %s [-b bits] [-p] [-c] [-f file] [-P pass] [-N new-pass] [-C comment]\n", av[0]);
+ exit(1);
+ }
+ }
+ if (optind < ac)
+ {
+ printf("Too many arguments.\n");
+ exit(1);
+ }
+ if (change_passphrase && change_comment)
+ {
+ printf("Can only have one of -p and -c.\n");
+ exit(1);
+ }
+
+ /* If the user requested to change the passphrase, do it now. This
+ function never returns. */
+ if (change_passphrase)
+ do_change_passphrase(pw);
+
+ /* If the user requested to change the comment, do it now. This function
+ never returns. */
+ if (change_comment)
+ do_change_comment(pw);
+
+ /* Initialize random number generator. This may take a while if the
+ user has no seed file, so display a message to the user. */
+ printf("Initializing random number generator...\n");
+ sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_SEEDFILE);
+ random_initialize(&state, buf);
+
+ /* Save random seed so we don\'t need to do all that time-consuming
+ environmental noise collection the next time. */
+ random_save(&state, buf);
+
+ /* Generate the rsa key pair. */
+ rsa_generate_key(&private_key, &public_key, &state, bits);
+
+ /* Save the state again, just to remove any fear that the previous state
+ could be used to recreate the key. (That should not be possible anyway
+ since the pool is stirred after save and some noise is added.) */
+ random_save(&state, buf);
+
+ ask_file_again:
+
+ /* Ask for a file to save the key in. */
+ if (identity_file)
+ {
+ strncpy(buf, identity_file, sizeof(buf));
+ buf[sizeof(buf) - 1] = '\0';
+ }
+ else
+ {
+ printf("Enter file in which to save the key ($HOME/%s): ",
+ SSH_CLIENT_IDENTITY);
+ fflush(stdout);
+ if (fgets(buf, sizeof(buf), stdin) == NULL)
+ exit(1);
+ if (strchr(buf, '\n'))
+ *strchr(buf, '\n') = 0;
+ if (strcmp(buf, "") == 0)
+ sprintf(buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
+ }
+
+ /* If the file aready exists, ask the user to confirm. */
+ if (stat(buf, &st) >= 0)
+ {
+ printf("%s already exists.\n", buf);
+ printf("Overwrite (y/n)? ");
+ fflush(stdout);
+ if (fgets(buf2, sizeof(buf2), stdin) == NULL)
+ exit(1);
+ if (buf2[0] != 'y' && buf2[0] != 'Y')
+ exit(1);
+ }
+
+ /* Ask for a passphrase (twice). */
+ if (identity_passphrase)
+ passphrase1 = xstrdup(identity_passphrase);
+ else
+ if (identity_new_passphrase)
+ passphrase1 = xstrdup(identity_new_passphrase);
+ else
+ {
+ passphrase_again:
+ passphrase1 =
+ read_passphrase("Enter passphrase (empty for no passphrase): ", 1);
+ passphrase2 = read_passphrase("Enter same passphrase again: ", 1);
+ if (strcmp(passphrase1, passphrase2) != 0)
+ {
+ /* The passphrases do not match. Clear them and retry. */
+ memset(passphrase1, 0, strlen(passphrase1));
+ memset(passphrase2, 0, strlen(passphrase2));
+ xfree(passphrase1);
+ xfree(passphrase2);
+ printf("Passphrases do not match. Try again.\n");
+ goto passphrase_again;
+ }
+ /* Clear the other copy of the passphrase. */
+ memset(passphrase2, 0, strlen(passphrase2));
+ xfree(passphrase2);
+ }
+
+ /* Create default commend field for the passphrase. The user can later
+ edit this field. */
+ if (identity_comment)
+ {
+ strncpy(buf2, identity_comment, sizeof(buf2));
+ buf2[sizeof(buf2) - 1] = '\0';
+ }
+ else
+ {
+#ifdef HAVE_GETHOSTNAME
+ if (gethostname(hostname, sizeof(hostname)) < 0)
+ {
+ perror("gethostname");
+ exit(1);
+ }
+ sprintf(buf2, "%s@%s", pw->pw_name, hostname);
+#else
+ if (uname(&uts) < 0)
+ {
+ perror("uname");
+ exit(1);
+ }
+ sprintf(buf2, "%s@%s", pw->pw_name, uts.nodename);
+#endif
+ }
+
+ /* Save the key with the given passphrase and comment. */
+ if (!save_private_key(buf, passphrase1, &private_key, buf2, &state))
+ {
+ printf("Saving the key failed: %s: %s.\n",
+ buf, strerror(errno));
+ memset(passphrase1, 0, strlen(passphrase1));
+ xfree(passphrase1);
+ goto ask_file_again;
+ }
+ /* Clear the passphrase. */
+ memset(passphrase1, 0, strlen(passphrase1));
+ xfree(passphrase1);
+
+ /* Clear the private key and the random number generator. */
+ rsa_clear_private_key(&private_key);
+ random_clear(&state);
+
+ printf("Your identification has been saved in %s.\n", buf);
+
+ /* Display the public key on the screen. */
+ printf("Your public key is:\n");
+ printf("%d ", public_key.bits);
+ mpz_out_str(stdout, 10, &public_key.e);
+ printf(" ");
+ mpz_out_str(stdout, 10, &public_key.n);
+ printf(" %s\n", buf2);
+
+ /* Save the public key in text format in a file with the same name but
+ .pub appended. */
+ strcat(buf, ".pub");
+ f = fopen(buf, "w");
+ if (!f)
+ {
+ printf("Could not save your public key in %s\n", buf);
+ exit(1);
+ }
+ fprintf(f, "%d ", public_key.bits);
+ mpz_out_str(f, 10, &public_key.e);
+ fprintf(f, " ");
+ mpz_out_str(f, 10, &public_key.n);
+ fprintf(f, " %s\n", buf2);
+ fclose(f);
+
+ printf("Your public key has been saved in %s\n", buf);
+
+ exit(0);
+}
diff --git a/usr.bin/ssh/ssh.1 b/usr.bin/ssh/ssh.1
new file mode 100644
index 00000000000..58c7c2272a5
--- /dev/null
+++ b/usr.bin/ssh/ssh.1
@@ -0,0 +1,1003 @@
+.\" -*- nroff -*-
+.\"
+.\" ssh.1.in
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\"
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" Created: Sat Apr 22 21:55:14 1995 ylo
+.\"
+.\" $Id: ssh.1,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+.\"
+.TH SSH 1 "November 8, 1995" "SSH" "SSH"
+
+.SH NAME
+ssh \- secure shell client (remote login program)
+
+.SH SYNOPSIS
+.B ssh
+[\c
+.BI \-l \ login_name\fR\c
+]
+.B hostname
+[\c
+.IR command \c
+]
+
+.B ssh
+[\c
+.BR \-k \c
+]
+[\c
+.B \-c
+\fIblowfish\fR\||\|\fIidea\fR\||\|\fIdes\fR\||\|\fI3des\fR\||\|\fInone\fR\c
+]
+[\c
+.BI \-e \ escape_char\fR\c
+]
+[\c
+.BI \-i \ identity_file\fR\c
+]
+[\c
+.BI \-l \ login_name\fR\c
+]
+[\c
+.BR \-n \c
+]
+[\c
+.BI \-o \ option\fR\c
+]
+[\c
+.BI \-p \ port\fR\c
+]
+[\c
+.BR \-q \c
+]
+[\c
+.BR \-t \c
+]
+[\c
+.BR \-v \c
+]
+[\c
+.BR \-x \c
+]
+[\c
+.BR \-X \c
+]
+[\c
+.BR \-C \c
+]
+[\c
+.BI \-L \ port\fB:\fIhost\fB:\fIhostport\fR\c
+]
+[\c
+.BI \-R \ port\fB:\fIhost\fB:\fIhostport\fR\c
+]
+.I hostname
+[\c
+.IR command \c
+]
+
+.SH DESCRIPTION
+.LP
+.B Ssh
+(Secure Shell) a program for logging into a remote machine and for
+executing commands in a remote machine. It is intended to replace
+rlogin and rsh, and provide secure encrypted communications between
+two untrusted hosts over an insecure network. X11 connections and
+arbitrary TCP/IP ports can also be forwarded over the secure channel.
+.LP
+.B Ssh
+connects and logs into the specified
+.IR hostname .
+The user must prove
+his/her identity to the remote machine using one of several methods.
+.LP
+First, if the machine the user logs in from is listed in
+.I /etc/hosts.equiv
+or
+.I /etc/shosts.equiv
+on the remote machine, and the user names are
+the same on both sides, the user is immediately permitted to log in.
+Second, if
+.I \&\s+2.\s0rhosts
+or
+.I \&\s+2.\s0shosts
+exists in the user's home directory on the
+remote machine and contains a line containing the name of the client
+machine and the name of the user on that machine, the user is
+permitted to log in. This form of authentication alone is normally not
+allowed by the server because it is not secure.
+.LP
+The second (and primary) authentication method is the
+.B rhosts
+or
+.B hosts.equiv
+method combined with RSA-based host authentication. It
+means that if the login would be permitted by
+.I \&\s+2.\s0rhosts\c
+\|,
+.I \&\s+2.\s0shosts\c
+\|,
+.IR /etc/hosts.equiv\c
+\|,
+or
+.IR /etc/shosts.equiv ",
+and additionally it can verify the client's
+host key (see
+.I \&$HOME/\s+2.\s0ssh/known_hosts
+and
+.I /etc/ssh_known_hosts
+in the
+.B \s-1FILES\s0
+section), only then login is
+permitted. This authentication method closes security holes due to IP
+spoofing, DNS spoofing and routing spoofing. [Note to the
+administrator:
+.IR /etc/hosts.equiv ",
+.IR \&\s+2.\s0rhosts ",
+and the rlogin/rsh protocol in general, are inherently insecure and should be
+disabled if security is desired.]
+.LP
+As a third authentication method,
+.B ssh
+supports RSA based authentication.
+The scheme is based on public-key cryptography: there are cryptosystems
+where encryption and decryption are done using separate keys, and it
+is not possible to derive the decryption key from the encryption key.
+RSA is one such system. The idea is that each user creates a public/private
+key pair for authentication purposes. The
+server knows the public key, and only the user knows the private key.
+The file
+.I \&$HOME/\s+2.\s0ssh/authorized_keys
+lists the public keys that are permitted for logging
+in. When the user logs in, the
+.B ssh
+program tells the server which key pair it would like to use for
+authentication. The server checks if this key is permitted, and if
+so, sends the user (actually the
+.B ssh
+program running on behalf of the user) a challenge, a random number,
+encrypted by the user's public key. The challenge can only be
+decrypted using the proper private key. The user's client then decrypts the
+challenge using the private key, proving that he/she knows the private
+key but without disclosing it to the server.
+.LP
+.B Ssh
+implements the RSA authentication protocol automatically. The user
+creates his/her RSA key pair by running
+.BR ssh-keygen (1).
+This stores the private key in
+.I \&\s+2.\s0ssh/identity
+and the public key in
+.I \&\s+2.\s0ssh/identity.pub
+in the user's home directory. The user should then
+copy the
+.I identity.pub
+to
+.I \&\s+2.\s0ssh/authorized_keys
+in his/her home directory on the remote machine (the
+.I authorized_keys
+file corresponds to the conventional
+.I \&\s+2.\s0rhosts
+file, and has one key
+per line, though the lines can be very long). After this, the user
+can log in without giving the password. RSA authentication is much
+more secure than rhosts authentication.
+.LP
+The most convenient way to use RSA authentication may be with an
+authentication agent. See
+.BR ssh-agent (1)
+for more information.
+.LP
+If other authentication methods fail,
+.B ssh
+prompts the user for a password. The password is sent to the remote
+host for checking; however, since all communications are encrypted,
+the password cannot be seen by someone listening on the network.
+.LP
+When the user's identity has been accepted by the server, the server
+either executes the given command, or logs into the machine and gives
+the user a normal shell on the remote machine. All communication with
+the remote command or shell will be automatically encrypted.
+.LP
+If a pseudo-terminal has been allocated (normal login session), the
+user can disconnect with "~.", and suspend
+.B ssh
+with "~^Z". All forwarded connections can be listed with "~#", and if
+the session blocks waiting for forwarded X11 or TCP/IP
+connections to terminate, it can be backgrounded with "~&" (this
+should not be used while the user shell is active, as it can cause the
+shell to hang). All available escapes can be listed with "~?".
+.LP
+A single tilde character can be sent as "~~" (or by
+following the tilde by a character other than those described above).
+The escape character must always follow a newline to be interpreted as
+special. The escape character can be changed in configuration files
+or on the command line.
+.LP
+If no pseudo tty has been allocated, the
+session is transparent and can be used to reliably transfer binary
+data. On most systems, setting the escape character to ``none'' will
+also make the session transparent even if a tty is used.
+.LP
+The session terminates when the command or shell in on the remote
+machine exists and all X11 and TCP/IP connections have been closed.
+The exit status of the remote program is returned as the exit status
+of
+.B ssh.
+.LP
+If the user is using X11 (the
+.B \s-1DISPLAY\s0
+environment variable is set), the connection to the X11 display is
+automatically forwarded to the remote side in such a way that any X11
+programs started from the shell (or command) will go through the
+encrypted channel, and the connection to the real X server will be made
+from the local machine. The user should not manually set
+.BR \s-1DISPLAY\s0 ".
+Forwarding of X11 connections can be
+configured on the command line or in configuration files.
+.LP
+The DISPLAY value set by
+.B ssh
+will point to the server machine, but with a display number greater
+than zero. This is normal, and happens because
+.B ssh
+creates a "proxy" X server on the server machine for forwarding the
+connections over the encrypted channel.
+.LP
+.B Ssh
+will also automatically set up Xauthority data on the server machine.
+For this purpose, it will generate a random authorization cookie,
+store it in Xauthority on the server, and verify that any forwarded
+connections carry this cookie and replace it by the real cookie when
+the connection is opened. The real authentication cookie is never
+sent to the server machine (and no cookies are sent in the plain).
+.LP
+If the user is using an authentication agent, the connection to the agent
+is automatically forwarded to the remote side unless disabled on
+command line or in a configuration file.
+.LP
+Forwarding of arbitrary TCP/IP connections over the secure channel can
+be specified either on command line or in a configuration file. One
+possible application of TCP/IP forwarding is a secure connection to an
+electronic purse; another is going trough firewalls.
+.LP
+.B Ssh
+automatically maintains and checks a database containing RSA-based
+identifications for all hosts it has ever been used with. The
+database is stored in
+.I \&\s+2.\s0ssh/known_hosts
+in the user's home directory. Additionally, the file
+.I /etc/ssh_known_hosts
+is automatically checked for known hosts. Any new hosts are
+automatically added to the user's file. If a host's identification
+ever changes,
+.B ssh
+warns about this and disables password authentication to prevent a
+trojan horse from getting the user's password. Another purpose of
+this mechanism is to prevent man-in-the-middle attacks which could
+otherwise be used to circumvent the encryption. The
+.B StrictHostKeyChecking
+option (see below) can be used to prevent logins to machines whose
+host key is not known or has changed.
+
+
+.ne 5
+.SH OPTIONS
+.TP
+.BI \-c \ \fIblowfish\fR\||\|\fIidea\fR\||\|\fIdes\fR\||\|\fI3des\fR\||\|\fInone\fR
+Selects the cipher to use for encrypting the session.
+.B \s-13DES\s0
+is used by default. It is believed to be secure.
+.B \s-1DES\s0
+is the data encryption standard, but is breakable by
+governments, large corporations, and major criminal organizations.
+.B \s-13DES\s0
+(triple-des) is encrypt-decrypt-encrypt triple with three different
+keys. It is presumably more secure than
+DES.
+.B none
+disables encryption entirely; it is only intended for debugging, and
+it renders the connection insecure.
+.ne 3
+.TP
+.B \-e \fIch\fR\||\|\fI^ch\fR\||\|\fInone\fR
+Sets the escape character for sessions with a pty (default: ~). The
+escape character is only recognized at the beginning of a line. The
+escape character followed by a dot (.) closes the connection, followed
+by control-Z suspends the connection, and followed by itself sends the
+escape character once. Setting the character to 'none' disables any
+escapes and makes the session fully transparent.
+.ne 3
+.TP
+.B \-f
+Requests ssh to go to background after authentication. This is useful
+if ssh is going to ask for passwords or passphrases, but the user
+wants it in the background. This implies
+.B \-n.
+The recommended way to start X11 programs at a remote site is with
+something like "ssh -f host xterm".
+.ne 3
+.TP
+.BI \-i \ identity_file
+Selects the file from which the identity (private key) for
+.B \s-1RSA\s0
+authentication is read. Default is
+.I \&\s+2.\s0ssh/identity
+in the user's home directory. Identity files may also be specified on
+a per-host basis in the configuration file. It is possible to have
+multiple \-i options (and multiple identities specified in
+configuration files).
+.ne 3
+.TP
+.B \-k
+Disables forwarding of Kerberos tickets / AFS tokens. This may
+also be specified on a per-host basis in the configuration file.
+.ne 3
+.TP
+.BI -l \ login_name
+Specifies the user to log in as on the remote machine. This may also
+be specified on a per-host basis in the configuration file.
+.ne 3
+.TP
+.B \-n
+Redirects stdin from /dev/null (actually, prevents reading from stdin).
+This must be used when
+.B ssh
+is run in the background. A common trick is to use this to run X11
+programs in a remote machine. For example, "ssh -n shadows.cs.hut.fi
+emacs &" will start an emacs on shadows.cs.hut.fi, and the X11
+connection will be automatically forwarded over an encrypted channel.
+The
+.B ssh
+program will be put in the background.
+(This does not work if
+.B ssh
+needs to ask for a password or passphrase; see also the -f option.)
+.ne 3
+.TP
+.BI \-o "\ 'option'
+Can be used to give options in the format used in the config file.
+This is useful for specifying options for which there is no separate
+command-line flag. The option has the same format as a line in the
+configuration file.
+.ne 3
+.TP
+.BI \-p "\ port
+Port to connect to on the remote host. This can be specified on a
+per-host basis in the configuration file.
+.ne 3
+.TP
+.B \-q
+Quiet mode. Causes all warning and diagnostic messages to be
+suppressed. Only fatal errors are displayed.
+.ne 3
+.TP
+.B \-t
+Force pseudo-tty allocation. This can be used to execute arbitary
+screen-based programs on a remote machine, which can be very useful
+e.g. when implementing menu services.
+.ne 3
+.TP
+.B \-v
+Verbose mode. Causes
+.B ssh
+to print debugging messages about its progress. This is helpful in
+debugging connection, authentication, and configuration problems.
+.ne 3
+.TP
+.B \-x
+Disables X11 forwarding. This can also be specified on a per-host
+basis in a configuration file.
+.ne 3
+.TP
+.B \-X
+Enables X11 forwarding.
+.ne 3
+.TP
+.B \-C
+Requests compression of all data (including stdin, stdout, stderr, and
+data for forwarded X11 and TCP/IP connections). The compression
+algorithm is the same used by gzip, and the "level" can be controlled
+by the
+.B CompressionLevel
+option (see below). Compression is desirable on modem lines and other
+slow connections, but will only slow down things on fast networks.
+The default value can be set on a host-by-host basis in the
+configuration files; see the
+.B Compress
+option below.
+.ne 3
+.TP
+.BI \-L "\ port:host:hostport
+Specifies that the given port on the local (client) host is to be
+forwarded to the given host and port on the remote side. This works
+by allocating a socket to listen to
+.B port
+on the local side, and whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.B host:hostport
+from the remote machine. Port forwardings can also be specified in the
+configuration file. Only root can forward privileged ports.
+.ne 3
+.TP
+.BI \-R "\ port:host:hostport
+Specifies that the given port on the remote (server) host is to be
+forwarded to the given host and port on the local side. This works
+by allocating a socket to listen to
+.B port
+on the remote side, and whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.B host:hostport
+from the local machine. Port forwardings can also be specified in the
+configuration file. Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+
+.SH CONFIGURATION FILES
+.LP
+.B Ssh
+obtains configuration data from the following sources (in this order):
+command line options, user's configuration file
+(\fI\&$HOME/\s+2.\s0ssh/config\fR), and system-wide configuration file
+(\fI/etc/ssh_config\fR). For each parameter, the first obtained value
+will be used. The configuration files contain sections bracketed by
+"Host" specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification. The matched
+host name is the one given on the command line.
+.LP
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.LP
+The configuration file has the following format:
+.IP
+Empty lines and lines starting with '#' are comments.
+.IP
+Otherwise a line is of the format "keyword arguments". The possible
+keywords and their meanings are as follows (note that the
+configuration files are case-sensitive):
+.ne 3
+.TP
+.de YN
+"\fByes\fR" or "\fBno\fR".
+..
+
+.B Host
+Restricts the following declarations (up to the next
+.B Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword. '*' and '?' can be as wildcards in the
+patterns. A single '*' as a pattern can be used to provide global
+defaults for all hosts. The host is the
+.IR hostname
+argument given on the command line (i.e., the name is not converted to
+a canonicalized host name before matching).
+.ne 3
+.TP
+.B AFSTokenPassing
+Specifies whether to pass AFS tokens to remote host. The argument to
+this keyword must be
+.YN
+.ne 3
+.TP
+.B BatchMode
+If set to "yes", passphrase/password querying will be disabled. This
+option is useful in scripts and other batch jobs where you have no
+user to supply the password. The argument must be
+.YN
+.ne 3
+.TP
+.B Cipher
+Specifies the cipher to use for encrypting the session. Currently,
+.IR blowfish ",
+.IR idea ",
+.IR des ",
+.IR 3des ",
+and
+.I none
+are supported. The default is "3des". Using "none" (no encryption) is intended
+only for debugging, and will render the connection insecure.
+.ne 3
+.TP
+.B Compression
+Specifies whether to use compression. The argument must be
+.YN
+.ne 3
+.TP
+.B CompressionLevel
+Specifies the compression level to use if compression is enable. The
+argument must be an integer from 1 (fast) to 9 (slow, best). The
+default level is 6, which is good for most applications. The meaning
+of the values is the same as in GNU GZIP.
+.ne 3
+.TP
+.B ConnectionAttempts
+Specifies the number of tries (one per second) to make before falling
+back to rsh or exiting. The argument must be an integer. This may be
+useful in scripts if the connection sometimes fails.
+.ne 3
+.TP
+.B EscapeChar
+Sets the escape character (default: ~). The escape character can also
+be set on the command line. The argument should be a single
+character, '^' followed by a letter, or ``none'' to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.ne 3
+.TP
+.B FallBackToRsh
+Specifies that if connecting via
+.B ssh
+fails due to a connection refused error (there is no
+.B sshd
+listening on the remote host),
+.B rsh
+should automatically be used instead (after a suitable warning about
+the session being unencrypted). The argument must be
+.YN
+.ne 3
+.TP
+.B ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine. The argument must be
+.YN
+.ne 3
+.TP
+.B ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.B \s-1DISPLAY\s0
+set. The argument must be
+.YN
+.ne 3
+.TP
+.B GlobalKnownHostsFile
+Specifies a file to use instead of
+.IR /etc/ssh_known_hosts ".
+.ne 3
+.TP
+.B HostName
+Specifies the real host name to log into. This can be used to specify
+nicnames or abbreviations for hosts. Default is the name given on the
+command line. Numeric IP addresses are also permitted (both on the
+command line and in
+.B HostName
+specifications).
+.ne 3
+.TP
+.B IdentityFile
+Specifies the file from which the user's RSA authentication identity
+is read (default \fI\s+2.\s0ssh/identity\fR in the user's home directory).
+Additionally, any identities represented by the authentication agent
+will be used for authentication. The file name may use the tilde
+syntax to refer to a user's home directory. It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+.ne 3
+.TP
+.B KeepAlive
+Specifies whether the system should send keepalive messages to the
+other side. If they are sent, death of the connection or crash of one
+of the machines will be properly noticed. However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+
+The default is "yes" (to send keepalives), and the client will notice
+if the network goes down or the remote host dies. This is important
+in scripts, and many users want it too.
+
+To disable keepalives, the value should be set to "no" in both the
+server and the client configuration files.
+.ne 3
+.TP
+.B KerberosAuthentication
+Specifies whether Kerberos authentication will be used.
+.TP
+.B KerberosTgtPassing
+Specifies whether a Kerberos TGT will be forwarded to the server.
+Note that TGT forwarding is normally not enabled in the server.
+.TP
+.B LocalForward
+Specifies that a TCP/IP port on the local machine be forwarded over
+the secure channel to given host:port from the remote machine. The
+first argument must be a port number, and the second must be
+host:port. Multiple forwardings may be specified, and additional
+forwardings can be given on the command line. Only the root can
+forward privileged ports.
+.ne 3
+.TP
+.B PasswordAuthentication
+Specifies whether to use password authentication. The argument to
+this keyword must be
+.YN
+.ne 3
+.TP
+.B Port
+Specifies the port number to connect on the remote host. Default is
+22.
+.ne 3
+.TP
+.B ProxyCommand
+Specifies the command to use to connect to the server. The command
+string extends to the end of the line, and is executed with /bin/sh.
+In the command string, %h will be substituted by the host name to
+connect and %p by the port. The command can be basically anything,
+and should read from its stdin and write to its stdout. It should
+eventually connect an
+.B sshd
+server running on some machine, or execute
+"sshd -i" somewhere. Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+
+Note that
+.B ssh
+can also be configured to support the SOCKS system using the
+--with-socks compile-time configuration option.
+.ne 3
+.TP
+.B RemoteForward
+Specifies that a TCP/IP port on the remote machine be forwarded over
+the secure channel to given host:port from the local machine. The
+first argument must be a port number, and the second must be
+host:port. Multiple forwardings may be specified, and additional
+forwardings can be given on the command line. Only the root can
+forward privileged ports.
+.ne 3
+.TP
+.B RhostsAuthentication
+Specifies whether to try rhosts based authentication. Note that this
+declaration only affects the client side and has no effect whatsoever
+on security. Disabling rhosts authentication may reduce
+authentication time on slow connections when rhosts authentication is
+not used. Most servers do not permit RhostsAuthentication because it
+is not secure (see RhostsRSAAuthentication). The argument to this
+keyword must be
+.YN
+.ne 3
+.TP
+.B RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication. This is the primary authentication method for most
+sites. The argument must be
+.YN
+.ne 3
+.TP
+.B RSAAuthentication
+Specifies whether to try RSA authentication. The argument to this
+keyword must be
+.YN
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+.ne 3
+.TP
+.B StrictHostKeyChecking
+If this flag is set to "yes",
+.B ssh
+ssh will never automatically add host keys to the
+.I $HOME/.ssh/known_hosts
+file, and refuses to connect hosts whose host key has changed. This
+provides maximum protection against trojan horse attacks. However, it
+can be somewhat annoying if you don't have good
+.I /etc/ssh_known_hosts
+files installed and frequently
+connect new hosts. Basically this option forces the user to manually
+add any new hosts. Normally this option is disabled, and new hosts
+will automatically be added to the known host files. The host keys of
+known hosts will be verified automatically in either case. The
+argument must be
+.YN
+.ne3
+.TP
+.B User
+Specifies the user to log in as. This can be useful if you have a
+different user name in different machines. This saves the trouble of
+having to remember to give the user name on the command line.
+.ne 3
+.TP
+.B UserKnownHostsFile
+Specifies a file to use instead of \fI$HOME/\s+2.\s0ssh/known_hosts\fR.
+.ne 3
+.TP
+.B UseRsh
+Specifies that rlogin/rsh should be used for this host. It is
+possible that the host does not at all support the
+.B ssh
+protocol. This causes
+.B ssh
+to immediately exec
+.B rsh.
+All other options (except
+.BR HostName )
+are ignored if this has been specified. The argument must be
+.YN
+
+.SH ENVIRONMENT
+.LP
+.B Ssh
+will normally set the following environment variables:
+.TP
+.B DISPLAY
+The DISPLAY variable indicates the location of the X11 server. It is
+automatically set by
+.B ssh
+to point to a value of the form "hostname:n" where hostname indicates
+the host where the shell runs, and n is an integer >= 1. Ssh uses
+this special value to forward X11 connections over the secure
+channel. The user should normally not set DISPLAY explicitly, as that
+will render the X11 connection insecure (and will require the user to
+manually copy any required authorization cookies).
+.ne 3
+.TP
+.B HOME
+Set to the path of the user's home directory.
+.ne 3
+.TP
+.B LOGNAME
+Synonym for USER; set for compatibility with systems that use
+this variable.
+.ne 3
+.TP
+.B MAIL
+Set to point the user's mailbox.
+.ne 3
+.TP
+.B PATH
+Set to the default PATH, as specified when compiling
+.B ssh
+or, on some systems,
+.I /etc/environment
+or
+.IR /etc/default/login ".
+.ne 3
+.TP
+.B SSH_AUTHENTICATION_FD
+This is set to an integer value if you are using the authentication
+agent and a connection to it has been forwarded. The value indicates
+a file descriptor number used for communicating with the agent. On
+some systems,
+.B SSH_AUTHENTICATION_SOCKET
+may be used instead to
+indicate the path of a unix-domain socket used to communicate with the
+agent (this method is less secure, and is only used on systems that
+don't support the first method).
+.ne 3
+.TP
+.B SSH_CLIENT
+Identifies the client end of the connection. The variable contains
+three space-separated values: client ip-address, client port number,
+and server port number.
+.ne 3
+.TP
+.B SSH_TTY
+This is set to the name of the tty (path to the device) associated
+with the current shell or command. If the current session has no tty,
+this variable is not set.
+.ne 3
+.TP
+.B TZ
+The timezone variable is set to indicate the present timezone if it
+was set when the daemon was started (e.i., the daemon passes the value
+on to new connections).
+.ne 3
+.TP
+.B USER
+Set to the name of the user logging in.
+.LP
+.RT
+Additionally,
+.B ssh
+reads
+.I /etc/environment
+and
+.IR $HOME/.ssh/environment ",
+and adds lines of
+the format
+.I VARNAME=value
+to the environment. Some systems may have
+still additional mechanisms for setting up the environment, such as
+.I /etc/default/login
+on Solaris.
+
+.ne 3
+.SH FILES
+.TP
+.I \&$HOME/\s+2.\s0ssh/known_hosts
+Records host keys for all hosts the user has logged into (that are not
+in \fI/etc/ssh_known_hosts\fR). See
+.B sshd
+manual page.
+.ne 3
+.TP
+.I \&$HOME/\s+2.\s0ssh/random_seed
+Used for seeding the random number generator. This file contains
+sensitive data and should read/write for the user and not accessible
+for others. This file is created the first time the program is run
+and updated automatically. The user should never need to read or
+modify this file.
+.ne 5
+.TP
+.I \&$HOME/\s+2.\s0ssh/identity
+Contains the RSA authentication identity of the user. This file
+contains sensitive data and should be readable by the user but not
+accessible by others. It is possible to specify a passphrase when
+generating the key; the passphrase will be used to encrypt the
+sensitive part of this file using
+.BR \s-1IDEA\s0 ".
+.ne 3
+.TP
+.I \&$HOME/\s+2.\s0ssh/identity.pub
+Contains the public key for authentication (public part of the
+identity file in human-readable form). The contents of this file
+should be added to \fI$HOME/\s+2.\s0ssh/authorized_keys\fR on all machines
+where you wish to log in using RSA authentication. This file is not
+sensitive and can (but need not) be readable by anyone. This file is
+never used automatically and is not necessary; it is only provided for
+the convenience of the user.
+.ne 3
+.TP
+.I \&$HOME/\s+2.\s0ssh/config
+This is the per-user configuration file. The format of this file is
+described above. This file is used by the
+.B ssh
+client. This file does not usually contain any sensitive information,
+but the recommended permissions are read/write for the user, and not
+accessible by others.
+.ne 3
+.TP
+.I \&$HOME/\s+2.\s0ssh/authorized_keys
+Lists the RSA keys that can be used for logging in as this user. The
+format of this file is described in the
+.B sshd
+manual page. In the simplest form the format is the same as the .pub
+identity files (that is, each line contains the number of bits in
+modulus, public exponent, modulus, and comment fields, separated by
+spaces). This file is not highly sensitive, but the recommended
+permissions are read/write for the user, and not accessible by others.
+.ne 3
+.TP
+.I /etc/ssh_known_hosts
+Systemwide list of known host keys. This file should be prepared by the
+system administrator to contain the public host keys of all machines in the
+organization. This file should be world-readable. This file contains
+public keys, one per line, in the following format (fields separated
+by spaces): system name, number of bits in modulus, public exponent,
+modulus, and optional comment field. When different names are used
+for the same machine, all such names should be listed, separated by
+commas. The format is described on the
+.B sshd
+manual page.
+.IP
+The canonical system name (as returned by name servers) is used by
+.B sshd
+to verify the client host when logging in; other names are needed because
+.B ssh
+does not convert the user-supplied name to a canonical name before
+checking the key, because someone with access to the name servers
+would then be able to fool host authentication.
+.ne 3
+.TP
+.I /etc/ssh_config
+Systemwide configuration file. This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file. This file must
+be world-readable.
+.ne 3
+.TP
+.I $HOME/\s+2.\s0rhosts
+This file is used in \s+2.\s0rhosts authentication to list the
+host/user pairs that are permitted to log in. (Note that this file is
+also used by rlogin and rsh, which makes using this file insecure.)
+Each line of the file contains a host name (in the canonical form
+returned by name servers), and then a user name on that host,
+separated by a space. One some machines this file may need to be
+world-readable if the user's home directory is on a NFS partition,
+because
+.B sshd
+reads it as root. Additionally, this file must be owned by the user,
+and must not have write permissions for anyone else. The recommended
+permission for most machines is read/write for the user, and not
+accessible by others.
+.IP
+Note that by default
+.B sshd
+will be installed so that it requires successful RSA host
+authentication before permitting \s+2.\s0rhosts authentication. If your
+server machine does not have the client's host key in
+\fI/etc/ssh_known_hosts\fR, you can store it in
+\fI$HOME/\s+2.\s0ssh/known_hosts\fR. The easiest way to do this is to
+connect back to the client from the server machine using ssh; this
+will automatically add the host key in \fI$HOME/\s+2.\s0ssh/known_hosts\fR.
+.ne 3
+.TP
+.I $HOME/\s+2.\s0shosts
+This file is used exactly the same way as \s+2.\s0rhosts. The purpose for
+having this file is to be able to use rhosts authentication with
+.B ssh
+without permitting login with rlogin or rsh.
+.ne 3
+.TP
+.I /etc/hosts.equiv
+This file is used during \s+2.\s0rhosts authentication. It contains
+canonical hosts names, one per line (the full format is described on
+the
+.B sshd
+manual page). If the client host is found in this file, login is
+automatically permitted provided client and server user names are the
+same. Additionally, successful RSA host authentication is normally
+required. This file should only be writable by root.
+.TP
+.I /etc/shosts.equiv
+This file is processed exactly as
+.IR /etc/hosts.equiv ".
+This file may be useful to permit logins using
+.B ssh
+but not using rsh/rlogin.
+.ne 3
+.TP
+.I /etc/sshrc
+Commands in this file are executed by
+.B ssh
+when the user logs in just before the user's shell (or command) is started.
+See the
+.B sshd
+manual page for more information.
+.ne 3
+.TP
+.I $HOME/.ssh/rc
+Commands in this file are executed by
+.B ssh
+when the user logs in just before the user's shell (or command) is
+started.
+See the
+.B sshd
+manual page for more information.
+
+.SH INSTALLATION
+.LP
+.B Ssh
+is normally installed as suid root. It needs root privileges only for
+rhosts authentication (rhosts authentication requires that the
+connection must come from a privileged port, and allocating such a
+port requires root privileges). It also needs to be able to read
+\fI/etc/ssh_host_key\fR to perform
+.B \s-1RSA\s0
+host authentication. It is possible to use
+.B ssh
+without root privileges, but rhosts authentication will then be
+disabled.
+.B Ssh
+drops any extra privileges immediately after the connection to the
+remote host has been made.
+.LP
+Considerable work has been put into making
+.B sshd
+secure. However, if you find a security problem, please report it
+immediately to <ssh-bugs@cs.hut.fi>.
+
+
+.SH AUTHOR
+.LP
+Tatu Ylonen <ylo@cs.hut.fi>
+.LP
+Information about new releases, mailing lists, and other related
+issues can be found from the ssh WWW home page at
+http://www.cs.hut.fi/ssh.
+
+.SH SEE ALSO
+.BR sshd (8),
+.BR ssh-keygen (1),
+.BR ssh-agent (1),
+.BR ssh-add (1),
+.BR scp (1),
+.BR make-ssh-known-hosts (1),
+.BR rlogin (1),
+.BR rsh (1),
+.BR telnet (1)
diff --git a/usr.bin/ssh/ssh.1.in b/usr.bin/ssh/ssh.1.in
new file mode 100644
index 00000000000..74a1255eb7d
--- /dev/null
+++ b/usr.bin/ssh/ssh.1.in
@@ -0,0 +1,1003 @@
+.\" -*- nroff -*-
+.\"
+.\" ssh.1.in
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\"
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" Created: Sat Apr 22 21:55:14 1995 ylo
+.\"
+.\" $Id: ssh.1.in,v 1.1 1999/09/26 20:53:37 deraadt Exp $
+.\"
+.TH SSH 1 "November 8, 1995" "SSH" "SSH"
+
+.SH NAME
+ssh \- secure shell client (remote login program)
+
+.SH SYNOPSIS
+.B ssh
+[\c
+.BI \-l \ login_name\fR\c
+]
+.B hostname
+[\c
+.IR command \c
+]
+
+.B ssh
+[\c
+.BR \-k \c
+]
+[\c
+.B \-c
+\fIblowfish\fR\||\|\fIidea\fR\||\|\fIdes\fR\||\|\fI3des\fR\||\|\fInone\fR\c
+]
+[\c
+.BI \-e \ escape_char\fR\c
+]
+[\c
+.BI \-i \ identity_file\fR\c
+]
+[\c
+.BI \-l \ login_name\fR\c
+]
+[\c
+.BR \-n \c
+]
+[\c
+.BI \-o \ option\fR\c
+]
+[\c
+.BI \-p \ port\fR\c
+]
+[\c
+.BR \-q \c
+]
+[\c
+.BR \-t \c
+]
+[\c
+.BR \-v \c
+]
+[\c
+.BR \-x \c
+]
+[\c
+.BR \-X \c
+]
+[\c
+.BR \-C \c
+]
+[\c
+.BI \-L \ port\fB:\fIhost\fB:\fIhostport\fR\c
+]
+[\c
+.BI \-R \ port\fB:\fIhost\fB:\fIhostport\fR\c
+]
+.I hostname
+[\c
+.IR command \c
+]
+
+.SH DESCRIPTION
+.LP
+.B Ssh
+(Secure Shell) a program for logging into a remote machine and for
+executing commands in a remote machine. It is intended to replace
+rlogin and rsh, and provide secure encrypted communications between
+two untrusted hosts over an insecure network. X11 connections and
+arbitrary TCP/IP ports can also be forwarded over the secure channel.
+.LP
+.B Ssh
+connects and logs into the specified
+.IR hostname .
+The user must prove
+his/her identity to the remote machine using one of several methods.
+.LP
+First, if the machine the user logs in from is listed in
+.I /etc/hosts.equiv
+or
+.I @ETCDIR@/shosts.equiv
+on the remote machine, and the user names are
+the same on both sides, the user is immediately permitted to log in.
+Second, if
+.I \&\s+2.\s0rhosts
+or
+.I \&\s+2.\s0shosts
+exists in the user's home directory on the
+remote machine and contains a line containing the name of the client
+machine and the name of the user on that machine, the user is
+permitted to log in. This form of authentication alone is normally not
+allowed by the server because it is not secure.
+.LP
+The second (and primary) authentication method is the
+.B rhosts
+or
+.B hosts.equiv
+method combined with RSA-based host authentication. It
+means that if the login would be permitted by
+.I \&\s+2.\s0rhosts\c
+\|,
+.I \&\s+2.\s0shosts\c
+\|,
+.IR /etc/hosts.equiv\c
+\|,
+or
+.IR @ETCDIR@/shosts.equiv ",
+and additionally it can verify the client's
+host key (see
+.I \&$HOME/\s+2.\s0ssh/known_hosts
+and
+.I @ETCDIR@/ssh_known_hosts
+in the
+.B \s-1FILES\s0
+section), only then login is
+permitted. This authentication method closes security holes due to IP
+spoofing, DNS spoofing and routing spoofing. [Note to the
+administrator:
+.IR /etc/hosts.equiv ",
+.IR \&\s+2.\s0rhosts ",
+and the rlogin/rsh protocol in general, are inherently insecure and should be
+disabled if security is desired.]
+.LP
+As a third authentication method,
+.B ssh
+supports RSA based authentication.
+The scheme is based on public-key cryptography: there are cryptosystems
+where encryption and decryption are done using separate keys, and it
+is not possible to derive the decryption key from the encryption key.
+RSA is one such system. The idea is that each user creates a public/private
+key pair for authentication purposes. The
+server knows the public key, and only the user knows the private key.
+The file
+.I \&$HOME/\s+2.\s0ssh/authorized_keys
+lists the public keys that are permitted for logging
+in. When the user logs in, the
+.B ssh
+program tells the server which key pair it would like to use for
+authentication. The server checks if this key is permitted, and if
+so, sends the user (actually the
+.B ssh
+program running on behalf of the user) a challenge, a random number,
+encrypted by the user's public key. The challenge can only be
+decrypted using the proper private key. The user's client then decrypts the
+challenge using the private key, proving that he/she knows the private
+key but without disclosing it to the server.
+.LP
+.B Ssh
+implements the RSA authentication protocol automatically. The user
+creates his/her RSA key pair by running
+.BR ssh-keygen (1).
+This stores the private key in
+.I \&\s+2.\s0ssh/identity
+and the public key in
+.I \&\s+2.\s0ssh/identity.pub
+in the user's home directory. The user should then
+copy the
+.I identity.pub
+to
+.I \&\s+2.\s0ssh/authorized_keys
+in his/her home directory on the remote machine (the
+.I authorized_keys
+file corresponds to the conventional
+.I \&\s+2.\s0rhosts
+file, and has one key
+per line, though the lines can be very long). After this, the user
+can log in without giving the password. RSA authentication is much
+more secure than rhosts authentication.
+.LP
+The most convenient way to use RSA authentication may be with an
+authentication agent. See
+.BR ssh-agent (1)
+for more information.
+.LP
+If other authentication methods fail,
+.B ssh
+prompts the user for a password. The password is sent to the remote
+host for checking; however, since all communications are encrypted,
+the password cannot be seen by someone listening on the network.
+.LP
+When the user's identity has been accepted by the server, the server
+either executes the given command, or logs into the machine and gives
+the user a normal shell on the remote machine. All communication with
+the remote command or shell will be automatically encrypted.
+.LP
+If a pseudo-terminal has been allocated (normal login session), the
+user can disconnect with "~.", and suspend
+.B ssh
+with "~^Z". All forwarded connections can be listed with "~#", and if
+the session blocks waiting for forwarded X11 or TCP/IP
+connections to terminate, it can be backgrounded with "~&" (this
+should not be used while the user shell is active, as it can cause the
+shell to hang). All available escapes can be listed with "~?".
+.LP
+A single tilde character can be sent as "~~" (or by
+following the tilde by a character other than those described above).
+The escape character must always follow a newline to be interpreted as
+special. The escape character can be changed in configuration files
+or on the command line.
+.LP
+If no pseudo tty has been allocated, the
+session is transparent and can be used to reliably transfer binary
+data. On most systems, setting the escape character to ``none'' will
+also make the session transparent even if a tty is used.
+.LP
+The session terminates when the command or shell in on the remote
+machine exists and all X11 and TCP/IP connections have been closed.
+The exit status of the remote program is returned as the exit status
+of
+.B ssh.
+.LP
+If the user is using X11 (the
+.B \s-1DISPLAY\s0
+environment variable is set), the connection to the X11 display is
+automatically forwarded to the remote side in such a way that any X11
+programs started from the shell (or command) will go through the
+encrypted channel, and the connection to the real X server will be made
+from the local machine. The user should not manually set
+.BR \s-1DISPLAY\s0 ".
+Forwarding of X11 connections can be
+configured on the command line or in configuration files.
+.LP
+The DISPLAY value set by
+.B ssh
+will point to the server machine, but with a display number greater
+than zero. This is normal, and happens because
+.B ssh
+creates a "proxy" X server on the server machine for forwarding the
+connections over the encrypted channel.
+.LP
+.B Ssh
+will also automatically set up Xauthority data on the server machine.
+For this purpose, it will generate a random authorization cookie,
+store it in Xauthority on the server, and verify that any forwarded
+connections carry this cookie and replace it by the real cookie when
+the connection is opened. The real authentication cookie is never
+sent to the server machine (and no cookies are sent in the plain).
+.LP
+If the user is using an authentication agent, the connection to the agent
+is automatically forwarded to the remote side unless disabled on
+command line or in a configuration file.
+.LP
+Forwarding of arbitrary TCP/IP connections over the secure channel can
+be specified either on command line or in a configuration file. One
+possible application of TCP/IP forwarding is a secure connection to an
+electronic purse; another is going trough firewalls.
+.LP
+.B Ssh
+automatically maintains and checks a database containing RSA-based
+identifications for all hosts it has ever been used with. The
+database is stored in
+.I \&\s+2.\s0ssh/known_hosts
+in the user's home directory. Additionally, the file
+.I @ETCDIR@/ssh_known_hosts
+is automatically checked for known hosts. Any new hosts are
+automatically added to the user's file. If a host's identification
+ever changes,
+.B ssh
+warns about this and disables password authentication to prevent a
+trojan horse from getting the user's password. Another purpose of
+this mechanism is to prevent man-in-the-middle attacks which could
+otherwise be used to circumvent the encryption. The
+.B StrictHostKeyChecking
+option (see below) can be used to prevent logins to machines whose
+host key is not known or has changed.
+
+
+.ne 5
+.SH OPTIONS
+.TP
+.BI \-c \ \fIblowfish\fR\||\|\fIidea\fR\||\|\fIdes\fR\||\|\fI3des\fR\||\|\fInone\fR
+Selects the cipher to use for encrypting the session.
+.B \s-13DES\s0
+is used by default. It is believed to be secure.
+.B \s-1DES\s0
+is the data encryption standard, but is breakable by
+governments, large corporations, and major criminal organizations.
+.B \s-13DES\s0
+(triple-des) is encrypt-decrypt-encrypt triple with three different
+keys. It is presumably more secure than
+DES.
+.B none
+disables encryption entirely; it is only intended for debugging, and
+it renders the connection insecure.
+.ne 3
+.TP
+.B \-e \fIch\fR\||\|\fI^ch\fR\||\|\fInone\fR
+Sets the escape character for sessions with a pty (default: ~). The
+escape character is only recognized at the beginning of a line. The
+escape character followed by a dot (.) closes the connection, followed
+by control-Z suspends the connection, and followed by itself sends the
+escape character once. Setting the character to 'none' disables any
+escapes and makes the session fully transparent.
+.ne 3
+.TP
+.B \-f
+Requests ssh to go to background after authentication. This is useful
+if ssh is going to ask for passwords or passphrases, but the user
+wants it in the background. This implies
+.B \-n.
+The recommended way to start X11 programs at a remote site is with
+something like "ssh -f host xterm".
+.ne 3
+.TP
+.BI \-i \ identity_file
+Selects the file from which the identity (private key) for
+.B \s-1RSA\s0
+authentication is read. Default is
+.I \&\s+2.\s0ssh/identity
+in the user's home directory. Identity files may also be specified on
+a per-host basis in the configuration file. It is possible to have
+multiple \-i options (and multiple identities specified in
+configuration files).
+.ne 3
+.TP
+.B \-k
+Disables forwarding of Kerberos tickets / AFS tokens. This may
+also be specified on a per-host basis in the configuration file.
+.ne 3
+.TP
+.BI -l \ login_name
+Specifies the user to log in as on the remote machine. This may also
+be specified on a per-host basis in the configuration file.
+.ne 3
+.TP
+.B \-n
+Redirects stdin from /dev/null (actually, prevents reading from stdin).
+This must be used when
+.B ssh
+is run in the background. A common trick is to use this to run X11
+programs in a remote machine. For example, "ssh -n shadows.cs.hut.fi
+emacs &" will start an emacs on shadows.cs.hut.fi, and the X11
+connection will be automatically forwarded over an encrypted channel.
+The
+.B ssh
+program will be put in the background.
+(This does not work if
+.B ssh
+needs to ask for a password or passphrase; see also the -f option.)
+.ne 3
+.TP
+.BI \-o "\ 'option'
+Can be used to give options in the format used in the config file.
+This is useful for specifying options for which there is no separate
+command-line flag. The option has the same format as a line in the
+configuration file.
+.ne 3
+.TP
+.BI \-p "\ port
+Port to connect to on the remote host. This can be specified on a
+per-host basis in the configuration file.
+.ne 3
+.TP
+.B \-q
+Quiet mode. Causes all warning and diagnostic messages to be
+suppressed. Only fatal errors are displayed.
+.ne 3
+.TP
+.B \-t
+Force pseudo-tty allocation. This can be used to execute arbitary
+screen-based programs on a remote machine, which can be very useful
+e.g. when implementing menu services.
+.ne 3
+.TP
+.B \-v
+Verbose mode. Causes
+.B ssh
+to print debugging messages about its progress. This is helpful in
+debugging connection, authentication, and configuration problems.
+.ne 3
+.TP
+.B \-x
+Disables X11 forwarding. This can also be specified on a per-host
+basis in a configuration file.
+.ne 3
+.TP
+.B \-X
+Enables X11 forwarding.
+.ne 3
+.TP
+.B \-C
+Requests compression of all data (including stdin, stdout, stderr, and
+data for forwarded X11 and TCP/IP connections). The compression
+algorithm is the same used by gzip, and the "level" can be controlled
+by the
+.B CompressionLevel
+option (see below). Compression is desirable on modem lines and other
+slow connections, but will only slow down things on fast networks.
+The default value can be set on a host-by-host basis in the
+configuration files; see the
+.B Compress
+option below.
+.ne 3
+.TP
+.BI \-L "\ port:host:hostport
+Specifies that the given port on the local (client) host is to be
+forwarded to the given host and port on the remote side. This works
+by allocating a socket to listen to
+.B port
+on the local side, and whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.B host:hostport
+from the remote machine. Port forwardings can also be specified in the
+configuration file. Only root can forward privileged ports.
+.ne 3
+.TP
+.BI \-R "\ port:host:hostport
+Specifies that the given port on the remote (server) host is to be
+forwarded to the given host and port on the local side. This works
+by allocating a socket to listen to
+.B port
+on the remote side, and whenever a connection is made to this port, the
+connection is forwarded over the secure channel, and a connection is
+made to
+.B host:hostport
+from the local machine. Port forwardings can also be specified in the
+configuration file. Privileged ports can be forwarded only when
+logging in as root on the remote machine.
+
+.SH CONFIGURATION FILES
+.LP
+.B Ssh
+obtains configuration data from the following sources (in this order):
+command line options, user's configuration file
+(\fI\&$HOME/\s+2.\s0ssh/config\fR), and system-wide configuration file
+(\fI@ETCDIR@/ssh_config\fR). For each parameter, the first obtained value
+will be used. The configuration files contain sections bracketed by
+"Host" specifications, and that section is only applied for hosts that
+match one of the patterns given in the specification. The matched
+host name is the one given on the command line.
+.LP
+Since the first obtained value for each parameter is used, more
+host-specific declarations should be given near the beginning of the
+file, and general defaults at the end.
+.LP
+The configuration file has the following format:
+.IP
+Empty lines and lines starting with '#' are comments.
+.IP
+Otherwise a line is of the format "keyword arguments". The possible
+keywords and their meanings are as follows (note that the
+configuration files are case-sensitive):
+.ne 3
+.TP
+.de YN
+"\fByes\fR" or "\fBno\fR".
+..
+
+.B Host
+Restricts the following declarations (up to the next
+.B Host
+keyword) to be only for those hosts that match one of the patterns
+given after the keyword. '*' and '?' can be as wildcards in the
+patterns. A single '*' as a pattern can be used to provide global
+defaults for all hosts. The host is the
+.IR hostname
+argument given on the command line (i.e., the name is not converted to
+a canonicalized host name before matching).
+.ne 3
+.TP
+.B AFSTokenPassing
+Specifies whether to pass AFS tokens to remote host. The argument to
+this keyword must be
+.YN
+.ne 3
+.TP
+.B BatchMode
+If set to "yes", passphrase/password querying will be disabled. This
+option is useful in scripts and other batch jobs where you have no
+user to supply the password. The argument must be
+.YN
+.ne 3
+.TP
+.B Cipher
+Specifies the cipher to use for encrypting the session. Currently,
+.IR blowfish ",
+.IR idea ",
+.IR des ",
+.IR 3des ",
+and
+.I none
+are supported. The default is "3des". Using "none" (no encryption) is intended
+only for debugging, and will render the connection insecure.
+.ne 3
+.TP
+.B Compression
+Specifies whether to use compression. The argument must be
+.YN
+.ne 3
+.TP
+.B CompressionLevel
+Specifies the compression level to use if compression is enable. The
+argument must be an integer from 1 (fast) to 9 (slow, best). The
+default level is 6, which is good for most applications. The meaning
+of the values is the same as in GNU GZIP.
+.ne 3
+.TP
+.B ConnectionAttempts
+Specifies the number of tries (one per second) to make before falling
+back to rsh or exiting. The argument must be an integer. This may be
+useful in scripts if the connection sometimes fails.
+.ne 3
+.TP
+.B EscapeChar
+Sets the escape character (default: ~). The escape character can also
+be set on the command line. The argument should be a single
+character, '^' followed by a letter, or ``none'' to disable the escape
+character entirely (making the connection transparent for binary
+data).
+.ne 3
+.TP
+.B FallBackToRsh
+Specifies that if connecting via
+.B ssh
+fails due to a connection refused error (there is no
+.B sshd
+listening on the remote host),
+.B rsh
+should automatically be used instead (after a suitable warning about
+the session being unencrypted). The argument must be
+.YN
+.ne 3
+.TP
+.B ForwardAgent
+Specifies whether the connection to the authentication agent (if any)
+will be forwarded to the remote machine. The argument must be
+.YN
+.ne 3
+.TP
+.B ForwardX11
+Specifies whether X11 connections will be automatically redirected
+over the secure channel and
+.B \s-1DISPLAY\s0
+set. The argument must be
+.YN
+.ne 3
+.TP
+.B GlobalKnownHostsFile
+Specifies a file to use instead of
+.IR @ETCDIR@/ssh_known_hosts ".
+.ne 3
+.TP
+.B HostName
+Specifies the real host name to log into. This can be used to specify
+nicnames or abbreviations for hosts. Default is the name given on the
+command line. Numeric IP addresses are also permitted (both on the
+command line and in
+.B HostName
+specifications).
+.ne 3
+.TP
+.B IdentityFile
+Specifies the file from which the user's RSA authentication identity
+is read (default \fI\s+2.\s0ssh/identity\fR in the user's home directory).
+Additionally, any identities represented by the authentication agent
+will be used for authentication. The file name may use the tilde
+syntax to refer to a user's home directory. It is possible to have
+multiple identity files specified in configuration files; all these
+identities will be tried in sequence.
+.ne 3
+.TP
+.B KeepAlive
+Specifies whether the system should send keepalive messages to the
+other side. If they are sent, death of the connection or crash of one
+of the machines will be properly noticed. However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying.
+
+The default is "yes" (to send keepalives), and the client will notice
+if the network goes down or the remote host dies. This is important
+in scripts, and many users want it too.
+
+To disable keepalives, the value should be set to "no" in both the
+server and the client configuration files.
+.ne 3
+.TP
+.B KerberosAuthentication
+Specifies whether Kerberos authentication will be used.
+.TP
+.B KerberosTgtPassing
+Specifies whether a Kerberos TGT will be forwarded to the server.
+Note that TGT forwarding is normally not enabled in the server.
+.TP
+.B LocalForward
+Specifies that a TCP/IP port on the local machine be forwarded over
+the secure channel to given host:port from the remote machine. The
+first argument must be a port number, and the second must be
+host:port. Multiple forwardings may be specified, and additional
+forwardings can be given on the command line. Only the root can
+forward privileged ports.
+.ne 3
+.TP
+.B PasswordAuthentication
+Specifies whether to use password authentication. The argument to
+this keyword must be
+.YN
+.ne 3
+.TP
+.B Port
+Specifies the port number to connect on the remote host. Default is
+22.
+.ne 3
+.TP
+.B ProxyCommand
+Specifies the command to use to connect to the server. The command
+string extends to the end of the line, and is executed with /bin/sh.
+In the command string, %h will be substituted by the host name to
+connect and %p by the port. The command can be basically anything,
+and should read from its stdin and write to its stdout. It should
+eventually connect an
+.B sshd
+server running on some machine, or execute
+"sshd -i" somewhere. Host key management will be done using the
+HostName of the host being connected (defaulting to the name typed by
+the user).
+
+Note that
+.B ssh
+can also be configured to support the SOCKS system using the
+--with-socks compile-time configuration option.
+.ne 3
+.TP
+.B RemoteForward
+Specifies that a TCP/IP port on the remote machine be forwarded over
+the secure channel to given host:port from the local machine. The
+first argument must be a port number, and the second must be
+host:port. Multiple forwardings may be specified, and additional
+forwardings can be given on the command line. Only the root can
+forward privileged ports.
+.ne 3
+.TP
+.B RhostsAuthentication
+Specifies whether to try rhosts based authentication. Note that this
+declaration only affects the client side and has no effect whatsoever
+on security. Disabling rhosts authentication may reduce
+authentication time on slow connections when rhosts authentication is
+not used. Most servers do not permit RhostsAuthentication because it
+is not secure (see RhostsRSAAuthentication). The argument to this
+keyword must be
+.YN
+.ne 3
+.TP
+.B RhostsRSAAuthentication
+Specifies whether to try rhosts based authentication with RSA host
+authentication. This is the primary authentication method for most
+sites. The argument must be
+.YN
+.ne 3
+.TP
+.B RSAAuthentication
+Specifies whether to try RSA authentication. The argument to this
+keyword must be
+.YN
+RSA authentication will only be
+attempted if the identity file exists, or an authentication agent is
+running.
+.ne 3
+.TP
+.B StrictHostKeyChecking
+If this flag is set to "yes",
+.B ssh
+ssh will never automatically add host keys to the
+.I $HOME/.ssh/known_hosts
+file, and refuses to connect hosts whose host key has changed. This
+provides maximum protection against trojan horse attacks. However, it
+can be somewhat annoying if you don't have good
+.I /etc/ssh_known_hosts
+files installed and frequently
+connect new hosts. Basically this option forces the user to manually
+add any new hosts. Normally this option is disabled, and new hosts
+will automatically be added to the known host files. The host keys of
+known hosts will be verified automatically in either case. The
+argument must be
+.YN
+.ne3
+.TP
+.B User
+Specifies the user to log in as. This can be useful if you have a
+different user name in different machines. This saves the trouble of
+having to remember to give the user name on the command line.
+.ne 3
+.TP
+.B UserKnownHostsFile
+Specifies a file to use instead of \fI$HOME/\s+2.\s0ssh/known_hosts\fR.
+.ne 3
+.TP
+.B UseRsh
+Specifies that rlogin/rsh should be used for this host. It is
+possible that the host does not at all support the
+.B ssh
+protocol. This causes
+.B ssh
+to immediately exec
+.B rsh.
+All other options (except
+.BR HostName )
+are ignored if this has been specified. The argument must be
+.YN
+
+.SH ENVIRONMENT
+.LP
+.B Ssh
+will normally set the following environment variables:
+.TP
+.B DISPLAY
+The DISPLAY variable indicates the location of the X11 server. It is
+automatically set by
+.B ssh
+to point to a value of the form "hostname:n" where hostname indicates
+the host where the shell runs, and n is an integer >= 1. Ssh uses
+this special value to forward X11 connections over the secure
+channel. The user should normally not set DISPLAY explicitly, as that
+will render the X11 connection insecure (and will require the user to
+manually copy any required authorization cookies).
+.ne 3
+.TP
+.B HOME
+Set to the path of the user's home directory.
+.ne 3
+.TP
+.B LOGNAME
+Synonym for USER; set for compatibility with systems that use
+this variable.
+.ne 3
+.TP
+.B MAIL
+Set to point the user's mailbox.
+.ne 3
+.TP
+.B PATH
+Set to the default PATH, as specified when compiling
+.B ssh
+or, on some systems,
+.I /etc/environment
+or
+.IR /etc/default/login ".
+.ne 3
+.TP
+.B SSH_AUTHENTICATION_FD
+This is set to an integer value if you are using the authentication
+agent and a connection to it has been forwarded. The value indicates
+a file descriptor number used for communicating with the agent. On
+some systems,
+.B SSH_AUTHENTICATION_SOCKET
+may be used instead to
+indicate the path of a unix-domain socket used to communicate with the
+agent (this method is less secure, and is only used on systems that
+don't support the first method).
+.ne 3
+.TP
+.B SSH_CLIENT
+Identifies the client end of the connection. The variable contains
+three space-separated values: client ip-address, client port number,
+and server port number.
+.ne 3
+.TP
+.B SSH_TTY
+This is set to the name of the tty (path to the device) associated
+with the current shell or command. If the current session has no tty,
+this variable is not set.
+.ne 3
+.TP
+.B TZ
+The timezone variable is set to indicate the present timezone if it
+was set when the daemon was started (e.i., the daemon passes the value
+on to new connections).
+.ne 3
+.TP
+.B USER
+Set to the name of the user logging in.
+.LP
+.RT
+Additionally,
+.B ssh
+reads
+.I /etc/environment
+and
+.IR $HOME/.ssh/environment ",
+and adds lines of
+the format
+.I VARNAME=value
+to the environment. Some systems may have
+still additional mechanisms for setting up the environment, such as
+.I /etc/default/login
+on Solaris.
+
+.ne 3
+.SH FILES
+.TP
+.I \&$HOME/\s+2.\s0ssh/known_hosts
+Records host keys for all hosts the user has logged into (that are not
+in \fI@ETCDIR@/ssh_known_hosts\fR). See
+.B sshd
+manual page.
+.ne 3
+.TP
+.I \&$HOME/\s+2.\s0ssh/random_seed
+Used for seeding the random number generator. This file contains
+sensitive data and should read/write for the user and not accessible
+for others. This file is created the first time the program is run
+and updated automatically. The user should never need to read or
+modify this file.
+.ne 5
+.TP
+.I \&$HOME/\s+2.\s0ssh/identity
+Contains the RSA authentication identity of the user. This file
+contains sensitive data and should be readable by the user but not
+accessible by others. It is possible to specify a passphrase when
+generating the key; the passphrase will be used to encrypt the
+sensitive part of this file using
+.BR \s-1IDEA\s0 ".
+.ne 3
+.TP
+.I \&$HOME/\s+2.\s0ssh/identity.pub
+Contains the public key for authentication (public part of the
+identity file in human-readable form). The contents of this file
+should be added to \fI$HOME/\s+2.\s0ssh/authorized_keys\fR on all machines
+where you wish to log in using RSA authentication. This file is not
+sensitive and can (but need not) be readable by anyone. This file is
+never used automatically and is not necessary; it is only provided for
+the convenience of the user.
+.ne 3
+.TP
+.I \&$HOME/\s+2.\s0ssh/config
+This is the per-user configuration file. The format of this file is
+described above. This file is used by the
+.B ssh
+client. This file does not usually contain any sensitive information,
+but the recommended permissions are read/write for the user, and not
+accessible by others.
+.ne 3
+.TP
+.I \&$HOME/\s+2.\s0ssh/authorized_keys
+Lists the RSA keys that can be used for logging in as this user. The
+format of this file is described in the
+.B sshd
+manual page. In the simplest form the format is the same as the .pub
+identity files (that is, each line contains the number of bits in
+modulus, public exponent, modulus, and comment fields, separated by
+spaces). This file is not highly sensitive, but the recommended
+permissions are read/write for the user, and not accessible by others.
+.ne 3
+.TP
+.I @ETCDIR@/ssh_known_hosts
+Systemwide list of known host keys. This file should be prepared by the
+system administrator to contain the public host keys of all machines in the
+organization. This file should be world-readable. This file contains
+public keys, one per line, in the following format (fields separated
+by spaces): system name, number of bits in modulus, public exponent,
+modulus, and optional comment field. When different names are used
+for the same machine, all such names should be listed, separated by
+commas. The format is described on the
+.B sshd
+manual page.
+.IP
+The canonical system name (as returned by name servers) is used by
+.B sshd
+to verify the client host when logging in; other names are needed because
+.B ssh
+does not convert the user-supplied name to a canonical name before
+checking the key, because someone with access to the name servers
+would then be able to fool host authentication.
+.ne 3
+.TP
+.I @ETCDIR@/ssh_config
+Systemwide configuration file. This file provides defaults for those
+values that are not specified in the user's configuration file, and
+for those users who do not have a configuration file. This file must
+be world-readable.
+.ne 3
+.TP
+.I $HOME/\s+2.\s0rhosts
+This file is used in \s+2.\s0rhosts authentication to list the
+host/user pairs that are permitted to log in. (Note that this file is
+also used by rlogin and rsh, which makes using this file insecure.)
+Each line of the file contains a host name (in the canonical form
+returned by name servers), and then a user name on that host,
+separated by a space. One some machines this file may need to be
+world-readable if the user's home directory is on a NFS partition,
+because
+.B sshd
+reads it as root. Additionally, this file must be owned by the user,
+and must not have write permissions for anyone else. The recommended
+permission for most machines is read/write for the user, and not
+accessible by others.
+.IP
+Note that by default
+.B sshd
+will be installed so that it requires successful RSA host
+authentication before permitting \s+2.\s0rhosts authentication. If your
+server machine does not have the client's host key in
+\fI@ETCDIR@/ssh_known_hosts\fR, you can store it in
+\fI$HOME/\s+2.\s0ssh/known_hosts\fR. The easiest way to do this is to
+connect back to the client from the server machine using ssh; this
+will automatically add the host key in \fI$HOME/\s+2.\s0ssh/known_hosts\fR.
+.ne 3
+.TP
+.I $HOME/\s+2.\s0shosts
+This file is used exactly the same way as \s+2.\s0rhosts. The purpose for
+having this file is to be able to use rhosts authentication with
+.B ssh
+without permitting login with rlogin or rsh.
+.ne 3
+.TP
+.I /etc/hosts.equiv
+This file is used during \s+2.\s0rhosts authentication. It contains
+canonical hosts names, one per line (the full format is described on
+the
+.B sshd
+manual page). If the client host is found in this file, login is
+automatically permitted provided client and server user names are the
+same. Additionally, successful RSA host authentication is normally
+required. This file should only be writable by root.
+.TP
+.I @ETCDIR@/shosts.equiv
+This file is processed exactly as
+.IR /etc/hosts.equiv ".
+This file may be useful to permit logins using
+.B ssh
+but not using rsh/rlogin.
+.ne 3
+.TP
+.I @ETCDIR@/sshrc
+Commands in this file are executed by
+.B ssh
+when the user logs in just before the user's shell (or command) is started.
+See the
+.B sshd
+manual page for more information.
+.ne 3
+.TP
+.I $HOME/.ssh/rc
+Commands in this file are executed by
+.B ssh
+when the user logs in just before the user's shell (or command) is
+started.
+See the
+.B sshd
+manual page for more information.
+
+.SH INSTALLATION
+.LP
+.B Ssh
+is normally installed as suid root. It needs root privileges only for
+rhosts authentication (rhosts authentication requires that the
+connection must come from a privileged port, and allocating such a
+port requires root privileges). It also needs to be able to read
+\fI@ETCDIR@/ssh_host_key\fR to perform
+.B \s-1RSA\s0
+host authentication. It is possible to use
+.B ssh
+without root privileges, but rhosts authentication will then be
+disabled.
+.B Ssh
+drops any extra privileges immediately after the connection to the
+remote host has been made.
+.LP
+Considerable work has been put into making
+.B sshd
+secure. However, if you find a security problem, please report it
+immediately to <ssh-bugs@cs.hut.fi>.
+
+
+.SH AUTHOR
+.LP
+Tatu Ylonen <ylo@cs.hut.fi>
+.LP
+Information about new releases, mailing lists, and other related
+issues can be found from the ssh WWW home page at
+http://www.cs.hut.fi/ssh.
+
+.SH SEE ALSO
+.BR sshd (8),
+.BR ssh-keygen (1),
+.BR ssh-agent (1),
+.BR ssh-add (1),
+.BR scp (1),
+.BR make-ssh-known-hosts (1),
+.BR rlogin (1),
+.BR rsh (1),
+.BR telnet (1)
diff --git a/usr.bin/ssh/ssh.c b/usr.bin/ssh/ssh.c
new file mode 100644
index 00000000000..f67a4f74197
--- /dev/null
+++ b/usr.bin/ssh/ssh.c
@@ -0,0 +1,813 @@
+/*
+
+ssh.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 18 16:36:11 1995 ylo
+
+Ssh client program. This program can be used to log into a remote machine.
+The software supports strong authentication, encryption, and forwarding
+of X11, TCP/IP, and authentication connections.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: ssh.c,v 1.1 1999/09/26 20:53:38 deraadt Exp $");
+
+#include "xmalloc.h"
+#include "randoms.h"
+#include "ssh.h"
+#include "packet.h"
+#include "buffer.h"
+#include "authfd.h"
+#include "readconf.h"
+#include "uidswap.h"
+
+/* Random number generator state. This is initialized in ssh_login, and
+ left initialized. This is used both by the packet module and by various
+ other functions. */
+RandomState random_state;
+
+/* Flag indicating whether debug mode is on. This can be set on the
+ command line. */
+int debug_flag = 0;
+
+/* Flag indicating whether quiet mode is on. */
+int quiet_flag = 0;
+
+/* Flag indicating whether to allocate a pseudo tty. This can be set on the
+ command line, and is automatically set if no command is given on the command
+ line. */
+int tty_flag = 0;
+
+/* Flag indicating that nothing should be read from stdin. This can be set
+ on the command line. */
+int stdin_null_flag = 0;
+
+/* Flag indicating that ssh should fork after authentication. This is useful
+ so that the pasphrase can be entered manually, and then ssh goes to the
+ background. */
+int fork_after_authentication_flag = 0;
+
+/* General data structure for command line options and options configurable
+ in configuration files. See readconf.h. */
+Options options;
+
+/* Name of the host we are connecting to. This is the name given on the
+ command line, or the HostName specified for the user-supplied name
+ in a configuration file. */
+char *host;
+
+#ifdef SIGWINCH
+/* Flag to indicate that we have received a window change signal which has
+ not yet been processed. This will cause a message indicating the new
+ window size to be sent to the server a little later. This is volatile
+ because this is updated in a signal handler. */
+volatile int received_window_change_signal = 0;
+#endif /* SIGWINCH */
+
+/* Value of argv[0] (set in the main program). */
+char *av0;
+
+/* Flag indicating whether we have a valid host private key loaded. */
+int host_private_key_loaded = 0;
+
+/* Host private key. */
+RSAPrivateKey host_private_key;
+
+
+/* Prints a help message to the user. This function never returns. */
+
+void usage()
+{
+ int i;
+
+ fprintf(stderr, "Usage: %s [options] host [command]\n", av0);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -l user Log in using this user name.\n");
+ fprintf(stderr, " -n Redirect input from /dev/null.\n");
+ fprintf(stderr, " -k Disable authentication agent forwarding.\n");
+#if defined(KERBEROS_TGT_PASSING) || defined(AFS)
+ fprintf(stderr, " This also disables passing of AFS tokens/Kerberos tickets.\n");
+#endif /* KERBEROS_TGT_PASSING || AFS */
+ fprintf(stderr, " -x Disable X11 connection forwarding.\n");
+ fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\n");
+ fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
+ fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
+ fprintf(stderr, " -q Quiet; don't display any warning messages.\n");
+ fprintf(stderr, " -f Fork into background after authentication.\n");
+ fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n");
+
+ fprintf(stderr, " -c cipher Select encryption algorithm: ");
+ for (i = 1; i <= 6; i++)
+ {
+ const char *t = cipher_name(i);
+ if (t[0] == 'n' && t[1] == 'o' && t[2] == ' ')
+ continue;
+ fprintf(stderr, "%s, ", t);
+ }
+ fprintf(stderr, "or none.\n");
+
+ fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n");
+ fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n");
+ fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n");
+ fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0);
+ fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
+#ifdef WITH_ZLIB
+ fprintf(stderr, " -C Enable compression.\n");
+#endif /* WITH_ZLIB */
+ fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n");
+ exit(1);
+}
+
+/* Connects to the given host using rsh (or prints an error message and exits
+ if rsh is not available). This function never returns. */
+
+void rsh_connect(char *host, char *user, Buffer *command)
+{
+#ifdef RSH_PATH
+ char *args[10];
+ int i;
+
+ log("Using rsh. WARNING: Connection will not be encrypted.");
+ /* Build argument list for rsh. */
+ i = 0;
+ args[i++] = RSH_PATH;
+ args[i++] = host; /* may have to come after user on some systems */
+ if (user)
+ {
+ args[i++] = "-l";
+ args[i++] = user;
+ }
+ if (buffer_len(command) > 0)
+ {
+ buffer_append(command, "\0", 1);
+ args[i++] = buffer_ptr(command);
+ }
+ args[i++] = NULL;
+ if (debug_flag)
+ {
+ for (i = 0; args[i]; i++)
+ {
+ if (i != 0)
+ fprintf(stderr, " ");
+ fprintf(stderr, "%s", args[i]);
+ }
+ fprintf(stderr, "\n");
+ }
+ execv(RSH_PATH, args);
+ perror(RSH_PATH);
+ exit(1);
+#else /* RSH_PATH */
+ fatal("Rsh not available.");
+#endif /* RSH_PATH */
+}
+
+/* Main program for the ssh client. */
+
+int main(int ac, char **av)
+{
+ int i, opt, optind, type, exit_status, ok, fwd_port, fwd_host_port, authfd;
+ char *optarg, *cp, buf[256];
+ Buffer command;
+ struct winsize ws;
+ struct stat st;
+ struct passwd *pw, pwcopy;
+ int interactive = 0, dummy;
+ uid_t original_real_uid;
+ uid_t original_effective_uid;
+ int plen;
+
+ /* Save the original real uid. It will be needed later (uid-swapping may
+ clobber the real uid). */
+ original_real_uid = getuid();
+ original_effective_uid = geteuid();
+
+ /* If we are installed setuid root be careful to not drop core. */
+ if (original_real_uid != original_effective_uid)
+ {
+#ifdef HAVE_SETRLIMIT
+ struct rlimit rlim;
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ if (setrlimit(RLIMIT_CORE, &rlim) < 0)
+ fatal("setrlimit failed: %.100s", strerror(errno));
+#else
+ fatal("ssh is installed setuid root.\n");
+#endif
+ }
+
+ /* Use uid-swapping to give up root privileges for the duration of option
+ processing. We will re-instantiate the rights when we are ready to
+ create the privileged port, and will permanently drop them when the
+ port has been created (actually, when the connection has been made, as
+ we may need to create the port several times). */
+ temporarily_use_uid(original_real_uid);
+
+#ifdef HAVE_UMASK
+ /* Set our umask to something reasonable, as some files are created with
+ the default umask. This will make them world-readable but writable
+ only by the owner, which is ok for all files for which we don't set
+ the modes explicitly. */
+ umask(022);
+#endif /* HAVE_UMASK */
+
+ /* Save our own name. */
+ av0 = av[0];
+
+#ifdef SOCKS
+ /* Initialize SOCKS (the firewall traversal library). */
+ SOCKSinit(av0);
+#endif /* SOCKS */
+
+ /* Set RSA (actually gmp) memory allocation functions. */
+ rsa_set_mp_memory_allocation();
+
+ /* Initialize option structure to indicate that no values have been set. */
+ initialize_options(&options);
+
+ /* Parse command-line arguments. */
+ host = NULL;
+
+ /* If program name is not one of the standard names, use it as host name. */
+ if (strchr(av0, '/'))
+ cp = strrchr(av0, '/') + 1;
+ else
+ cp = av0;
+ if (strcmp(cp, "rsh") != 0 && strcmp(cp, "ssh") != 0 &&
+ strcmp(cp, "rlogin") != 0 && strcmp(cp, "slogin") != 0)
+ host = cp;
+
+ for (optind = 1; optind < ac; optind++)
+ {
+ if (av[optind][0] != '-')
+ {
+ if (host)
+ break;
+ host = av[optind];
+ continue;
+ }
+ opt = av[optind][1];
+ if (!opt)
+ usage();
+ if (strchr("eilcpLRo", opt)) /* options with arguments */
+ {
+ optarg = av[optind] + 2;
+ if (strcmp(optarg, "") == 0)
+ {
+ if (optind >= ac - 1)
+ usage();
+ optarg = av[++optind];
+ }
+ }
+ else
+ {
+ if (av[optind][2])
+ usage();
+ optarg = NULL;
+ }
+ switch (opt)
+ {
+ case 'n':
+ stdin_null_flag = 1;
+ break;
+
+ case 'f':
+ fork_after_authentication_flag = 1;
+ stdin_null_flag = 1;
+ break;
+
+ case 'x':
+ options.forward_x11 = 0;
+ break;
+
+ case 'X':
+ options.forward_x11 = 1;
+ break;
+
+ case 'a':
+ options.forward_agent = 0;
+#ifdef KERBEROS_TGT_PASSING
+ options.kerberos_tgt_passing = 0;
+#endif
+#ifdef AFS
+ options.afs_token_passing = 0;
+#endif
+ break;
+
+ case 'i':
+ if (stat(optarg, &st) < 0)
+ {
+ fprintf(stderr, "Warning: Identity file %s does not exist.\n",
+ optarg);
+ break;
+ }
+ if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
+ fatal("Too many identity files specified (max %d)",
+ SSH_MAX_IDENTITY_FILES);
+ options.identity_files[options.num_identity_files++] =
+ xstrdup(optarg);
+ break;
+
+ case 't':
+ tty_flag = 1;
+ break;
+
+ case 'v':
+ debug_flag = 1;
+ fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n",
+ SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR);
+#ifdef RSAREF
+ fprintf(stderr, "Compiled with RSAREF.\n");
+#elif defined(DO_SSL)
+ fprintf(stderr, "Compiled with SSL.\n");
+#else /* RSAREF */
+ fprintf(stderr, "Standard version. Does not use RSAREF.\n");
+#endif /* RSAREF */
+ break;
+
+ case 'q':
+ quiet_flag = 1;
+ break;
+
+ case 'e':
+ if (optarg[0] == '^' && optarg[2] == 0 &&
+ (unsigned char)optarg[1] >= 64 && (unsigned char)optarg[1] < 128)
+ options.escape_char = (unsigned char)optarg[1] & 31;
+ else
+ if (strlen(optarg) == 1)
+ options.escape_char = (unsigned char)optarg[0];
+ else
+ if (strcmp(optarg, "none") == 0)
+ options.escape_char = -2;
+ else
+ {
+ fprintf(stderr, "Bad escape character '%s'.\n", optarg);
+ exit(1);
+ }
+ break;
+
+ case 'c':
+ options.cipher = cipher_number(optarg);
+ if (options.cipher == -1)
+ {
+ fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
+ exit(1);
+ }
+ break;
+
+ case 'p':
+ options.port = atoi(optarg);
+ if (options.port < 1 || options.port > 65535)
+ {
+ fprintf(stderr, "Bad port %s.\n", optarg);
+ exit(1);
+ }
+ break;
+
+ case 'l':
+ options.user = optarg;
+ break;
+
+ case 'R':
+ if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
+ &fwd_host_port) != 3)
+ {
+ fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
+ usage();
+ /*NOTREACHED*/
+ }
+ add_remote_forward(&options, fwd_port, buf, fwd_host_port);
+ break;
+
+ case 'L':
+ if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
+ &fwd_host_port) != 3)
+ {
+ fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
+ usage();
+ /*NOTREACHED*/
+ }
+ if (fwd_port < 1024 && original_real_uid != 0)
+ {
+ fprintf(stderr,
+ "Privileged ports can only be forwarded by root.\n");
+ exit(1);
+ }
+ add_local_forward(&options, fwd_port, buf, fwd_host_port);
+ break;
+
+#ifdef WITH_ZLIB
+ case 'C':
+ options.compression = 1;
+ break;
+#endif /* WITH_ZLIB */
+
+ case 'o':
+ dummy = 1;
+ process_config_line(&options, host ? host : "", optarg,
+ "command-line", 0, &dummy);
+ break;
+
+ default:
+ usage();
+ }
+ }
+
+ /* Check that we got a host name. */
+ if (!host)
+ usage();
+
+ /* Initialize the command to execute on remote host. */
+ buffer_init(&command);
+
+ /* Save the command to execute on the remote host in a buffer. There is
+ no limit on the length of the command, except by the maximum packet
+ size. Also sets the tty flag if there is no command. */
+ if (optind == ac)
+ {
+ /* No command specified - execute shell on a tty. */
+ tty_flag = 1;
+ }
+ else
+ {
+ /* A command has been specified. Store it into the buffer. */
+ for (i = optind; i < ac; i++)
+ {
+ if (i > optind)
+ buffer_append(&command, " ", 1);
+ buffer_append(&command, av[i], strlen(av[i]));
+ }
+ }
+
+ /* Cannot fork to background if no command. */
+ if (fork_after_authentication_flag && buffer_len(&command) == 0)
+ fatal("Cannot fork into background without a command to execute.");
+
+ /* Allocate a tty by default if no command specified. */
+ if (buffer_len(&command) == 0)
+ tty_flag = 1;
+
+ /* Do not allocate a tty if stdin is not a tty. */
+ if (!isatty(fileno(stdin)))
+ {
+ if (tty_flag)
+ fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
+ tty_flag = 0;
+ }
+
+ /* Get user data. */
+ pw = getpwuid(original_real_uid);
+ if (!pw)
+ {
+ fprintf(stderr, "You don't exist, go away!\n");
+ exit(1);
+ }
+
+ /* Take a copy of the returned structure. */
+ memset(&pwcopy, 0, sizeof(pwcopy));
+ pwcopy.pw_name = xstrdup(pw->pw_name);
+ pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
+ pwcopy.pw_uid = pw->pw_uid;
+ pwcopy.pw_gid = pw->pw_gid;
+ pwcopy.pw_dir = xstrdup(pw->pw_dir);
+ pwcopy.pw_shell = xstrdup(pw->pw_shell);
+ pw = &pwcopy;
+
+ /* Initialize "log" output. Since we are the client all output actually
+ goes to the terminal. */
+ log_init(av[0], 1, debug_flag, quiet_flag, SYSLOG_FACILITY_USER);
+
+ /* Read per-user configuration file. */
+ sprintf(buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE);
+ read_config_file(buf, host, &options);
+
+ /* Read systemwide configuration file. */
+ read_config_file(HOST_CONFIG_FILE, host, &options);
+
+ /* Fill configuration defaults. */
+ fill_default_options(&options);
+ if (options.user == NULL)
+ options.user = xstrdup(pw->pw_name);
+
+ if (options.hostname != NULL)
+ host = options.hostname;
+
+ /* Find canonic host name. */
+ if (strchr(host, '.') == 0)
+ {
+ struct hostent *hp = gethostbyname(host);
+ if (hp != 0)
+ {
+ if (strchr(hp->h_name, '.') != 0)
+ host = xstrdup(hp->h_name);
+ else if (hp->h_aliases != 0
+ && hp->h_aliases[0] != 0
+ && strchr(hp->h_aliases[0], '.') != 0)
+ host = xstrdup(hp->h_aliases[0]);
+ }
+ }
+
+ /* Disable rhosts authentication if not running as root. */
+ if (original_effective_uid != 0)
+ {
+ options.rhosts_authentication = 0;
+ options.rhosts_rsa_authentication = 0;
+ }
+
+ /* If using rsh has been selected, exec it now (without trying anything
+ else). Note that we must release privileges first. */
+ if (options.use_rsh)
+ {
+ /* Restore our superuser privileges. This must be done before
+ permanently setting the uid. */
+ restore_uid();
+
+ /* Switch to the original uid permanently. */
+ permanently_set_uid(original_real_uid);
+
+ /* Execute rsh. */
+ rsh_connect(host, options.user, &command);
+ fatal("rsh_connect returned");
+ }
+
+ /* Restore our superuser privileges. */
+ restore_uid();
+
+ /* Open a connection to the remote host. This needs root privileges if
+ rhosts_authentication is true. Note that the random_state is not
+ yet used by this call, although a pointer to it is stored, and thus it
+ need not be initialized. */
+ ok = ssh_connect(host, options.port, options.connection_attempts,
+ !options.rhosts_authentication &&
+ !options.rhosts_rsa_authentication,
+ original_real_uid, options.proxy_command, &random_state);
+
+ /* If we successfully made the connection, load the host private key in
+ case we will need it later for combined rsa-rhosts authentication.
+ This must be done before releasing extra privileges, because the file
+ is only readable by root. */
+ if (ok)
+ {
+ if (load_private_key(HOST_KEY_FILE, "", &host_private_key, NULL))
+ host_private_key_loaded = 1;
+ }
+
+ /* Get rid of any extra privileges that we may have. We will no longer need
+ them. Also, extra privileges could make it very hard to read identity
+ files and other non-world-readable files from the user's home directory
+ if it happens to be on a NFS volume where root is mapped to nobody. */
+ permanently_set_uid(original_real_uid);
+
+ /* Now that we are back to our own permissions, create ~/.ssh directory
+ if it doesn\'t already exist. */
+ sprintf(buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
+ if (stat(buf, &st) < 0)
+ if (mkdir(buf, 0755) < 0)
+ error("Could not create directory '%.200s'.", buf);
+
+ /* Check if the connection failed, and try "rsh" if appropriate. */
+ if (!ok)
+ {
+ if (options.port != 0)
+ log("Secure connection to %.100s on port %d refused%.100s.",
+ host, options.port,
+ options.fallback_to_rsh ? "; reverting to insecure method" : "");
+ else
+ log("Secure connection to %.100s refused%.100s.", host,
+ options.fallback_to_rsh ? "; reverting to insecure method" : "");
+
+ if (options.fallback_to_rsh)
+ {
+ rsh_connect(host, options.user, &command);
+ fatal("rsh_connect returned");
+ }
+ exit(1);
+ }
+
+ /* Expand ~ in options.identity_files. */
+ for (i = 0; i < options.num_identity_files; i++)
+ options.identity_files[i] =
+ tilde_expand_filename(options.identity_files[i], original_real_uid);
+
+ /* Expand ~ in known host file names. */
+ options.system_hostfile = tilde_expand_filename(options.system_hostfile,
+ original_real_uid);
+ options.user_hostfile = tilde_expand_filename(options.user_hostfile,
+ original_real_uid);
+
+ /* Log into the remote system. This never returns if the login fails.
+ Note: this initializes the random state, and leaves it initialized. */
+ ssh_login(&random_state, host_private_key_loaded, &host_private_key,
+ host, &options, original_real_uid);
+
+ /* We no longer need the host private key. Clear it now. */
+ if (host_private_key_loaded)
+ rsa_clear_private_key(&host_private_key);
+
+ /* Close connection cleanly after attack. */
+ cipher_attack_detected = packet_disconnect;
+
+ /* If requested, fork and let ssh continue in the background. */
+ if (fork_after_authentication_flag)
+ {
+ int ret = fork();
+ if (ret == -1)
+ fatal("fork failed: %.100s", strerror(errno));
+ if (ret != 0)
+ exit(0);
+#ifdef HAVE_SETSID
+ setsid();
+#endif /* HAVE_SETSID */
+ }
+
+#ifdef WITH_ZLIB
+ /* Enable compression if requested. */
+ if (options.compression)
+ {
+ debug("Requesting compression at level %d.", options.compression_level);
+
+ if (options.compression_level < 1 || options.compression_level > 9)
+ fatal("Compression level must be from 1 (fast) to 9 (slow, best).");
+
+ /* Send the request. */
+ packet_start(SSH_CMSG_REQUEST_COMPRESSION);
+ packet_put_int(options.compression_level);
+ packet_send();
+ packet_write_wait();
+ type = packet_read(&plen);
+ if (type == SSH_SMSG_SUCCESS)
+ packet_start_compression(options.compression_level);
+ else if (type == SSH_SMSG_FAILURE)
+ log("Warning: Remote host refused compression.");
+ else
+ packet_disconnect("Protocol error waiting for compression response.");
+ }
+#endif /* WITH_ZLIB */
+
+ /* Allocate a pseudo tty if appropriate. */
+ if (tty_flag)
+ {
+ debug("Requesting pty.");
+
+ /* Start the packet. */
+ packet_start(SSH_CMSG_REQUEST_PTY);
+
+ /* Store TERM in the packet. There is no limit on the length of the
+ string. */
+ cp = getenv("TERM");
+ if (!cp)
+ cp = "";
+ packet_put_string(cp, strlen(cp));
+
+ /* Store window size in the packet. */
+ if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
+ memset(&ws, 0, sizeof(ws));
+ packet_put_int(ws.ws_row);
+ packet_put_int(ws.ws_col);
+ packet_put_int(ws.ws_xpixel);
+ packet_put_int(ws.ws_ypixel);
+
+ /* Store tty modes in the packet. */
+ tty_make_modes(fileno(stdin));
+
+ /* Send the packet, and wait for it to leave. */
+ packet_send();
+ packet_write_wait();
+
+ /* Read response from the server. */
+ type = packet_read(&plen);
+ if (type == SSH_SMSG_SUCCESS)
+ interactive = 1;
+ else if (type == SSH_SMSG_FAILURE)
+ log("Warning: Remote host failed or refused to allocate a pseudo tty.");
+ else
+ packet_disconnect("Protocol error waiting for pty request response.");
+ }
+
+ /* Request X11 forwarding if enabled and DISPLAY is set. */
+ if (options.forward_x11 && getenv("DISPLAY") != NULL)
+ {
+ char line[512], proto[512], data[512];
+ FILE *f;
+ int forwarded = 0, got_data = 0, i;
+
+#ifdef XAUTH_PATH
+ /* Try to get Xauthority information for the display. */
+ sprintf(line, "%.100s list %.200s 2>/dev/null",
+ XAUTH_PATH, getenv("DISPLAY"));
+ f = popen(line, "r");
+ if (f && fgets(line, sizeof(line), f) &&
+ sscanf(line, "%*s %s %s", proto, data) == 2)
+ got_data = 1;
+ if (f)
+ pclose(f);
+#endif /* XAUTH_PATH */
+ /* If we didn't get authentication data, just make up some data. The
+ forwarding code will check the validity of the response anyway, and
+ substitute this data. The X11 server, however, will ignore this
+ fake data and use whatever authentication mechanisms it was using
+ otherwise for the local connection. */
+ if (!got_data)
+ {
+ strcpy(proto, "MIT-MAGIC-COOKIE-1");
+ for (i = 0; i < 16; i++)
+ sprintf(data + 2 * i, "%02x", random_get_byte(&random_state));
+ }
+
+ /* Got local authentication reasonable information. Request forwarding
+ with authentication spoofing. */
+ debug("Requesting X11 forwarding with authentication spoofing.");
+ x11_request_forwarding_with_spoofing(&random_state, proto, data);
+
+ /* Read response from the server. */
+ type = packet_read(&plen);
+ if (type == SSH_SMSG_SUCCESS)
+ {
+ forwarded = 1;
+ interactive = 1;
+ }
+ else if (type == SSH_SMSG_FAILURE)
+ log("Warning: Remote host denied X11 forwarding.");
+ else
+ packet_disconnect("Protocol error waiting for X11 forwarding");
+ }
+
+ /* Tell the packet module whether this is an interactive session. */
+ packet_set_interactive(interactive, options.keepalives);
+
+ /* Clear agent forwarding if we don\'t have an agent. */
+ authfd = ssh_get_authentication_fd();
+ if (authfd < 0)
+ options.forward_agent = 0;
+ else
+ ssh_close_authentication_socket(authfd);
+
+ /* Request authentication agent forwarding if appropriate. */
+ if (options.forward_agent)
+ {
+ debug("Requesting authentication agent forwarding.");
+ auth_request_forwarding();
+
+ /* Read response from the server. */
+ type = packet_read(&plen);
+ packet_integrity_check(plen, 0, type);
+ if (type != SSH_SMSG_SUCCESS)
+ log("Warning: Remote host denied authentication agent forwarding.");
+ }
+
+ /* Initiate local TCP/IP port forwardings. */
+ for (i = 0; i < options.num_local_forwards; i++)
+ {
+ debug("Connections to local port %d forwarded to remote address %.200s:%d",
+ options.local_forwards[i].port, options.local_forwards[i].host,
+ options.local_forwards[i].host_port);
+ channel_request_local_forwarding(options.local_forwards[i].port,
+ options.local_forwards[i].host,
+ options.local_forwards[i].host_port);
+ }
+
+ /* Initiate remote TCP/IP port forwardings. */
+ for (i = 0; i < options.num_remote_forwards; i++)
+ {
+ debug("Connections to remote port %d forwarded to local address %.200s:%d",
+ options.remote_forwards[i].port, options.remote_forwards[i].host,
+ options.remote_forwards[i].host_port);
+ channel_request_remote_forwarding(options.remote_forwards[i].port,
+ options.remote_forwards[i].host,
+ options.remote_forwards[i].host_port);
+ }
+
+ /* If a command was specified on the command line, execute the command now.
+ Otherwise request the server to start a shell. */
+ if (buffer_len(&command) > 0)
+ {
+ int len = buffer_len(&command);
+ if (len > 900)
+ len = 900;
+ debug("Sending command: %.*s", len, buffer_ptr(&command));
+ packet_start(SSH_CMSG_EXEC_CMD);
+ packet_put_string(buffer_ptr(&command), buffer_len(&command));
+ packet_send();
+ packet_write_wait();
+ }
+ else
+ {
+ debug("Requesting shell.");
+ packet_start(SSH_CMSG_EXEC_SHELL);
+ packet_send();
+ packet_write_wait();
+ }
+
+ /* Enter the interactive session. */
+ exit_status = client_loop(tty_flag, tty_flag ? options.escape_char : -1);
+
+ /* Close the connection to the remote host. */
+ packet_close();
+
+ /* Exit with the status returned by the program on the remote side. */
+ exit(exit_status);
+}
diff --git a/usr.bin/ssh/ssh.h b/usr.bin/ssh/ssh.h
new file mode 100644
index 00000000000..3aa6d8804f4
--- /dev/null
+++ b/usr.bin/ssh/ssh.h
@@ -0,0 +1,596 @@
+/*
+
+ssh.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Fri Mar 17 17:09:37 1995 ylo
+
+Generic header file for ssh.
+
+*/
+
+/* RCSID("$Id: ssh.h,v 1.1 1999/09/26 20:53:38 deraadt Exp $"); */
+
+#ifndef SSH_H
+#define SSH_H
+
+#include <gmp.h>
+#include "rsa.h"
+#include "randoms.h"
+#include "cipher.h"
+
+/* The default cipher used if IDEA is not supported by the remote host.
+ It is recommended that this be one of the mandatory ciphers (DES, 3DES),
+ though that is not required. */
+#define SSH_FALLBACK_CIPHER SSH_CIPHER_3DES
+
+/* Cipher used for encrypting authentication files. */
+#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
+
+/* Default port number. */
+#define SSH_DEFAULT_PORT 22
+
+/* Maximum number of TCP/IP ports forwarded per direction. */
+#define SSH_MAX_FORWARDS_PER_DIRECTION 100
+
+/* Maximum number of RSA authentication identity files that can be specified
+ in configuration files or on the command line. */
+#define SSH_MAX_IDENTITY_FILES 100
+
+/* Major protocol version. Different version indicates major incompatiblity
+ that prevents communication. */
+#define PROTOCOL_MAJOR 1
+
+/* Minor protocol version. Different version indicates minor incompatibility
+ that does not prevent interoperation. */
+#define PROTOCOL_MINOR 3
+
+/* Name for the service. The port named by this service overrides the default
+ port if present. */
+#define SSH_SERVICE_NAME "ssh"
+
+/* System-wide file containing host keys of known hosts. This file should be
+ world-readable. */
+#define SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts"
+
+/* HOST_KEY_FILE /etc/ssh_host_key,
+ SERVER_CONFIG_FILE /etc/sshd_config,
+and HOST_CONFIG_FILE /etc/ssh_config
+are all defined in Makefile.in. Of these, ssh_host_key should be readable
+only by root, whereas ssh_config should be world-readable. */
+
+/* Random seed file for the daemon. This file should be readable only by
+ root. */
+#define SSH_DAEMON_SEED_FILE ETCDIR "/ssh_random_seed"
+
+/* The process id of the daemon listening for connections is saved
+ here to make it easier to kill the correct daemon when necessary. */
+#define SSH_DAEMON_PID_FILE PIDDIR "/sshd.pid"
+
+/* The directory in user\'s home directory in which the files reside.
+ The directory should be world-readable (though not all files are). */
+#define SSH_USER_DIR ".ssh"
+
+/* Per-user file containing host keys of known hosts. This file need
+ not be readable by anyone except the user him/herself, though this does
+ not contain anything particularly secret. */
+#define SSH_USER_HOSTFILE "~/.ssh/known_hosts"
+
+/* Name of the file containing client-side random seed. This file should
+ only be readable by the user him/herself. */
+#define SSH_CLIENT_SEEDFILE ".ssh/random_seed"
+
+/* Name of the default file containing client-side authentication key.
+ This file should only be readable by the user him/herself. */
+#define SSH_CLIENT_IDENTITY ".ssh/identity"
+
+/* Configuration file in user\'s home directory. This file need not be
+ readable by anyone but the user him/herself, but does not contain
+ anything particularly secret. If the user\'s home directory resides
+ on an NFS volume where root is mapped to nobody, this may need to be
+ world-readable. */
+#define SSH_USER_CONFFILE ".ssh/config"
+
+/* File containing a list of those rsa keys that permit logging in as
+ this user. This file need not be
+ readable by anyone but the user him/herself, but does not contain
+ anything particularly secret. If the user\'s home directory resides
+ on an NFS volume where root is mapped to nobody, this may need to be
+ world-readable. (This file is read by the daemon which is running as
+ root.) */
+#define SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys"
+
+/* Per-user and system-wide ssh "rc" files. These files are executed with
+ /bin/sh before starting the shell or command if they exist. They
+ will be passed "proto cookie" as arguments if X11 forwarding with
+ spoofing is in use. xauth will be run if neither of these exists. */
+#define SSH_USER_RC ".ssh/rc"
+#define SSH_SYSTEM_RC ETCDIR "/sshrc"
+
+/* Ssh-only version of /etc/hosts.equiv. */
+#define SSH_HOSTS_EQUIV ETCDIR "/shosts.equiv"
+
+/* Additionally, the daemon may use ~/.rhosts and /etc/hosts.equiv if
+ rhosts authentication is enabled. */
+
+/* Socket for connecting the authentication agent. Normally the connection
+ to the authentication agent is passed in a file descriptor; however,
+ on some systems, commonly used shells close all open file descriptors.
+ To make the agent usable on those systems, configure checks whether
+ the shells close all descriptors, and if so, defines AGENT_USES_SOCKET.
+ That socket is an unix-domain socket and will be stored with this name
+ in the user\'s home directory. The socket must not be accessible by
+ anyone but the user him/herself. The number at the end of the name
+ is the pid of the agent or the forwarding daemon. Note that this
+ socket is stored in /tmp, which is supposedly on the local machine. If
+ this were in the user\'s home directory, the daemon (running as root)
+ might not be able to create and chown the file to the user\'s uid. */
+#define SSH_AGENT_SOCKET "/tmp/ssh_agent.%d"
+
+/* Name of the environment variable containing the authentication fd. */
+#define SSH_AUTHFD_ENV_NAME "SSH_AUTHENTICATION_FD"
+
+/* Name of the environment variable containing the pathname of the
+ authentication socket. */
+#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTHENTICATION_SOCKET"
+
+/* Force host key length and server key length to differ by at least this
+ many bits. This is to make double encryption with rsaref work. */
+#define SSH_KEY_BITS_RESERVED 128
+
+/* Length of the session key in bytes. (Specified as 256 bits in the
+ protocol.) */
+#define SSH_SESSION_KEY_LENGTH 32
+
+/* Name of Kerberos service for SSH to use. */
+#define KRB4_SERVICE_NAME "rcmd"
+
+/* Authentication methods. New types can be added, but old types should not
+ be removed for compatibility. The maximum allowed value is 31. */
+#define SSH_AUTH_RHOSTS 1
+#define SSH_AUTH_RSA 2
+#define SSH_AUTH_PASSWORD 3
+#define SSH_AUTH_RHOSTS_RSA 4
+ /* 5 is TIS */
+#define SSH_AUTH_KERBEROS 6
+#define SSH_PASS_KERBEROS_TGT 7
+#define SSH_PASS_AFS_TOKEN 21
+
+/* Protocol flags. These are bit masks. */
+#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
+#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
+
+/* Definition of message types. New values can be added, but old values
+ should not be removed or without careful consideration of the consequences
+ for compatibility. The maximum value is 254; value 255 is reserved
+ for future extension. */
+/* Message name */ /* msg code */ /* arguments */
+#define SSH_MSG_NONE 0 /* no message */
+#define SSH_MSG_DISCONNECT 1 /* cause (string) */
+#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
+#define SSH_CMSG_SESSION_KEY 3 /* key (MP_INT) */
+#define SSH_CMSG_USER 4 /* user (string) */
+#define SSH_CMSG_AUTH_RHOSTS 5 /* user (string) */
+#define SSH_CMSG_AUTH_RSA 6 /* modulus (MP_INT) */
+#define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (MP_INT) */
+#define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (MP_INT) */
+#define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */
+#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */
+#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */
+#define SSH_CMSG_EXEC_SHELL 12 /* */
+#define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */
+#define SSH_SMSG_SUCCESS 14 /* */
+#define SSH_SMSG_FAILURE 15 /* */
+#define SSH_CMSG_STDIN_DATA 16 /* data (string) */
+#define SSH_SMSG_STDOUT_DATA 17 /* data (string) */
+#define SSH_SMSG_STDERR_DATA 18 /* data (string) */
+#define SSH_CMSG_EOF 19 /* */
+#define SSH_SMSG_EXITSTATUS 20 /* status (int) */
+#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* channel (int) */
+#define SSH_MSG_CHANNEL_OPEN_FAILURE 22 /* channel (int) */
+#define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */
+#define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */
+#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */
+/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */
+#define SSH_SMSG_X11_OPEN 27 /* channel (int) */
+#define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */
+#define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */
+#define SSH_CMSG_AGENT_REQUEST_FORWARDING 30 /* */
+#define SSH_SMSG_AGENT_OPEN 31 /* port (int) */
+#define SSH_MSG_IGNORE 32 /* string */
+#define SSH_CMSG_EXIT_CONFIRMATION 33 /* */
+#define SSH_CMSG_X11_REQUEST_FORWARDING 34 /* proto,data (s,s) */
+#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */
+#define SSH_MSG_DEBUG 36 /* string */
+#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */
+
+#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
+#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
+#define SSH_CMSG_HAVE_KERBEROS_TGT 44 /* credentials (s) */
+#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */
+
+
+/* Includes that need definitions above. */
+
+#include "readconf.h"
+
+/*------------ definitions for login.c -------------*/
+
+/* Returns the time when the user last logged in. Returns 0 if the
+ information is not available. This must be called before record_login.
+ The host from which the user logged in is stored in buf. */
+unsigned long get_last_login_time(uid_t uid, const char *logname,
+ char *buf, unsigned int bufsize);
+
+/* Records that the user has logged in. This does many things normally
+ done by login(1). */
+void record_login(int pid, const char *ttyname, const char *user, uid_t uid,
+ const char *host, struct sockaddr_in *addr);
+
+/* Records that the user has logged out. This does many thigs normally
+ done by login(1) or init. */
+void record_logout(int pid, const char *ttyname);
+
+/*------------ definitions for sshconnect.c ----------*/
+
+/* Opens a TCP/IP connection to the remote server on the given host. If
+ port is 0, the default port will be used. If anonymous is zero,
+ a privileged port will be allocated to make the connection.
+ This requires super-user privileges if anonymous is false.
+ Connection_attempts specifies the maximum number of tries, one per
+ second. This returns true on success, and zero on failure. If the
+ connection is successful, this calls packet_set_connection for the
+ connection. */
+int ssh_connect(const char *host, int port, int connection_attempts,
+ int anonymous, uid_t original_real_uid,
+ const char *proxy_command, RandomState *random_state);
+
+/* Starts a dialog with the server, and authenticates the current user on the
+ server. This does not need any extra privileges. The basic connection
+ to the server must already have been established before this is called.
+ If login fails, this function prints an error and never returns.
+ This initializes the random state, and leaves it initialized (it will also
+ have references from the packet module). */
+void ssh_login(RandomState *state, int host_key_valid, RSAPrivateKey *host_key,
+ const char *host, Options *options, uid_t original_real_uid);
+
+/*------------ Definitions for various authentication methods. -------*/
+
+/* Tries to authenticate the user using the .rhosts file. Returns true if
+ authentication succeeds. If ignore_rhosts is non-zero, this will not
+ consider .rhosts and .shosts (/etc/hosts.equiv will still be used).
+ If strict_modes is true, checks ownership and modes of .rhosts/.shosts. */
+int auth_rhosts(struct passwd *pw, const char *client_user,
+ int ignore_rhosts, int strict_modes);
+
+/* Tries to authenticate the user using the .rhosts file and the host using
+ its host key. Returns true if authentication succeeds. */
+int auth_rhosts_rsa(RandomState *state,
+ struct passwd *pw, const char *client_user,
+ unsigned int bits, MP_INT *client_host_key_e,
+ MP_INT *client_host_key_n, int ignore_rhosts,
+ int strict_modes);
+
+/* Tries to authenticate the user using password. Returns true if
+ authentication succeeds. */
+int auth_password(const char *server_user, const char *password);
+
+/* Performs the RSA authentication dialog with the client. This returns
+ 0 if the client could not be authenticated, and 1 if authentication was
+ successful. This may exit if there is a serious protocol violation. */
+int auth_rsa(struct passwd *pw, MP_INT *client_n, RandomState *state);
+
+/* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
+ over the key. Skips any whitespace at the beginning and at end. */
+int auth_rsa_read_key(char **cpp, unsigned int *bitsp, MP_INT *e, MP_INT *n);
+
+/* Returns the name of the machine at the other end of the socket. The
+ returned string should be freed by the caller. */
+char *get_remote_hostname(int socket);
+
+/* Return the canonical name of the host in the other side of the current
+ connection (as returned by packet_get_connection). The host name is
+ cached, so it is efficient to call this several times. */
+const char *get_canonical_hostname(void);
+
+/* Returns the remote IP address as an ascii string. The value need not be
+ freed by the caller. */
+const char *get_remote_ipaddr(void);
+
+/* Returns the port number of the peer of the socket. */
+int get_peer_port(int sock);
+
+/* Returns the port number of the remote host. */
+int get_remote_port(void);
+
+/* Tries to match the host name (which must be in all lowercase) against the
+ comma-separated sequence of subpatterns (each possibly preceded by ! to
+ indicate negation). Returns true if there is a positive match; zero
+ otherwise. */
+int match_hostname(const char *host, const char *pattern, unsigned int len);
+
+/* Checks whether the given host is already in the list of our known hosts.
+ Returns HOST_OK if the host is known and has the specified key,
+ HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
+ but used to have a different host key. The host must be in all lowercase. */
+typedef enum { HOST_OK, HOST_NEW, HOST_CHANGED } HostStatus;
+HostStatus check_host_in_hostfile(const char *filename,
+ const char *host, unsigned int bits,
+ MP_INT *e, MP_INT *n);
+
+/* Appends an entry to the host file. Returns false if the entry
+ could not be appended. */
+int add_host_to_hostfile(const char *filename, const char *host,
+ unsigned int bits, MP_INT *e, MP_INT *n);
+
+/* Performs the RSA authentication challenge-response dialog with the client,
+ and returns true (non-zero) if the client gave the correct answer to
+ our challenge; returns zero if the client gives a wrong answer. */
+int auth_rsa_challenge_dialog(RandomState *state, unsigned int bits,
+ MP_INT *e, MP_INT *n);
+
+/* Reads a passphrase from /dev/tty with echo turned off. Returns the
+ passphrase (allocated with xmalloc). Exits if EOF is encountered.
+ If from_stdin is true, the passphrase will be read from stdin instead. */
+char *read_passphrase(const char *prompt, int from_stdin);
+
+/* Saves the authentication (private) key in a file, encrypting it with
+ passphrase. The identification of the file (lowest 64 bits of n)
+ will precede the key to provide identification of the key without
+ needing a passphrase. */
+int save_private_key(const char *filename, const char *passphrase,
+ RSAPrivateKey *private_key, const char *comment,
+ RandomState *state);
+
+/* Loads the public part of the key file (public key and comment).
+ Returns 0 if an error occurred; zero if the public key was successfully
+ read. The comment of the key is returned in comment_return if it is
+ non-NULL; the caller must free the value with xfree. */
+int load_public_key(const char *filename, RSAPublicKey *pub,
+ char **comment_return);
+
+/* Loads the private key from the file. Returns 0 if an error is encountered
+ (file does not exist or is not readable, or passphrase is bad).
+ This initializes the private key. The comment of the key is returned
+ in comment_return if it is non-NULL; the caller must free the value
+ with xfree. */
+int load_private_key(const char *filename, const char *passphrase,
+ RSAPrivateKey *private_key, char **comment_return);
+
+/*------------ Definitions for logging. -----------------------*/
+
+/* Supported syslog facilities. */
+typedef enum
+{
+ SYSLOG_FACILITY_DAEMON,
+ SYSLOG_FACILITY_USER,
+ SYSLOG_FACILITY_AUTH,
+ SYSLOG_FACILITY_LOCAL0,
+ SYSLOG_FACILITY_LOCAL1,
+ SYSLOG_FACILITY_LOCAL2,
+ SYSLOG_FACILITY_LOCAL3,
+ SYSLOG_FACILITY_LOCAL4,
+ SYSLOG_FACILITY_LOCAL5,
+ SYSLOG_FACILITY_LOCAL6,
+ SYSLOG_FACILITY_LOCAL7
+} SyslogFacility;
+
+/* Initializes logging. If debug is non-zero, debug() will output something.
+ If quiet is non-zero, none of these will log send anything to syslog
+ (but maybe to stderr). */
+void log_init(char *av0, int on_stderr, int debug, int quiet,
+ SyslogFacility facility);
+
+/* Outputs a message to syslog or stderr, depending on the implementation.
+ The format must guarantee that the final message does not exceed 1024
+ characters. The message should not contain newline. */
+void log(const char *fmt, ...);
+
+/* Outputs a message to syslog or stderr, depending on the implementation.
+ The format must guarantee that the final message does not exceed 1024
+ characters. The message should not contain newline. */
+void debug(const char *fmt, ...);
+
+/* Outputs a message to syslog or stderr, depending on the implementation.
+ The format must guarantee that the final message does not exceed 1024
+ characters. The message should not contain newline. */
+void error(const char *fmt, ...);
+
+/* Outputs a message to syslog or stderr, depending on the implementation.
+ The format must guarantee that the final message does not exceed 1024
+ characters. The message should not contain newline.
+ This call never returns. */
+void fatal(const char *fmt, ...);
+
+/* Registers a cleanup function to be called by fatal() before exiting.
+ It is permissible to call fatal_remove_cleanup for the function itself
+ from the function. */
+void fatal_add_cleanup(void (*proc)(void *context), void *context);
+
+/* Removes a cleanup frunction to be called at fatal(). */
+void fatal_remove_cleanup(void (*proc)(void *context), void *context);
+
+/*---------------- definitions for x11.c ------------------*/
+
+
+/* Sets specific protocol options. */
+void channel_set_options(int hostname_in_open);
+
+/* Allocate a new channel object and set its type and socket. Remote_name
+ must have been allocated with xmalloc; this will free it when the channel
+ is freed. */
+int channel_allocate(int type, int sock, char *remote_name);
+
+/* Free the channel and close its socket. */
+void channel_free(int channel);
+
+/* Add any bits relevant to channels in select bitmasks. */
+void channel_prepare_select(fd_set *readset, fd_set *writeset);
+
+/* After select, perform any appropriate operations for channels which
+ have events pending. */
+void channel_after_select(fd_set *readset, fd_set *writeset);
+
+/* If there is data to send to the connection, send some of it now. */
+void channel_output_poll(void);
+
+/* This is called when a packet of type CHANNEL_DATA has just been received.
+ The message type has already been consumed, but channel number and data
+ is still there. */
+void channel_input_data(int payload_len);
+
+/* Returns true if no channel has too much buffered data. */
+int channel_not_very_much_buffered_data(void);
+
+/* This is called after receiving CHANNEL_CLOSE. */
+void channel_input_close(void);
+
+/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION. */
+void channel_input_close_confirmation(void);
+
+/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */
+void channel_input_open_confirmation(void);
+
+/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
+void channel_input_open_failure(void);
+
+/* This closes any sockets that are listening for connections; this removes
+ any unix domain sockets. */
+void channel_stop_listening(void);
+
+/* Closes the sockets of all channels. This is used to close extra file
+ descriptors after a fork. */
+void channel_close_all(void);
+
+/* Returns the maximum file descriptor number used by the channels. */
+int channel_max_fd(void);
+
+/* Returns true if there is still an open channel over the connection. */
+int channel_still_open(void);
+
+/* Returns a string containing a list of all open channels. The list is
+ suitable for displaying to the user. It uses crlf instead of newlines.
+ The caller should free the string with xfree. */
+char *channel_open_message(void);
+
+/* Initiate forwarding of connections to local port "port" through the secure
+ channel to host:port from remote side. This never returns if there
+ was an error. */
+void channel_request_local_forwarding(int port, const char *host,
+ int remote_port);
+
+/* Initiate forwarding of connections to port "port" on remote host through
+ the secure channel to host:port from local side. This never returns
+ if there was an error. This registers that open requests for that
+ port are permitted. */
+void channel_request_remote_forwarding(int port, const char *host,
+ int remote_port);
+
+/* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
+ called by the server, because the user could connect to any port anyway,
+ and the server has no way to know but to trust the client anyway. */
+void channel_permit_all_opens(void);
+
+/* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
+ listening for the port, and sends back a success reply (or disconnect
+ message if there was an error). This never returns if there was an
+ error. */
+void channel_input_port_forward_request(int is_root);
+
+/* This is called after receiving PORT_OPEN message. This attempts to connect
+ to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION or
+ CHANNEL_OPEN_FAILURE. */
+void channel_input_port_open(int payload_len);
+
+/* Creates a port for X11 connections, and starts listening for it.
+ Returns the display name, or NULL if an error was encountered. */
+char *x11_create_display(int screen);
+
+/* Creates an internet domain socket for listening for X11 connections.
+ Returns a suitable value for the DISPLAY variable, or NULL if an error
+ occurs. */
+char *x11_create_display_inet(int screen);
+
+/* This is called when SSH_SMSG_X11_OPEN is received. The packet contains
+ the remote channel number. We should do whatever we want, and respond
+ with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */
+void x11_input_open(int payload_len);
+
+/* Requests forwarding of X11 connections. This should be called on the
+ client only. */
+void x11_request_forwarding(void);
+
+/* Requests forwarding for X11 connections, with authentication spoofing.
+ This should be called in the client only. */
+void x11_request_forwarding_with_spoofing(RandomState *state,
+ const char *proto, const char *data);
+
+/* Local Xauthority file (server only). */
+extern char *xauthfile;
+
+/* Sends a message to the server to request authentication fd forwarding. */
+void auth_request_forwarding(void);
+
+/* Returns the number of the file descriptor to pass to child programs as
+ the authentication fd. */
+int auth_get_fd(void);
+
+/* Returns the name of the forwarded authentication socket. Returns NULL
+ if there is no forwarded authentication socket. The returned value points
+ to a static buffer. */
+char *auth_get_socket_name(void);
+
+/* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
+ This starts forwarding authentication requests. */
+void auth_input_request_forwarding(struct passwd *pw);
+
+/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
+void auth_input_open_request(void);
+
+/* Returns true if the given string matches the pattern (which may contain
+ ? and * as wildcards), and zero if it does not match. */
+int match_pattern(const char *s, const char *pattern);
+
+/* Expands tildes in the file name. Returns data allocated by xmalloc.
+ Warning: this calls getpw*. */
+char *tilde_expand_filename(const char *filename, uid_t my_uid);
+
+/* Gets a file descriptor that won't get closed by shell pathname.
+ If pathname is NULL, the path is inferred from the SHELL environment
+ variable or the user id. */
+int get_permanent_fd(const char *pathname);
+
+/* Performs the interactive session. This handles data transmission between
+ the client and the program. Note that the notion of stdin, stdout, and
+ stderr in this function is sort of reversed: this function writes to
+ stdin (of the child program), and reads from stdout and stderr (of the
+ child program). */
+void server_loop(int pid, int fdin, int fdout, int fderr);
+
+/* Client side main loop for the interactive session. */
+int client_loop(int have_pty, int escape_char);
+
+/* Linked list of custom environment strings (see auth-rsa.c). */
+struct envstring {
+ struct envstring *next;
+ char *s;
+};
+
+#ifdef KRB4
+#include <krb.h>
+
+int ssh_tf_init(uid_t uid);
+int auth_krb4(const char *server_user, KTEXT auth, char **client);
+int auth_kerberos_tgt(struct passwd *pw, const char *string);
+int auth_afs_token(char *server_user, uid_t uid, const char *string);
+
+int creds_to_radix(CREDENTIALS *creds, unsigned char *buf);
+int radix_to_creds(const char *buf, CREDENTIALS *creds);
+
+#endif /* KRB4 */
+
+#endif /* SSH_H */
diff --git a/usr.bin/ssh/ssh_md5.c b/usr.bin/ssh/ssh_md5.c
new file mode 100644
index 00000000000..e0b370e26d3
--- /dev/null
+++ b/usr.bin/ssh/ssh_md5.c
@@ -0,0 +1,237 @@
+/* This code has been heavily hacked by Tatu Ylonen <ylo@cs.hut.fi> to
+ make it compile on machines like Cray that don't have a 32 bit integer
+ type. */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest. This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#include "includes.h"
+#include "ssh_md5.h"
+#include "getput.h"
+
+/*
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD5Init(struct MD5Context *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+ uint32 t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ MD5Transform(ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ MD5Transform(ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ MD5Transform(ctx->buf, ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+
+ /* Append length in bits and transform */
+ PUT_32BIT_LSB_FIRST(ctx->in + 56, ctx->bits[0]);
+ PUT_32BIT_LSB_FIRST(ctx->in + 60, ctx->bits[1]);
+
+ MD5Transform(ctx->buf, ctx->in);
+ PUT_32BIT_LSB_FIRST(digest, ctx->buf[0]);
+ PUT_32BIT_LSB_FIRST(digest + 4, ctx->buf[1]);
+ PUT_32BIT_LSB_FIRST(digest + 8, ctx->buf[2]);
+ PUT_32BIT_LSB_FIRST(digest + 12, ctx->buf[3]);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+ ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void MD5Transform(uint32 buf[4], const unsigned char inext[64])
+{
+ register word32 a, b, c, d, i;
+ word32 in[16];
+
+ for (i = 0; i < 16; i++)
+ in[i] = GET_32BIT_LSB_FIRST(inext + 4 * i);
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+#endif
diff --git a/usr.bin/ssh/ssh_md5.h b/usr.bin/ssh/ssh_md5.h
new file mode 100644
index 00000000000..999fea945a2
--- /dev/null
+++ b/usr.bin/ssh/ssh_md5.h
@@ -0,0 +1,27 @@
+#ifndef MD5_H
+#define MD5_H
+
+typedef word32 uint32;
+
+struct MD5Context {
+ uint32 buf[4];
+ uint32 bits[2];
+ unsigned char in[64];
+};
+
+#define MD5Init ssh_MD5Init
+void MD5Init(struct MD5Context *context);
+#define MD5Update ssh_MD5Update
+void MD5Update(struct MD5Context *context, unsigned char const *buf,
+ unsigned len);
+#define MD5Final ssh_MD5Final
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+#define MD5Transform ssh_MD5Transform
+void MD5Transform(uint32 buf[4], const unsigned char in[64]);
+
+/*
+ * This is needed to make RSAREF happy on some MS-DOS compilers.
+ */
+typedef struct MD5Context MD5_CTX;
+
+#endif /* !MD5_H */
diff --git a/usr.bin/ssh/sshconnect.c b/usr.bin/ssh/sshconnect.c
new file mode 100644
index 00000000000..1ce4b01047f
--- /dev/null
+++ b/usr.bin/ssh/sshconnect.c
@@ -0,0 +1,1434 @@
+/*
+
+sshconnect.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Mar 18 22:15:47 1995 ylo
+
+Code to connect to a remote host, and to perform the client side of the
+login (authentication) dialog.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: sshconnect.c,v 1.1 1999/09/26 20:53:38 deraadt Exp $");
+
+#include <gmp.h>
+#include "xmalloc.h"
+#include "randoms.h"
+#include "rsa.h"
+#include "ssh.h"
+#include "packet.h"
+#include "authfd.h"
+#include "cipher.h"
+#include "ssh_md5.h"
+#include "mpaux.h"
+#include "uidswap.h"
+
+#ifdef KRB4
+#include <krb.h>
+#ifdef AFS
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 4
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#include <kafs.h>
+#endif /* AFS */
+#endif /* KRB4 */
+
+/* Session id for the current session. */
+unsigned char session_id[16];
+
+/* Connect to the given ssh server using a proxy command. */
+
+int ssh_proxy_connect(const char *host, int port, uid_t original_real_uid,
+ const char *proxy_command, RandomState *random_state)
+{
+ Buffer command;
+ const char *cp;
+ char *command_string;
+ int pin[2], pout[2];
+ int pid;
+ char portstring[100];
+
+ /* Convert the port number into a string. */
+ sprintf(portstring, "%d", port);
+
+ /* Build the final command string in the buffer by making the appropriate
+ substitutions to the given proxy command. */
+ buffer_init(&command);
+ for (cp = proxy_command; *cp; cp++)
+ {
+ if (cp[0] == '%' && cp[1] == '%')
+ {
+ buffer_append(&command, "%", 1);
+ cp++;
+ continue;
+ }
+ if (cp[0] == '%' && cp[1] == 'h')
+ {
+ buffer_append(&command, host, strlen(host));
+ cp++;
+ continue;
+ }
+ if (cp[0] == '%' && cp[1] == 'p')
+ {
+ buffer_append(&command, portstring, strlen(portstring));
+ cp++;
+ continue;
+ }
+ buffer_append(&command, cp, 1);
+ }
+ buffer_append(&command, "\0", 1);
+
+ /* Get the final command string. */
+ command_string = buffer_ptr(&command);
+
+ /* Create pipes for communicating with the proxy. */
+ if (pipe(pin) < 0 || pipe(pout) < 0)
+ fatal("Could not create pipes to communicate with the proxy: %.100s",
+ strerror(errno));
+
+ debug("Executing proxy command: %.500s", command_string);
+
+ /* Fork and execute the proxy command. */
+ if ((pid = fork()) == 0)
+ {
+ char *argv[10];
+
+ /* Child. Permanently give up superuser privileges. */
+ permanently_set_uid(original_real_uid);
+
+ /* Redirect stdin and stdout. */
+ close(pin[1]);
+ if (pin[0] != 0)
+ {
+ if (dup2(pin[0], 0) < 0)
+ perror("dup2 stdin");
+ close(pin[0]);
+ }
+ close(pout[0]);
+ if (dup2(pout[1], 1) < 0)
+ perror("dup2 stdout");
+ close(pout[1]); /* Cannot be 1 because pin allocated two descriptors. */
+
+ /* Stderr is left as it is so that error messages get printed on
+ the user's terminal. */
+ argv[0] = "/bin/sh";
+ argv[1] = "-c";
+ argv[2] = command_string;
+ argv[3] = NULL;
+
+ /* Execute the proxy command. Note that we gave up any extra
+ privileges above. */
+ execv("/bin/sh", argv);
+ perror("/bin/sh");
+ exit(1);
+ }
+ /* Parent. */
+ if (pid < 0)
+ fatal("fork failed: %.100s", strerror(errno));
+
+ /* Close child side of the descriptors. */
+ close(pin[0]);
+ close(pout[1]);
+
+ /* Free the command name. */
+ buffer_free(&command);
+
+ /* Set the connection file descriptors. */
+ packet_set_connection(pout[0], pin[1], random_state);
+
+ return 1;
+}
+
+/* Creates a (possibly privileged) socket for use as the ssh connection. */
+
+int ssh_create_socket(uid_t original_real_uid, int privileged)
+{
+ int sock;
+
+ /* If we are running as root and want to connect to a privileged port,
+ bind our own socket to a privileged port. */
+ if (privileged)
+ {
+ struct sockaddr_in sin;
+ int p;
+ for (p = 1023; p > 512; p--)
+ {
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ fatal("socket: %.100s", strerror(errno));
+
+ /* Initialize the desired sockaddr_in structure. */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+ sin.sin_port = htons(p);
+
+ /* Try to bind the socket to the privileged port. */
+ if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ break; /* Success. */
+ if (errno == EADDRINUSE)
+ {
+ close(sock);
+ continue;
+ }
+ fatal("bind: %.100s", strerror(errno));
+ }
+ debug("Allocated local port %d.", p);
+ }
+ else
+ {
+ /* Just create an ordinary socket on arbitrary port. We use the
+ user's uid to create the socket. */
+ temporarily_use_uid(original_real_uid);
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0)
+ fatal("socket: %.100s", strerror(errno));
+ restore_uid();
+ }
+ return sock;
+}
+
+/* Opens a TCP/IP connection to the remote server on the given host. If
+ port is 0, the default port will be used. If anonymous is zero,
+ a privileged port will be allocated to make the connection.
+ This requires super-user privileges if anonymous is false.
+ Connection_attempts specifies the maximum number of tries (one per
+ second). If proxy_command is non-NULL, it specifies the command (with %h
+ and %p substituted for host and port, respectively) to use to contact
+ the daemon. */
+
+int ssh_connect(const char *host, int port, int connection_attempts,
+ int anonymous, uid_t original_real_uid,
+ const char *proxy_command, RandomState *random_state)
+{
+ int sock = -1, attempt, i;
+ int on = 1;
+ struct servent *sp;
+ struct hostent *hp;
+ struct sockaddr_in hostaddr;
+#ifdef SO_LINGER
+ struct linger linger;
+#endif /* SO_LINGER */
+
+ debug("ssh_connect: getuid %d geteuid %d anon %d",
+ (int)getuid(), (int)geteuid(), anonymous);
+
+ /* Get default port if port has not been set. */
+ if (port == 0)
+ {
+ sp = getservbyname(SSH_SERVICE_NAME, "tcp");
+ if (sp)
+ port = ntohs(sp->s_port);
+ else
+ port = SSH_DEFAULT_PORT;
+ }
+
+ /* If a proxy command is given, connect using it. */
+ if (proxy_command != NULL)
+ return ssh_proxy_connect(host, port, original_real_uid, proxy_command,
+ random_state);
+
+ /* No proxy command. */
+
+ /* No host lookup made yet. */
+ hp = NULL;
+
+ /* Try to connect several times. On some machines, the first time will
+ sometimes fail. In general socket code appears to behave quite
+ magically on many machines. */
+ for (attempt = 0; attempt < connection_attempts; attempt++)
+ {
+ if (attempt > 0)
+ debug("Trying again...");
+
+ /* Try to parse the host name as a numeric inet address. */
+ memset(&hostaddr, 0, sizeof(hostaddr));
+ hostaddr.sin_family = AF_INET;
+ hostaddr.sin_port = htons(port);
+#ifdef BROKEN_INET_ADDR
+ hostaddr.sin_addr.s_addr = inet_network(host);
+#else /* BROKEN_INET_ADDR */
+ hostaddr.sin_addr.s_addr = inet_addr(host);
+#endif /* BROKEN_INET_ADDR */
+ if ((hostaddr.sin_addr.s_addr & 0xffffffff) != 0xffffffff)
+ {
+ /* Valid numeric IP address */
+ debug("Connecting to %.100s port %d.",
+ inet_ntoa(hostaddr.sin_addr), port);
+
+ /* Create a socket. */
+ sock = ssh_create_socket(original_real_uid,
+ !anonymous && geteuid() == 0 &&
+ port < 1024);
+
+ /* Connect to the host. We use the user's uid in the hope that
+ it will help with the problems of tcp_wrappers showing the
+ remote uid as root. */
+ temporarily_use_uid(original_real_uid);
+ if (connect(sock, (struct sockaddr *)&hostaddr, sizeof(hostaddr))
+ >= 0)
+ {
+ /* Successful connect. */
+ restore_uid();
+ break;
+ }
+ debug("connect: %.100s", strerror(errno));
+ restore_uid();
+
+ /* Destroy the failed socket. */
+ shutdown(sock, 2);
+ close(sock);
+ }
+ else
+ {
+ /* Not a valid numeric inet address. */
+ /* Map host name to an address. */
+ if (!hp)
+ hp = gethostbyname(host);
+ if (!hp)
+ fatal("Bad host name: %.100s", host);
+ if (!hp->h_addr_list[0])
+ fatal("Host does not have an IP address: %.100s", host);
+
+ /* Loop through addresses for this host, and try each one in
+ sequence until the connection succeeds. */
+ for (i = 0; hp->h_addr_list[i]; i++)
+ {
+ /* Set the address to connect to. */
+ hostaddr.sin_family = hp->h_addrtype;
+ memcpy(&hostaddr.sin_addr, hp->h_addr_list[i],
+ sizeof(hostaddr.sin_addr));
+
+ debug("Connecting to %.200s [%.100s] port %d.",
+ host, inet_ntoa(hostaddr.sin_addr), port);
+
+ /* Create a socket for connecting. */
+ sock = ssh_create_socket(original_real_uid,
+ !anonymous && geteuid() == 0 &&
+ port < 1024);
+
+ /* Connect to the host. We use the user's uid in the hope that
+ it will help with tcp_wrappers showing the remote uid as
+ root. */
+ temporarily_use_uid(original_real_uid);
+ if (connect(sock, (struct sockaddr *)&hostaddr,
+ sizeof(hostaddr)) >= 0)
+ {
+ /* Successful connection. */
+ restore_uid();
+ break;
+ }
+ debug("connect: %.100s", strerror(errno));
+ restore_uid();
+
+ /* Close the failed socket; there appear to be some problems
+ when reusing a socket for which connect() has already
+ returned an error. */
+ shutdown(sock, 2);
+ close(sock);
+ }
+ if (hp->h_addr_list[i])
+ break; /* Successful connection. */
+ }
+
+ /* Sleep a moment before retrying. */
+ sleep(1);
+ }
+ /* Return failure if we didn't get a successful connection. */
+ if (attempt >= connection_attempts)
+ return 0;
+
+ debug("Connection established.");
+
+ /* Set socket options. We would like the socket to disappear as soon as
+ it has been closed for whatever reason. */
+ /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
+#ifdef TCP_NODELAY
+ setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on));
+#endif /* TCP_NODELAY */
+#ifdef SO_LINGER
+ linger.l_onoff = 1;
+ linger.l_linger = 5;
+ setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
+#endif /* SO_LINGER */
+
+ /* Set the connection. */
+ packet_set_connection(sock, sock, random_state);
+
+ return 1;
+}
+
+/* Checks if the user has an authentication agent, and if so, tries to
+ authenticate using the agent. */
+
+int try_agent_authentication()
+{
+ int status, type, bits;
+ MP_INT e, n, challenge;
+ char *comment;
+ AuthenticationConnection *auth;
+ unsigned char response[16];
+ unsigned int i;
+
+ /* Get connection to the agent. */
+ auth = ssh_get_authentication_connection();
+ if (!auth)
+ return 0;
+
+ mpz_init(&e);
+ mpz_init(&n);
+ mpz_init(&challenge);
+
+ /* Loop through identities served by the agent. */
+ for (status = ssh_get_first_identity(auth, &bits, &e, &n, &comment);
+ status;
+ status = ssh_get_next_identity(auth, &bits, &e, &n, &comment))
+ {
+ int plen, clen;
+
+ /* Try this identity. */
+ debug("Trying RSA authentication via agent with '%.100s'", comment);
+ xfree(comment);
+
+ /* Tell the server that we are willing to authenticate using this key. */
+ packet_start(SSH_CMSG_AUTH_RSA);
+ packet_put_mp_int(&n);
+ packet_send();
+ packet_write_wait();
+
+ /* Wait for server's response. */
+ type = packet_read(&plen);
+
+ /* The server sends failure if it doesn\'t like our key or does not
+ support RSA authentication. */
+ if (type == SSH_SMSG_FAILURE)
+ {
+ debug("Server refused our key.");
+ continue;
+ }
+
+ /* Otherwise it should have sent a challenge. */
+ if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
+ packet_disconnect("Protocol error during RSA authentication: %d",
+ type);
+
+ packet_get_mp_int(&challenge, &clen);
+
+ packet_integrity_check(plen, clen, type);
+
+ debug("Received RSA challenge from server.");
+
+ /* Ask the agent to decrypt the challenge. */
+ if (!ssh_decrypt_challenge(auth, bits, &e, &n, &challenge,
+ session_id, 1, response))
+ {
+ /* The agent failed to authenticate this identifier although it
+ advertised it supports this. Just return a wrong value. */
+ log("Authentication agent failed to decrypt challenge.");
+ memset(response, 0, sizeof(response));
+ }
+
+ debug("Sending response to RSA challenge.");
+
+ /* Send the decrypted challenge back to the server. */
+ packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
+ for (i = 0; i < 16; i++)
+ packet_put_char(response[i]);
+ packet_send();
+ packet_write_wait();
+
+ /* Wait for response from the server. */
+ type = packet_read(&plen);
+
+ /* The server returns success if it accepted the authentication. */
+ if (type == SSH_SMSG_SUCCESS)
+ {
+ debug("RSA authentication accepted by server.");
+ mpz_clear(&e);
+ mpz_clear(&n);
+ mpz_clear(&challenge);
+ return 1;
+ }
+
+ /* Otherwise it should return failure. */
+ if (type != SSH_SMSG_FAILURE)
+ packet_disconnect("Protocol error waiting RSA auth response: %d",
+ type);
+ }
+
+ mpz_clear(&e);
+ mpz_clear(&n);
+ mpz_clear(&challenge);
+
+ debug("RSA authentication using agent refused.");
+ return 0;
+}
+
+/* Computes the proper response to a RSA challenge, and sends the response to
+ the server. */
+
+void respond_to_rsa_challenge(MP_INT *challenge, RSAPrivateKey *prv)
+{
+ unsigned char buf[32], response[16];
+ struct MD5Context md;
+ int i;
+
+ /* Decrypt the challenge using the private key. */
+ rsa_private_decrypt(challenge, challenge, prv);
+
+ /* Compute the response. */
+ /* The response is MD5 of decrypted challenge plus session id. */
+ mp_linearize_msb_first(buf, 32, challenge);
+ MD5Init(&md);
+ MD5Update(&md, buf, 32);
+ MD5Update(&md, session_id, 16);
+ MD5Final(response, &md);
+
+ debug("Sending response to host key RSA challenge.");
+
+ /* Send the response back to the server. */
+ packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
+ for (i = 0; i < 16; i++)
+ packet_put_char(response[i]);
+ packet_send();
+ packet_write_wait();
+
+ memset(buf, 0, sizeof(buf));
+ memset(response, 0, sizeof(response));
+ memset(&md, 0, sizeof(md));
+}
+
+/* Checks if the user has authentication file, and if so, tries to authenticate
+ the user using it. */
+
+int try_rsa_authentication(struct passwd *pw, const char *authfile,
+ int may_ask_passphrase)
+{
+ MP_INT challenge;
+ RSAPrivateKey private_key;
+ RSAPublicKey public_key;
+ char *passphrase, *comment;
+ int type, i;
+ int plen, clen;
+
+ /* Try to load identification for the authentication key. */
+ if (!load_public_key(authfile, &public_key, &comment))
+ return 0; /* Could not load it. Fail. */
+
+ debug("Trying RSA authentication with key '%.100s'", comment);
+
+ /* Tell the server that we are willing to authenticate using this key. */
+ packet_start(SSH_CMSG_AUTH_RSA);
+ packet_put_mp_int(&public_key.n);
+ packet_send();
+ packet_write_wait();
+
+ /* We no longer need the public key. */
+ rsa_clear_public_key(&public_key);
+
+ /* Wait for server's response. */
+ type = packet_read(&plen);
+
+ /* The server responds with failure if it doesn\'t like our key or doesn\'t
+ support RSA authentication. */
+ if (type == SSH_SMSG_FAILURE)
+ {
+ debug("Server refused our key.");
+ xfree(comment);
+ return 0; /* Server refuses to authenticate with this key. */
+ }
+
+ /* Otherwise, the server should respond with a challenge. */
+ if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
+ packet_disconnect("Protocol error during RSA authentication: %d", type);
+
+ /* Get the challenge from the packet. */
+ mpz_init(&challenge);
+ packet_get_mp_int(&challenge, &clen);
+
+ packet_integrity_check(plen, clen, type);
+
+ debug("Received RSA challenge from server.");
+
+ /* Load the private key. Try first with empty passphrase; if it fails,
+ ask for a passphrase. */
+ if (!load_private_key(authfile, "", &private_key, NULL))
+ {
+ char buf[300];
+ /* Request passphrase from the user. We read from /dev/tty to make
+ this work even if stdin has been redirected. If running in
+ batch mode, we just use the empty passphrase, which will fail and
+ return. */
+ sprintf(buf, "Enter passphrase for RSA key '%.100s': ", comment);
+ if (may_ask_passphrase)
+ passphrase = read_passphrase(buf, 0);
+ else
+ {
+ debug("Will not query passphrase for %.100s in batch mode.",
+ comment);
+ passphrase = xstrdup("");
+ }
+
+ /* Load the authentication file using the pasphrase. */
+ if (!load_private_key(authfile, passphrase, &private_key, NULL))
+ {
+ memset(passphrase, 0, strlen(passphrase));
+ xfree(passphrase);
+ error("Bad passphrase.");
+
+ /* Send a dummy response packet to avoid protocol error. */
+ packet_start(SSH_CMSG_AUTH_RSA_RESPONSE);
+ for (i = 0; i < 16; i++)
+ packet_put_char(0);
+ packet_send();
+ packet_write_wait();
+
+ /* Expect the server to reject it... */
+ packet_read_expect(&plen, SSH_SMSG_FAILURE);
+ xfree(comment);
+ return 0;
+ }
+
+ /* Destroy the passphrase. */
+ memset(passphrase, 0, strlen(passphrase));
+ xfree(passphrase);
+ }
+
+ /* We no longer need the comment. */
+ xfree(comment);
+
+ /* Compute and send a response to the challenge. */
+ respond_to_rsa_challenge(&challenge, &private_key);
+
+ /* Destroy the private key. */
+ rsa_clear_private_key(&private_key);
+
+ /* We no longer need the challenge. */
+ mpz_clear(&challenge);
+
+ /* Wait for response from the server. */
+ type = packet_read(&plen);
+ if (type == SSH_SMSG_SUCCESS)
+ {
+ debug("RSA authentication accepted by server.");
+ return 1;
+ }
+ if (type != SSH_SMSG_FAILURE)
+ packet_disconnect("Protocol error waiting RSA auth response: %d", type);
+ debug("RSA authentication refused.");
+ return 0;
+}
+
+/* Tries to authenticate the user using combined rhosts or /etc/hosts.equiv
+ authentication and RSA host authentication. */
+
+int try_rhosts_rsa_authentication(const char *local_user,
+ RSAPrivateKey *host_key)
+{
+ int type;
+ MP_INT challenge;
+ int plen, clen;
+
+ debug("Trying rhosts or /etc/hosts.equiv with RSA host authentication.");
+
+ /* Tell the server that we are willing to authenticate using this key. */
+ packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
+ packet_put_string(local_user, strlen(local_user));
+ packet_put_int(host_key->bits);
+ packet_put_mp_int(&host_key->e);
+ packet_put_mp_int(&host_key->n);
+ packet_send();
+ packet_write_wait();
+
+ /* Wait for server's response. */
+ type = packet_read(&plen);
+
+ /* The server responds with failure if it doesn't admit our .rhosts
+ authentication or doesn't know our host key. */
+ if (type == SSH_SMSG_FAILURE)
+ {
+ debug("Server refused our rhosts authentication or host key.");
+ return 0; /* Server refuses to authenticate us with this method. */
+ }
+
+ /* Otherwise, the server should respond with a challenge. */
+ if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
+ packet_disconnect("Protocol error during RSA authentication: %d", type);
+
+ /* Get the challenge from the packet. */
+ mpz_init(&challenge);
+ packet_get_mp_int(&challenge, &clen);
+
+ packet_integrity_check(plen, clen, type);
+
+ debug("Received RSA challenge for host key from server.");
+
+ /* Compute a response to the challenge. */
+ respond_to_rsa_challenge(&challenge, host_key);
+
+ /* We no longer need the challenge. */
+ mpz_clear(&challenge);
+
+ /* Wait for response from the server. */
+ type = packet_read(&plen);
+ if (type == SSH_SMSG_SUCCESS)
+ {
+ debug("Rhosts or /etc/hosts.equiv with RSA host authentication accepted by server.");
+ return 1;
+ }
+ if (type != SSH_SMSG_FAILURE)
+ packet_disconnect("Protocol error waiting RSA auth response: %d", type);
+ debug("Rhosts or /etc/hosts.equiv with RSA host authentication refused.");
+ return 0;
+}
+
+#ifdef KRB4
+int try_kerberos_authentication()
+{
+ KTEXT_ST auth; /* Kerberos data */
+ char *reply;
+ char inst[INST_SZ];
+ char *realm;
+ CREDENTIALS cred;
+ int r, type;
+ Key_schedule schedule;
+ u_long checksum, cksum;
+ MSG_DAT msg_data;
+ struct sockaddr_in local, foreign;
+ struct stat st;
+ int plen;
+
+ /* Don't do anything if we don't have any tickets. */
+ if (stat(tkt_string(), &st) < 0) return 0;
+
+ debug("Trying Kerberos authentication.");
+ strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
+
+ realm = (char *)krb_realmofhost(get_canonical_hostname());
+ if (!realm) {
+ debug("Kerberos V4: no realm for %.100s", get_canonical_hostname());
+ return 0;
+ }
+ /* This can really be anything. */
+ checksum = (u_long) getpid();
+
+ r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
+ if (r != KSUCCESS) {
+ debug("Kerberos V4 krb_mk_req failed: %.100s", krb_err_txt[r]);
+ return 0;
+ }
+ /* Get session key to decrypt the server's reply with. */
+ r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred);
+ if (r != KSUCCESS) {
+ debug("get_cred failed: %.100s", krb_err_txt[r]);
+ return 0;
+ }
+ des_key_sched((des_cblock *)cred.session, schedule);
+
+ /* Send authentication info to server. */
+ packet_start(SSH_CMSG_AUTH_KERBEROS);
+ packet_put_string((char *)auth.dat, auth.length);
+ packet_send();
+ packet_write_wait();
+
+ /* zero the buffer */
+ (void) memset(auth.dat, 0, MAX_KTXT_LEN);
+
+ r = sizeof(local);
+ memset(&local, 0, sizeof(local));
+ if (getsockname(packet_get_connection_in(),
+ (struct sockaddr *) &local, &r) < 0)
+ debug("getsockname failed: %.100s", strerror(errno));
+
+ r = sizeof(foreign);
+ memset(&foreign, 0, sizeof(foreign));
+ if (getpeername(packet_get_connection_in(),
+ (struct sockaddr *)&foreign, &r) < 0)
+ debug("getpeername failed: %.100s", strerror(errno));
+
+ /* Get server reply. */
+ type = packet_read(&plen);
+ switch(type) {
+
+ case SSH_SMSG_FAILURE: /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
+ debug("Kerberos V4 authentication failed.");
+ return 0;
+ break;
+
+ case SSH_SMSG_AUTH_KERBEROS_RESPONSE: /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
+ debug("Kerberos V4 authentication accepted.");
+
+ /* Get server's response. */
+ reply = packet_get_string((unsigned int *)&auth.length);
+ memcpy(auth.dat, reply, auth.length);
+ xfree(reply);
+
+ packet_integrity_check(plen, 4 + auth.length, type);
+
+ /* If his response isn't properly encrypted with the session key,
+ and the decrypted checksum fails to match, he's bogus. Bail out. */
+ r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
+ &foreign, &local, &msg_data);
+ if (r != KSUCCESS) {
+ debug("Kerberos V4 krb_rd_priv failed: %.100s", krb_err_txt[r]);
+ packet_disconnect("Kerberos V4 challenge failed!");
+ }
+ /* fetch the (incremented) checksum that we supplied in the request */
+ (void)memcpy((char *)&cksum, (char *)msg_data.app_data, sizeof(cksum));
+ cksum = ntohl(cksum);
+
+ /* If it matches, we're golden. */
+ if (cksum == checksum + 1) {
+ debug("Kerberos V4 challenge successful.");
+ return 1;
+ }
+ else
+ packet_disconnect("Kerberos V4 challenge failed!");
+ break;
+
+ default:
+ packet_disconnect("Protocol error on Kerberos V4 response: %d", type);
+ }
+ return 0;
+}
+#endif /* KRB4 */
+
+#ifdef AFS
+
+#ifdef KERBEROS_TGT_PASSING
+int send_kerberos_tgt()
+{
+ CREDENTIALS *creds;
+ char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
+ int r, plen, type;
+ unsigned char buffer[8192];
+ struct stat st;
+
+ /* Don't do anything if we don't have any tickets. */
+ if (stat(tkt_string(), &st) < 0) return 0;
+
+ creds = xmalloc(sizeof(CREDENTIALS));
+
+ if ((r=krb_get_tf_fullname(TKT_FILE,pname,pinst,prealm)) != KSUCCESS) {
+ debug("Kerberos V4 tf_fullname failed: %.100s",krb_err_txt[r]);
+ return 0;
+}
+ if ((r=krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) {
+ debug("Kerberos V4 get_cred failed: %.100s", krb_err_txt[r]);
+ return 0;
+ }
+ if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {
+ debug("Kerberos V4 ticket expired: %.100s", TKT_FILE);
+ return 0;
+ }
+
+ creds_to_radix(creds, buffer);
+ xfree(creds);
+
+ packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
+ packet_put_string((char *)buffer, strlen(buffer));
+ packet_send();
+ packet_write_wait();
+
+ type = packet_read(&plen);
+
+ if (type == SSH_SMSG_FAILURE)
+ debug("Kerberos TGT for realm %.100s rejected.", prealm);
+ else if (type != SSH_SMSG_SUCCESS)
+ packet_disconnect("Protocol error on Kerberos TGT response: %d", type);
+
+ return 1;
+}
+#endif /* KERBEROS_TGT_PASSING */
+
+/* Forwards our AFS tokens to the server. */
+void send_afs_tokens(void)
+{
+ CREDENTIALS creds;
+ struct ViceIoctl parms;
+ struct ClearToken ct;
+ int i, type;
+ int len, plen;
+ char buf[2048], *p, *server_cell;
+ unsigned char buffer[8192];
+
+ /* Move over ktc_GetToken, here's something leaner. */
+ for (i = 0; i < 100; i++) { /* just in case */
+ parms.in = (char *)&i;
+ parms.in_size = sizeof(i);
+ parms.out = buf;
+ parms.out_size = sizeof(buf);
+ if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) break;
+ p = buf;
+
+ /* Get secret token. */
+ memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
+ if (creds.ticket_st.length > MAX_KTXT_LEN) break;
+ p += sizeof(unsigned int);
+ memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
+ p += creds.ticket_st.length;
+
+ /* Get clear token. */
+ memcpy(&len, p, sizeof(len));
+ if (len != sizeof(struct ClearToken)) break;
+ p += sizeof(len);
+ memcpy(&ct, p, len);
+ p += len;
+ p += sizeof(len); /* primary flag */
+ server_cell = p;
+
+ /* Flesh out our credentials. */
+ strcpy(creds.service, "afs");
+ creds.instance[0] = '\0';
+ strncpy(creds.realm, server_cell, REALM_SZ);
+ memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
+ creds.issue_date = ct.BeginTimestamp;
+ creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp);
+ creds.kvno = ct.AuthHandle;
+ sprintf(creds.pname, "AFS ID %d", ct.ViceId);
+ creds.pinst[0] = '\0';
+
+ /* Encode token, ship it off. */
+ if (!creds_to_radix(&creds, buffer)) break;
+ packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
+ packet_put_string((char *)buffer, strlen(buffer));
+ packet_send();
+ packet_write_wait();
+
+ /* Roger, Roger. Clearance, Clarence. What's your vector, Victor? */
+ type = packet_read(&plen);
+
+ if (type == SSH_SMSG_FAILURE)
+ debug("AFS token for cell %.100s rejected.", server_cell);
+ else if (type != SSH_SMSG_SUCCESS)
+ packet_disconnect("Protocol error on AFS token response: %d", type);
+ }
+}
+#endif /* AFS */
+
+/* Waits for the server identification string, and sends our own identification
+ string. */
+
+void ssh_exchange_identification()
+{
+ char buf[256], remote_version[256]; /* must be same size! */
+ int remote_major, remote_minor, i;
+ int connection_in = packet_get_connection_in();
+ int connection_out = packet_get_connection_out();
+
+ /* Read other side\'s version identification. */
+ for (i = 0; i < sizeof(buf) - 1; i++)
+ {
+ if (read(connection_in, &buf[i], 1) != 1)
+ fatal("read: %.100s", strerror(errno));
+ if (buf[i] == '\r')
+ {
+ buf[i] = '\n';
+ buf[i + 1] = 0;
+ break;
+ }
+ if (buf[i] == '\n')
+ {
+ buf[i + 1] = 0;
+ break;
+ }
+ }
+ buf[sizeof(buf) - 1] = 0;
+
+ /* Check that the versions match. In future this might accept several
+ versions and set appropriate flags to handle them. */
+ if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
+ remote_version) != 3)
+ fatal("Bad remote protocol version identification: '%.100s'", buf);
+ debug("Remote protocol version %d.%d, remote software version %.100s",
+ remote_major, remote_minor, remote_version);
+#if 0
+ /* Removed for now, to permit compatibility with latter versions. The server
+ will reject our version and disconnect if it doesn't support it. */
+ if (remote_major != PROTOCOL_MAJOR)
+ fatal("Protocol major versions differ: %d vs. %d",
+ PROTOCOL_MAJOR, remote_major);
+#endif
+
+ /* Check if the remote protocol version is too old. */
+ if (remote_major == 1 && remote_minor == 0)
+ fatal("Remote machine has too old SSH software version.");
+
+ /* Send our own protocol version identification. */
+ sprintf(buf, "SSH-%d.%d-%.100s\n",
+ PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
+ if (write(connection_out, buf, strlen(buf)) != strlen(buf))
+ fatal("write: %.100s", strerror(errno));
+}
+
+int ssh_cipher_default = SSH_CIPHER_3DES;
+
+int read_yes_or_no(const char *prompt, int defval)
+{
+ char buf[1024];
+ FILE *f;
+ int retval = -1;
+
+ if (isatty(0))
+ f = stdin;
+ else
+ f = fopen("/dev/tty", "rw");
+
+ if (f == NULL)
+ return 0;
+
+ fflush(stdout);
+
+ while (1)
+ {
+ fprintf(stderr, "%s", prompt);
+ if (fgets(buf, sizeof(buf), f) == NULL)
+ {
+ /* Print a newline (the prompt probably didn\'t have one). */
+ fprintf(stderr, "\n");
+ strcpy(buf, "no");
+ }
+ /* Remove newline from response. */
+ if (strchr(buf, '\n'))
+ *strchr(buf, '\n') = 0;
+
+ if (buf[0] == 0)
+ retval = defval;
+ if (strcmp(buf, "yes") == 0)
+ retval = 1;
+ if (strcmp(buf, "no") == 0)
+ retval = 0;
+
+ if (retval != -1)
+ {
+ if (f != stdin)
+ fclose(f);
+ return retval;
+ }
+ }
+}
+
+/* Starts a dialog with the server, and authenticates the current user on the
+ server. This does not need any extra privileges. The basic connection
+ to the server must already have been established before this is called.
+ User is the remote user; if it is NULL, the current local user name will
+ be used. Anonymous indicates that no rhosts authentication will be used.
+ If login fails, this function prints an error and never returns.
+ This function does not require super-user privileges. */
+
+void ssh_login(RandomState *state, int host_key_valid,
+ RSAPrivateKey *own_host_key,
+ const char *orighost,
+ Options *options, uid_t original_real_uid)
+{
+ int i, type;
+ char buf[1024];
+ char *password;
+ struct passwd *pw;
+ MP_INT key;
+ RSAPublicKey host_key;
+ RSAPublicKey public_key;
+ unsigned char session_key[SSH_SESSION_KEY_LENGTH];
+ const char *server_user, *local_user;
+ char *cp, *host;
+ struct stat st;
+ unsigned char check_bytes[8];
+ unsigned int supported_ciphers, supported_authentications, protocol_flags;
+ HostStatus host_status;
+ int payload_len, clen, sum_len = 0;
+
+ /* Convert the user-supplied hostname into all lowercase. */
+ host = xstrdup(orighost);
+ for (cp = host; *cp; cp++)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+
+ /* Exchange protocol version identification strings with the server. */
+ ssh_exchange_identification();
+
+ /* Put the connection into non-blocking mode. */
+ packet_set_nonblocking();
+
+ /* Get local user name. Use it as server user if no user name
+ was given. */
+ pw = getpwuid(original_real_uid);
+ if (!pw)
+ fatal("User id %d not found from user database.", original_real_uid);
+ local_user = xstrdup(pw->pw_name);
+ server_user = options->user ? options->user : local_user;
+
+ debug("Waiting for server public key.");
+
+ /* Wait for a public key packet from the server. */
+ packet_read_expect(&payload_len, SSH_SMSG_PUBLIC_KEY);
+
+ /* Get check bytes from the packet. */
+ for (i = 0; i < 8; i++)
+ check_bytes[i] = packet_get_char();
+
+ /* Get the public key. */
+ public_key.bits = packet_get_int();
+ mpz_init(&public_key.e);
+ packet_get_mp_int(&public_key.e, &clen);
+ sum_len += clen;
+ mpz_init(&public_key.n);
+ packet_get_mp_int(&public_key.n, &clen);
+ sum_len += clen;
+
+ /* Get the host key. */
+ host_key.bits = packet_get_int();
+ mpz_init(&host_key.e);
+ packet_get_mp_int(&host_key.e, &clen);
+ sum_len += clen;
+ mpz_init(&host_key.n);
+ packet_get_mp_int(&host_key.n, &clen);
+ sum_len += clen;
+
+ /* Get protocol flags. */
+ protocol_flags = packet_get_int();
+ packet_set_protocol_flags(protocol_flags);
+
+ /* Get supported cipher types. */
+ supported_ciphers = packet_get_int();
+
+ /* Get supported authentication types. */
+ supported_authentications = packet_get_int();
+
+ debug("Received server public key (%d bits) and host key (%d bits).",
+ public_key.bits, host_key.bits);
+
+ packet_integrity_check(payload_len,
+ 8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
+ SSH_SMSG_PUBLIC_KEY);
+
+ /* Compute the session id. */
+ compute_session_id(session_id, check_bytes, host_key.bits, &host_key.n,
+ public_key.bits, &public_key.n);
+
+ /* Check if the host key is present in the user\'s list of known hosts
+ or in the systemwide list. */
+ host_status = check_host_in_hostfile(options->user_hostfile,
+ host, host_key.bits,
+ &host_key.e, &host_key.n);
+ if (host_status == HOST_NEW)
+ host_status = check_host_in_hostfile(options->system_hostfile, host,
+ host_key.bits, &host_key.e,
+ &host_key.n);
+
+ /* Force accepting of the host key for localhost and 127.0.0.1.
+ The problem is that if the home directory is NFS-mounted to multiple
+ machines, localhost will refer to a different machine in each of them,
+ and the user will get bogus HOST_CHANGED warnings. This essentially
+ disables host authentication for localhost; however, this is probably
+ not a real problem. */
+ if (strcmp(host, "localhost") == 0 ||
+ strcmp(host, "127.0.0.1") == 0)
+ {
+ debug("Forcing accepting of host key for localhost.");
+ host_status = HOST_OK;
+ }
+
+ switch (host_status)
+ {
+ case HOST_OK:
+ /* The host is known and the key matches. */
+ debug("Host '%.200s' is known and matches the host key.", host);
+ break;
+ case HOST_NEW:
+ /* The host is new. */
+ if (options->strict_host_key_checking == 1)
+ { /* User has requested strict host key checking. We will not
+ add the host key automatically. The only alternative left
+ is to abort. */
+ fatal("No host key is known for %.200s and you have requested strict checking.", host);
+ }
+ else if (options->strict_host_key_checking == 2) /* The default */
+ {
+ char prompt[1024];
+ sprintf(prompt,
+ "The authenticity of host '%.200s' can't be established.\n"
+ "Are you sure you want to continue connecting (yes/no)? ",
+ host);
+ if (!read_yes_or_no(prompt, -1))
+ fatal("Aborted by user!\n");
+ }
+ /* If not in strict mode, add the key automatically to the local
+ known_hosts file. */
+ if (!add_host_to_hostfile(options->user_hostfile, host, host_key.bits,
+ &host_key.e, &host_key.n))
+ log("Failed to add the host to the list of known hosts (%.500s).",
+ options->user_hostfile);
+ else
+ log("Warning: Permanently added host '%.200s' to the list of known hosts.", host);
+ break;
+ case HOST_CHANGED:
+ /* The host key has changed. */
+ error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ error("@ WARNING: HOST IDENTIFICATION HAS CHANGED! @");
+ error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+ error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
+ error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
+ error("It is also possible that the host key has just been changed.");
+ error("Please contact your system administrator.");
+ error("Add correct host key in %.100s to get rid of this message.",
+ options->user_hostfile);
+
+ /* If strict host key checking is in use, the user will have to edit
+ the key manually and we can only abort. */
+ if (options->strict_host_key_checking)
+ fatal("Host key for %.200s has changed and you have requested strict checking.", host);
+
+ /* If strict host key checking has not been requested, allow the
+ connection but without password authentication. */
+ error("Password authentication is disabled to avoid trojan horses.");
+ options->password_authentication = 0;
+ /* XXX Should permit the user to change to use the new id. This could
+ be done by converting the host key to an identifying sentence, tell
+ that the host identifies itself by that sentence, and ask the user
+ if he/she whishes to accept the authentication. */
+ break;
+ }
+
+ /* Generate a session key. */
+
+ /* Initialize the random number generator. */
+ sprintf(buf, "%.500s/%.200s", pw->pw_dir, SSH_CLIENT_SEEDFILE);
+ if (stat(buf, &st) < 0)
+ log("Creating random seed file ~/%.900s. This may take a while.",
+ SSH_CLIENT_SEEDFILE);
+ else
+ debug("Initializing random; seed file %.900s", buf);
+ random_initialize(state, buf);
+
+ /* Generate an encryption key for the session. The key is a 256 bit
+ random number, interpreted as a 32-byte key, with the least significant
+ 8 bits being the first byte of the key. */
+ for (i = 0; i < 32; i++)
+ session_key[i] = random_get_byte(state);
+
+ /* Save the new random state. */
+ random_save(state, buf);
+ random_stir(state); /* This is supposed to be irreversible. */
+
+ /* According to the protocol spec, the first byte of the session key is
+ the highest byte of the integer. The session key is xored with the
+ first 16 bytes of the session id. */
+ mpz_init_set_ui(&key, 0);
+ for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++)
+ {
+ mpz_mul_2exp(&key, &key, 8);
+ if (i < 16)
+ mpz_add_ui(&key, &key, session_key[i] ^ session_id[i]);
+ else
+ mpz_add_ui(&key, &key, session_key[i]);
+ }
+
+ /* Encrypt the integer using the public key and host key of the server
+ (key with smaller modulus first). */
+ if (mpz_cmp(&public_key.n, &host_key.n) < 0)
+ {
+ /* Public key has smaller modulus. */
+ assert(host_key.bits >= public_key.bits + SSH_KEY_BITS_RESERVED);
+
+ rsa_public_encrypt(&key, &key, &public_key, state);
+ rsa_public_encrypt(&key, &key, &host_key, state);
+ }
+ else
+ {
+ /* Host key has smaller modulus (or they are equal). */
+ assert(public_key.bits >= host_key.bits + SSH_KEY_BITS_RESERVED);
+
+ rsa_public_encrypt(&key, &key, &host_key, state);
+ rsa_public_encrypt(&key, &key, &public_key, state);
+ }
+
+ if (options->cipher == SSH_CIPHER_NOT_SET)
+ if (cipher_mask() & supported_ciphers & (1 << ssh_cipher_default))
+ options->cipher = ssh_cipher_default;
+ else
+ {
+ debug("Cipher %d not supported, using %.100s instead.",
+ cipher_name(ssh_cipher_default),
+ cipher_name(SSH_FALLBACK_CIPHER));
+ options->cipher = SSH_FALLBACK_CIPHER;
+ }
+
+ /* Check that the selected cipher is supported. */
+ if (!(supported_ciphers & (1 << options->cipher)))
+ fatal("Selected cipher type %.100s not supported by server.",
+ cipher_name(options->cipher));
+
+ debug("Encryption type: %.100s", cipher_name(options->cipher));
+
+ /* Send the encrypted session key to the server. */
+ packet_start(SSH_CMSG_SESSION_KEY);
+ packet_put_char(options->cipher);
+
+ /* Send the check bytes back to the server. */
+ for (i = 0; i < 8; i++)
+ packet_put_char(check_bytes[i]);
+
+ /* Send the encrypted encryption key. */
+ packet_put_mp_int(&key);
+
+ /* Send protocol flags. */
+ packet_put_int(SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
+
+ /* Send the packet now. */
+ packet_send();
+ packet_write_wait();
+
+ /* Destroy the session key integer and the public keys since we no longer
+ need them. */
+ mpz_clear(&key);
+ rsa_clear_public_key(&public_key);
+ rsa_clear_public_key(&host_key);
+
+ debug("Sent encrypted session key.");
+
+ /* Set the encryption key. */
+ packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH,
+ options->cipher, 1);
+
+ /* We will no longer need the session key here. Destroy any extra copies. */
+ memset(session_key, 0, sizeof(session_key));
+
+ /* Expect a success message from the server. Note that this message will
+ be received in encrypted form. */
+ packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
+
+ debug("Received encrypted confirmation.");
+
+ /* Send the name of the user to log in as on the server. */
+ packet_start(SSH_CMSG_USER);
+ packet_put_string(server_user, strlen(server_user));
+ packet_send();
+ packet_write_wait();
+
+ /* The server should respond with success if no authentication is needed
+ (the user has no password). Otherwise the server responds with
+ failure. */
+ type = packet_read(&payload_len);
+ if (type == SSH_SMSG_SUCCESS)
+ return; /* Connection was accepted without authentication. */
+ if (type != SSH_SMSG_FAILURE)
+ packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER",
+ type);
+
+#ifdef KERBEROS_TGT_PASSING
+ /* Try Kerberos tgt passing if the server supports it. */
+ if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
+ options->kerberos_tgt_passing) {
+ if (options->cipher == SSH_CIPHER_NONE)
+ log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
+ (void)send_kerberos_tgt();
+ }
+#endif /* KERBEROS_TGT_PASSING */
+
+#ifdef AFS
+ /* Try AFS token passing if the server supports it. */
+ if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
+ options->afs_token_passing && k_hasafs()) {
+ if (options->cipher == SSH_CIPHER_NONE)
+ log("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
+ send_afs_tokens();
+ }
+#endif /* AFS */
+
+#if defined(KRB4)
+ if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
+ options->kerberos_authentication)
+ {
+ if (try_kerberos_authentication()) {
+ /* The server should respond with success or failure. */
+ type = packet_read(&payload_len);
+ if (type == SSH_SMSG_SUCCESS)
+ return; /* Successful connection. */
+ if (type != SSH_SMSG_FAILURE)
+ packet_disconnect("Protocol error: got %d in response to Kerberos auth", type);
+ }
+ }
+#endif /* KRB4 */
+
+ /* Use rhosts authentication if running in privileged socket and we do not
+ wish to remain anonymous. */
+ if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) &&
+ options->rhosts_authentication)
+ {
+ debug("Trying rhosts authentication.");
+ packet_start(SSH_CMSG_AUTH_RHOSTS);
+ packet_put_string(local_user, strlen(local_user));
+ packet_send();
+ packet_write_wait();
+
+ /* The server should respond with success or failure. */
+ type = packet_read(&payload_len);
+ if (type == SSH_SMSG_SUCCESS)
+ return; /* Successful connection. */
+ if (type != SSH_SMSG_FAILURE)
+ packet_disconnect("Protocol error: got %d in response to rhosts auth",
+ type);
+ }
+
+ /* Try .rhosts or /etc/hosts.equiv authentication with RSA host
+ authentication. */
+ if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
+ options->rhosts_rsa_authentication && host_key_valid)
+ {
+ if (try_rhosts_rsa_authentication(local_user, own_host_key))
+ return; /* Successful authentication. */
+ }
+
+ /* Try RSA authentication if the server supports it. */
+ if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
+ options->rsa_authentication)
+ {
+ /* Try RSA authentication using the authentication agent. The agent
+ is tried first because no passphrase is needed for it, whereas
+ identity files may require passphrases. */
+ if (try_agent_authentication())
+ return; /* Successful connection. */
+
+ /* Try RSA authentication for each identity. */
+ for (i = 0; i < options->num_identity_files; i++)
+ if (try_rsa_authentication(pw, options->identity_files[i],
+ !options->batch_mode))
+ return; /* Successful connection. */
+ }
+
+ /* Try password authentication if the server supports it. */
+ if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
+ options->password_authentication && !options->batch_mode)
+ {
+ debug("Doing password authentication.");
+ if (options->cipher == SSH_CIPHER_NONE)
+ log("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
+ password = read_passphrase("Password: ", 0);
+ packet_start(SSH_CMSG_AUTH_PASSWORD);
+ packet_put_string(password, strlen(password));
+ memset(password, 0, strlen(password));
+ xfree(password);
+ packet_send();
+ packet_write_wait();
+
+ type = packet_read(&payload_len);
+ if (type == SSH_SMSG_SUCCESS)
+ return; /* Successful connection. */
+ if (type != SSH_SMSG_FAILURE)
+ packet_disconnect("Protocol error: got %d in response to passwd auth",
+ type);
+ }
+
+ /* All authentication methods have failed. Exit with an error message. */
+ fatal("Permission denied.");
+ /*NOTREACHED*/
+}
diff --git a/usr.bin/ssh/sshd.8 b/usr.bin/ssh/sshd.8
new file mode 100644
index 00000000000..5bffcc2be70
--- /dev/null
+++ b/usr.bin/ssh/sshd.8
@@ -0,0 +1,734 @@
+.\" -*- nroff -*-
+.\"
+.\" sshd.8.in
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\"
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" Created: Sat Apr 22 21:55:14 1995 ylo
+.\"
+.\" $Id: sshd.8,v 1.1 1999/09/26 20:53:38 deraadt Exp $
+.\"
+.TH SSHD 8 "November 8, 1995" "SSH" "SSH"
+
+.SH NAME
+sshd \- secure shell daemon
+
+.SH SYNOPSIS
+.na
+.B sshd
+[\c
+.BI \-b \ bits\fR\c
+]
+[\c
+.B \-d \c
+]
+[\c
+.BI \-f \ config_file\fR\c
+]
+[\c
+.BI \-g \ login_grace_time\fR\c
+]
+[\c
+.BI \-h \ host_key_file\fR\c
+]
+[\c
+.B \-i \c
+]
+[\c
+.BI \-k \ key_gen_time\fR\c
+]
+[\c
+.BI \-p \ port\fR\c
+]
+[\c
+.B \-q \c
+]
+.ad
+
+
+.SH DESCRIPTION
+.LP
+.B Sshd
+(Secure Shell Daemon) is the daemon program for
+.BR ssh ".
+Together these programs replace rlogin and rsh programs, and
+provide secure encrypted communications between two untrusted hosts
+over an insecure network. The programs are intended to be as easy to
+install and use as possible.
+.LP
+.B Sshd
+is the daemon that listens for connections from clients. It is
+normally started at boot from
+.I /etc/rc.local
+or equivalent. It forks a new
+daemon for each incoming connection. The forked daemons handle
+key exchange, encryption, authentication, command execution,
+and data exchange.
+.LP
+Sshd works as follows. Each host has a host-specific RSA key
+(normally 1024 bits) used to identify the host. Additionally, when
+the daemon starts, it generates a server RSA key (normally 768 bits).
+This key is normally regenerated every hour if it has been used, and
+is never stored on disk.
+.LP
+Whenever a client connects the daemon, the daemon sends its host
+and server public keys to the client. The client compares the
+host key against its own database to verify that it has not changed.
+The client then generates a 256 bit random number. It encrypts this
+random number using both the host key and the server key, and sends
+the encrypted number to the server. Both sides then start to use this
+random number as a session key which is used to encrypt all further
+communications in the session. The rest of the session is encrypted
+using a conventional cipher. Currently,
+.BR \s-1Blowfish\s0 ",
+.BR \s-1IDEA\s0 ",
+.BR \s-1DES\s0 ",
+.BR \s-1\&3DES\s0 ",
+.B \s-13DES\s0
+is used by default. The client selects the encryption algorithm to use
+from those offered by the server.
+.LP
+Next, the server and the client enter an authentication dialog. The
+client tries to authenticate itself using \|\s+2.\s0rhosts
+authentication, \|\s+2.\s0rhosts authentication combined with RSA host
+authentication, RSA challenge-response authentication, or password
+based authentication.
+.LP
+Rhosts authentication is normally disabled
+because it is fundamentally insecure, but can be enabled in the server
+configuration file if desired. System security is not improved unless
+.BR rshd "(8),
+.BR rlogind "(8),
+.BR rexecd "(8), and
+.B rexd "(8)
+are disabled (thus completely disabling
+.BR rlogin (1)
+and
+.BR rsh (1)
+into that machine).
+.LP
+If the client successfully authenticates itself, a dialog for
+preparing the session is entered. At this time the client may request
+things like allocating a pseudo-tty, forwarding X11 connections,
+forwarding TCP/IP connections, or forwarding the authentication agent
+connection over the secure channel.
+.LP
+Finally, the client either requests a shell or execution of a command.
+The sides then enter session mode. In this mode, either side may send
+data at any time, and such data is forwarded to/from the shell or
+command on the server side, and the user terminal in the client side.
+.LP
+When the user program terminates and all forwarded X11 and other
+connections have been closed, the server sends command exit status to
+the client, and both sides exit.
+.LP
+.B Sshd
+can be configured using command-line options or a configuration
+file. Command-line options override values specified in the
+configuration file.
+
+
+.SH OPTIONS
+.TP
+.BI \-b \ bits
+Specifies the number of bits in the server key (default 768).
+.TP
+.B \-d
+Debug mode. The server sends verbose debug output to the system
+log, and does not put itself in the background. The server also will
+not fork and will only process one connection. This option is only
+intended for debugging for the server.
+.TP
+.BI \-f \ configuration_file
+Specifies the name of the configuration file. The default is
+.IR /etc/sshd_config ".
+.TP
+.BI \-g \ login_grace_time
+Gives the grace time for clients to authenticate themselves (default
+300 seconds). If the client fails to authenticate the user within
+this many seconds, the server disconnects and exits. A value of zero
+indicates no limit.
+.TP
+.BI \-h \ host_key_file
+Specifies the file from which the host key is read (default
+.IR /etc/ssh_host_key).
+This option must be given if sshd is not run as root (as the normal
+host file is normally not readable by anyone but root).
+.TP
+.B \-i
+Specifies that sshd is being run from inetd. Sshd is normally not run
+from inetd because it needs to generate the server key before it can
+respond to the client, and this may take tens of seconds. Clients
+would have to wait too long if the key was regenerated every time.
+However, with small key sizes (e.g. 512) using sshd from inetd may
+be feasible.
+.TP
+.BI \-k \ key_gen_time
+Specifies how often the server key is regenerated (default 3600
+seconds, or one hour). The motivation for regenerating the key fairly
+often is that the key is not stored anywhere, and after about an hour,
+it becomes impossible to recover the key for decrypting intercepted
+communications even if the machine is cracked into or physically
+seized. A value of zero indicates that the key will never be regenerated.
+.TP
+.BI \-p \ port
+Specifies the port on which the server listens for connections
+(default 22).
+.TP
+.B \-q
+Quiet mode. Nothing is sent to the system log. Normally the beginning,
+authentication, and termination of each connection is logged.
+
+.SH CONFIGURATION FILE
+
+.B Sshd
+reads configuration data from
+.I /etc/sshd_config
+(or the file specified with -f on the command line). The file
+contains keyword-value pairs, one per line. Lines starting with '#'
+and empty lines are interpreted as comments.
+
+The following keywords are possible.
+.TP
+.B AFSTokenPassing
+Specifies whether to accept AFS tokens passed from the client. Default
+is "yes".
+.TP
+.B AllowHosts
+This keyword can be followed by any number of host name patterns,
+separated by spaces. If specified, login is allowed only from hosts
+whose name matches one of the patterns. '*' and '?' can be used as
+wildcards in the patterns. Normal name servers are used to map the
+client's host into a canonical host name. If the name cannot be
+mapped, its IP-address is used as the host name. By default all hosts
+are allowed to connect.
+
+Note that
+.B sshd
+can also be configured to use tcp_wrappers using the --with-libwrap
+compile-time configuration option.
+.TP
+.B DenyHosts
+This keyword can be followed by any number of host name patterns,
+separated by spaces. If specified, login is disallowed from the hosts
+whose name matches any of the patterns.
+.TP
+.B FascistLogging
+Specifies whether to use verbose logging. Verbose logging violates
+the privacy of users and is not recommended. The argument must be
+"yes" or "no" (without the quotes). The default is "no".
+.TP
+.B HostKey
+Specifies the file containing the private host key (default
+.IR /etc/ssh_host_key ").
+.TP
+.B IgnoreRhosts
+Specifies that rhosts and shosts files will not be used in
+authentication.
+.I /etc/hosts.equiv
+and
+.I /etc/shosts.equiv
+are still used. The default is "no".
+.TP
+.B KeepAlive
+Specifies whether the system should send keepalive messages to the
+other side. If they are sent, death of the connection or crash of one
+of the machines will be properly noticed. However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying. On the other hand, if keepalives are not send,
+sessions may hang indefinitely on the server, leaving "ghost" users
+and consuming server resources.
+
+The default is "yes" (to send keepalives), and the server will notice
+if the network goes down or the client host reboots. This avoids
+infinitely hanging sessions.
+
+To disable keepalives, the value should be set to "no" in both the
+server and the client configuration files.
+.TP
+.B KerberosAuthentication
+Specifies whether Kerberos authentication is allowed. This can
+be in the form of a Kerberos ticket, or if PasswordAuthentication
+is yes, the password provided by the user will be validated through
+the Kerberos KDC / AFS kaserver / DCE Security Server. Default is yes.
+.TP
+.B KerberosOrLocalPasswd
+If set then if password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as /etc/passwd or SecurID. Default is no.
+.TP
+.B KerberosTgtPassing
+Specifies whether a Kerberos TGT may be forwarded to the server.
+Default is no, TGT forwarding does only work with the AFS kaserver.
+.TP
+.B KerberosTicketCleanup
+Specifies whether to automatically destroy the user's
+ticket cache file on logout. Default is yes.
+.TP
+.B KeyRegenerationInterval
+The server key is automatically regenerated after this many seconds
+(if it has been used). The purpose of regeneration is to prevent
+decrypting captured sessions by later breaking into the machine and
+stealing the keys. The key is never stored anywhere. If the value is
+0, the key is never regenerated. The default is 3600
+(seconds).
+.TP
+.B LoginGraceTime
+The server disconnects after this time if the user has not
+successfully logged in. If the value is 0, there is no time limit.
+The default is 600 (seconds).
+.TP
+.B PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is "yes".
+.TP
+.B PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings. The default
+is "yes".
+.TP
+.B PermitRootLogin
+Specifies whether the root can log in using
+.BR ssh .
+The default is "yes".
+
+Root login with RSA authentication when the "command" option has been
+specified will be allowed regardless of the value of this setting
+(which may be useful for taking remote backups even if root login is
+normally not allowed).
+.TP
+.B Port
+Specifies the port number that
+.B sshd
+listens on. The default is 22.
+.TP
+.B PrintMotd
+Specifies whether
+.B sshd
+should print
+.I /etc/motd
+when a user logs in interactively. (On some systems it is also
+printed by the shell, /etc/profile, or equivalent.) The default is
+"yes".
+.TP
+.B QuietMode
+Specifies whether the system runs in quiet mode. In quiet mode,
+nothing is logged in the system log, except fatal errors. The default
+is "no".
+.TP
+.B RandomSeed
+Specifies the file containing the random seed for the server; this
+file is created automatically and updated regularly. The default is
+.IR /etc/ssh_random_seed ".
+.TP
+.B RhostsAuthentication
+Specifies whether authentication using rhosts or /etc/hosts.equiv
+files is sufficient. Normally, this method should not be permitted
+because it is insecure. RhostsRSAAuthentication should be used
+instead, because it performs RSA-based host authentication in addition
+to normal rhosts or /etc/hosts.equiv authentication.
+The default is "no".
+.TP
+.B RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed. The default is "yes".
+.TP
+.B RSAAuthentication
+Specifies whether pure RSA authentication is allowed. The default is "yes".
+.TP
+.B ServerKeyBits
+Defines the number of bits in the server key. The minimum value is
+512, and the default is 768.
+.TP
+.B StrictModes
+Specifies whether ssh should check file modes and ownership of the
+user's home directory and rhosts files before accepting login. This
+is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable. The default is "yes".
+.TP
+.B SyslogFacility
+Gives the facility code that is used when logging messages from
+.B sshd.
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is DAEMON.
+.TP
+.B X11Forwarding
+Specifies whether X11 forwarding is permitted. The default is "yes".
+Note that disabling X11 forwarding does not improve security in any
+way, as users can always install their own forwarders.
+
+.SH LOGIN PROCESS
+
+When a user successfully logs in,
+.B sshd
+does the following:
+.IP 1.
+If the login is on a tty, and no command has been specified,
+prints last login time and
+.B /etc/motd
+(unless prevented in the configuration file or by
+.IR $HOME/\s+2.\s0hushlogin ;
+see the FILES section).
+.IP 2.
+If the login is on a tty, records login time.
+.IP 3.
+Checks /etc/nologin; if it exists, prints contents and quits
+(unless root).
+.IP 4.
+Changes to run with normal user privileges.
+.IP 5.
+Sets up basic environment.
+.IP 6.
+Reads /etc/environment if it exists.
+.IP 7.
+Reads $HOME/.ssh/environment if it exists.
+.IP 8.
+Changes to user's home directory.
+.IP 9.
+If $HOME/.ssh/rc exists, runs it; else if /etc/sshrc exists, runs
+it; otherwise runs xauth. The "rc" files are given the X11
+authentication protocol and cookie in standard input.
+.IP 10.
+Runs user's shell or command.
+.RT
+
+
+.SH AUTHORIZED_KEYS FILE FORMAT
+.LP
+The
+.I \&$HOME/\s+2.\s0ssh/authorized_keys
+file lists the RSA keys that are
+permitted for RSA authentication. Each line of the file contains one
+key (empty lines and lines starting with a '#' are ignored as
+comments). Each line consists of the following fields, separated by
+spaces: options, bits, exponent, modulus, comment. The options field
+is optional; its presence is determined by whether the line starts
+with a number or not (the option field never starts with a number).
+The bits, exponent, modulus and comment fields give the RSA key; the
+comment field is not used for anything (but may be convenient for the
+user to identify the key).
+.LP
+Note that lines in this file are usually several hundred bytes long
+(because of the size of the RSA key modulus). You don't want to type
+them in; instead, copy the
+.I identity.pub
+file and edit it.
+.LP
+The options (if present) consists of comma-separated option
+specifications. No spaces are permitted, except within double quotes.
+The following option specifications are supported:
+.IP
+.ti -.5i
+\fBfrom="pattern-list" \fR
+.br
+Specifies that in addition to RSA authentication, the canonical name
+of the remote host must be present in the comma-separated list of
+patterns ('*' and '?' serve as wildcards). The list may also contain
+patterns negated by prefixing them with '!'; if the canonical host
+name matches a negated pattern, the key is not accepted. The purpose
+of this option is to optionally increase security: RSA authentication
+by itself does not trust the network or name servers or anything (but
+the key); however, if somebody somehow steals the key, the key
+permits an intruder to log in from anywhere in the world. This
+additional option makes using a stolen key more difficult (name
+servers and/or routers would have to be compromised in addition to
+just the key).
+.IP
+.ti -.5i
+\fBcommand="command"\fR
+.br
+Specifies that the command is executed whenever this key is used for
+authentication. The command supplied by the user (if any) is ignored.
+The command is run on a pty if the connection requests a pty;
+otherwise it is run without a tty. A quote may be included in the
+command by quoting it with a backslash. This option might be useful
+to restrict certain RSA keys to perform just a specific operation. An
+example might be a key that permits remote backups but nothing
+else. Notice that the client may specify TCP/IP and/or X11
+forwardings unless they are explicitly prohibited.
+.IP
+.ti -.5i
+\fBenvironment="NAME=value"\fR
+.br
+Specifies that the string is to be added to the environment when
+logging in using this key. Environment variables set this way
+override other default environment values. Multiple options of this
+type are permitted.
+.TP
+.B no-port-forwarding
+Forbids TCP/IP forwarding when this key is used for authentication.
+Any port forward requests by the client will return an error. This
+might be used e.g. in connection with the
+.B command
+option.
+.TP
+.B no-X11-forwarding
+Forbids X11 forwarding when this key is used for authentication.
+Any X11 forward requests by the client will return an error.
+.TP
+.B no-agent-forwarding
+Forbids authentication agent forwarding when this key is used for
+authentication.
+.TP
+.B no-pty
+Prevents tty allocation (a request to allocate a pty will fail).
+
+.SS Examples
+.LP
+1024 33 12121.\|.\|.\|312314325 ylo@foo.bar
+.LP
+from="*.niksula.hut.fi,!pc.niksula.hut.fi" 1024 35 23.\|.\|.\|2334 ylo@niksula
+.LP
+command="dump /home",no-pty,no-port-forwarding 1024 33 23.\|.\|.\|2323 backup.hut.fi
+
+
+
+.SH SSH_KNOWN_HOSTS FILE FORMAT
+.LP
+The
+.I /etc/ssh_known_hosts
+and
+.I \&$HOME/\s+2.\s0ssh/known_hosts
+files contain host public keys for all known hosts. The global file should
+be prepared by the admistrator (optional), and the per-user file is
+maintained automatically: whenever the user connects an unknown host
+its key is added to the per-user file. The recommended way to create
+.I /etc/ssh_known_hosts
+is to use the
+.B make-ssh-known-hosts
+command.
+.LP
+Each line in these files contains the following fields: hostnames,
+bits, exponent, modulus, comment. The fields are separated by spaces.
+.LP
+Hostnames is a comma-separated list of patterns ('*' and '?' act as
+wildcards); each pattern in turn is matched against the canonical host
+name (when authenticating a client) or against the user-supplied
+name (when authenticating a server). A pattern may also be preceded
+by '!' to indicate negation: if the host name matches a negated
+pattern, it is not accepted (by that line) even if it matched another
+pattern on the line.
+.LP
+Bits, exponent, and modulus are taken directly from the host key; they
+can be obtained e.g. from
+.IR /etc/ssh_host_key.pub ".
+The optional comment field continues to the end of the line, and is not used.
+.LP
+Lines starting with '#' and empty lines are ignored as comments.
+.LP
+When performing host authentication, authentication is accepted if any
+matching line has the proper key. It is thus permissible (but not
+recommended) to have several lines or different host keys for the same
+names. This will inevitably happen when short forms of host names
+from different domains are put in the file. It is possible
+that the files contain conflicting information; authentication is
+accepted if valid information can be found from either file.
+.LP
+Note that the lines in these files are typically hundreds of characters
+long, and you definitely don't want to type in the host keys by hand.
+Rather, generate them by a script (see
+.BR make-ssh-known-hosts (1))
+or by taking
+.I /etc/ssh_host_key.pub
+and adding the host names at the front.
+
+.SS Examples
+
+closenet,closenet.hut.fi,.\|.\|.\|,130.233.208.41 1024 37 159.\|.\|.93 closenet.hut.fi
+
+.SH FILES
+.TP
+.I /etc/sshd_config
+Contains configuration data for
+.BR sshd .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.TP
+.I /etc/ssh_host_key
+Contains the private part of the host key. This file is normally
+created automatically by "make install", but can also be created
+manually using
+.BR ssh-keygen (1).
+This file should only be owned by root, readable only by root, and not
+accessible to others.
+.TP
+.I /etc/ssh_host_key.pub
+Contains the public part of the host key. This file is normally
+created automatically by "make install", but can also be created
+manually. This file should be world-readable but writable only by
+root. Its contents should match the private part. This file is not
+really used for anything; it is only provided for the convenience of
+the user so its contents can be copied to known hosts files.
+.TP
+.I /etc/ssh_random_seed
+This file contains a seed for the random number generator. This file
+should only be accessible by root.
+.TP
+.I /var/run/sshd.pid
+Contains the process id of the
+.B sshd
+listening for connections (if there are several daemons running
+concurrently for different ports, this contains the pid of the one
+started last). The contents of this file are not sensitive; it can be
+world-readable.
+.TP
+.I \&$HOME/\s+2.\s0ssh/authorized_keys
+Lists the RSA keys that can be used to log into the user's account.
+This file must be readable by root (which may on some machines imply
+it being world-readable if the user's home directory resides on an NFS
+volume). It is recommended that it not be accessible by others. The
+format of this file is described above.
+.TP
+.I "/etc/ssh_known_hosts\fR and \fI$HOME/\s+2.\s0ssh/known_hosts\fR
+These files are consulted when using rhosts with RSA host
+authentication to check the public key of the host. The key must be
+listed in one of these files to be accepted. (The client uses the
+same files to verify that the remote host is the one we intended to
+connect.) These files should be writable only by root/the owner.
+.I /etc/ssh_known_hosts
+should be world-readable, and \fI$HOME/\s+2.\s0ssh/known_hosts\fR can
+but need not be world-readable.
+.TP
+.I /etc/nologin
+If this file exists,
+.B sshd
+refuses to let anyone except root log in. The contents of the file
+are displayed to anyone trying to log in, and non-root connections are
+refused. The file should be world-readable.
+.TP
+.I \&$HOME/\s+2.\s0rhosts
+This file contains host-username pairs, separated by a space, one per
+line. The given user on the corresponding host is permitted to log in
+without password. The same file is used by rlogind and rshd.
+.B Ssh
+differs from rlogind
+and rshd in that it requires RSA host authentication in addition to
+validating the host name retrieved from domain name servers (unless
+compiled with the \-\-with\-rhosts configuration option). The file must
+be writable only by the user; it is recommended that it not be
+accessible by others.
+
+If is also possible to use netgroups in the file. Either host or user
+name may be of the form +@groupname to specify all hosts or all users
+in the group.
+.TP
+.I \&$HOME/\s+2.\s0shosts
+For
+.B ssh,
+this file is exactly the same as for \s+2.\s0rhosts. However, this file is
+not used by rlogin and rshd, so using this permits access using
+.B ssh
+only.
+.TP
+.I /etc/hosts.equiv
+This file is used during \s+2.\s0rhosts authentication. In the
+simplest form, this file contains host names, one per line. Users on
+those hosts are permitted to log in without a password, provided they
+have the same user name on both machines. The host name may also be
+followed by a user name; such users are permitted to log in as
+.B any
+user on this machine (except root). Additionally, the syntax +@group
+can be used to specify netgroups. Negated entries start with '-'.
+
+If the client host/user is successfully matched in this file, login is
+automatically permitted provided the client and server user names are the
+same. Additionally, successful RSA host authentication is normally
+required. This file must be writable only by root; it is recommended
+that it be world-readable.
+
+\fBWarning: It is almost never a good idea to use user names in
+hosts.equiv.\fR
+Beware that it really means that the named user(s) can log in as
+\fBanybody\fR,
+which includes bin, daemon, adm, and other accounts that own critical
+binaries and directories. Using a user name practically grants the
+user root access. The only valid use for user names that I can think
+of is in negative entries.
+\fBNote that this warning also applies to rsh/rlogin.\fR
+.TP
+.I /etc/shosts.equiv
+This is processed exactly as
+.I /etc/hosts.equiv.
+However, this file may be useful in environments that want to run both
+rsh/rlogin and
+.B ssh.
+.TP
+.I /etc/environment
+This file is read into the environment at login (if it exists). It
+can only contain empty lines, comment lines (that start with '#'), and
+assignment lines of the form name=value. This file is processed in
+all environments (normal rsh/rlogin only process it on AIX and
+potentially some other systems). The file should be writable only by
+root, and should be world-readable.
+.TP
+.I \&$HOME/\s+2.\s0ssh/environment
+This file is read into the environment after /etc/environment. It has
+the same format. The file should be writable only by the user; it
+need not be readable by anyone else.
+.TP
+.I \&$HOME/\s+2.\s0ssh/rc
+If this file exists, it is run with /bin/sh after reading the
+environment files but before starting the user's shell or command. If
+X11 spoofing is in use, this will receive the "proto cookie" pair in
+standard input (and DISPLAY in environment). This must call xauth in
+that case.
+
+The primary purpose of this file is to run any initialization routines
+which may be needed before the user's home directory becomes
+accessible; AFS is a particular example of such an environment.
+
+This file will probably contain some initialization code followed by
+something similar to: "if read proto cookie; then echo add $DISPLAY
+$proto $cookie | xauth -q -; fi".
+
+If this file does not exist, /etc/sshrc is run, and if that
+does not exist either, xauth is used to store the cookie.
+
+This file should be writable only by the user, and need not be
+readable by anyone else.
+.TP
+.I /etc/sshrc
+Like $HOME/\s+2.\s0ssh/rc. This can be used to specify
+machine-specific login-time initializations globally. This file
+should be writable only by root, and should be world-readable.
+
+
+.SH INSTALLATION
+.LP
+.B Sshd
+is normally run as root. If it is not run as root, it can
+only log in as the user it is running as, and password authentication
+may not work if the system uses shadow passwords. An alternative
+host key file must also be used.
+.LP
+.B Sshd
+is normally started from
+.I /etc/rc.local
+or equivalent at system boot.
+.LP
+Considerable work has been put to making
+.B sshd
+secure. However, if you find a security problem, please report it
+immediately to <ssh-bugs@cs.hut.fi>.
+
+.SH AUTHOR
+.LP
+Tatu Ylonen <ylo@cs.hut.fi>
+.LP
+Information about new releases, mailing lists, and other related
+issues can be found from the ssh WWW home page at
+http://www.cs.hut.fi/ssh.
+
+.SH SEE ALSO
+.LP
+.BR ssh (1),
+.BR make-ssh-known-hosts (1),
+.BR ssh-keygen (1),
+.BR ssh-agent (1),
+.BR ssh-add (1),
+.BR scp (1),
+.BR rlogin (1),
+.BR rsh (1)
diff --git a/usr.bin/ssh/sshd.8.in b/usr.bin/ssh/sshd.8.in
new file mode 100644
index 00000000000..419c132144c
--- /dev/null
+++ b/usr.bin/ssh/sshd.8.in
@@ -0,0 +1,734 @@
+.\" -*- nroff -*-
+.\"
+.\" sshd.8.in
+.\"
+.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
+.\"
+.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+.\" All rights reserved
+.\"
+.\" Created: Sat Apr 22 21:55:14 1995 ylo
+.\"
+.\" $Id: sshd.8.in,v 1.1 1999/09/26 20:53:38 deraadt Exp $
+.\"
+.TH SSHD 8 "November 8, 1995" "SSH" "SSH"
+
+.SH NAME
+sshd \- secure shell daemon
+
+.SH SYNOPSIS
+.na
+.B sshd
+[\c
+.BI \-b \ bits\fR\c
+]
+[\c
+.B \-d \c
+]
+[\c
+.BI \-f \ config_file\fR\c
+]
+[\c
+.BI \-g \ login_grace_time\fR\c
+]
+[\c
+.BI \-h \ host_key_file\fR\c
+]
+[\c
+.B \-i \c
+]
+[\c
+.BI \-k \ key_gen_time\fR\c
+]
+[\c
+.BI \-p \ port\fR\c
+]
+[\c
+.B \-q \c
+]
+.ad
+
+
+.SH DESCRIPTION
+.LP
+.B Sshd
+(Secure Shell Daemon) is the daemon program for
+.BR ssh ".
+Together these programs replace rlogin and rsh programs, and
+provide secure encrypted communications between two untrusted hosts
+over an insecure network. The programs are intended to be as easy to
+install and use as possible.
+.LP
+.B Sshd
+is the daemon that listens for connections from clients. It is
+normally started at boot from
+.I /etc/rc.local
+or equivalent. It forks a new
+daemon for each incoming connection. The forked daemons handle
+key exchange, encryption, authentication, command execution,
+and data exchange.
+.LP
+Sshd works as follows. Each host has a host-specific RSA key
+(normally 1024 bits) used to identify the host. Additionally, when
+the daemon starts, it generates a server RSA key (normally 768 bits).
+This key is normally regenerated every hour if it has been used, and
+is never stored on disk.
+.LP
+Whenever a client connects the daemon, the daemon sends its host
+and server public keys to the client. The client compares the
+host key against its own database to verify that it has not changed.
+The client then generates a 256 bit random number. It encrypts this
+random number using both the host key and the server key, and sends
+the encrypted number to the server. Both sides then start to use this
+random number as a session key which is used to encrypt all further
+communications in the session. The rest of the session is encrypted
+using a conventional cipher. Currently,
+.BR \s-1Blowfish\s0 ",
+.BR \s-1IDEA\s0 ",
+.BR \s-1DES\s0 ",
+.BR \s-1\&3DES\s0 ",
+.B \s-13DES\s0
+is used by default. The client selects the encryption algorithm to use
+from those offered by the server.
+.LP
+Next, the server and the client enter an authentication dialog. The
+client tries to authenticate itself using \|\s+2.\s0rhosts
+authentication, \|\s+2.\s0rhosts authentication combined with RSA host
+authentication, RSA challenge-response authentication, or password
+based authentication.
+.LP
+Rhosts authentication is normally disabled
+because it is fundamentally insecure, but can be enabled in the server
+configuration file if desired. System security is not improved unless
+.BR rshd "(8),
+.BR rlogind "(8),
+.BR rexecd "(8), and
+.B rexd "(8)
+are disabled (thus completely disabling
+.BR rlogin (1)
+and
+.BR rsh (1)
+into that machine).
+.LP
+If the client successfully authenticates itself, a dialog for
+preparing the session is entered. At this time the client may request
+things like allocating a pseudo-tty, forwarding X11 connections,
+forwarding TCP/IP connections, or forwarding the authentication agent
+connection over the secure channel.
+.LP
+Finally, the client either requests a shell or execution of a command.
+The sides then enter session mode. In this mode, either side may send
+data at any time, and such data is forwarded to/from the shell or
+command on the server side, and the user terminal in the client side.
+.LP
+When the user program terminates and all forwarded X11 and other
+connections have been closed, the server sends command exit status to
+the client, and both sides exit.
+.LP
+.B Sshd
+can be configured using command-line options or a configuration
+file. Command-line options override values specified in the
+configuration file.
+
+
+.SH OPTIONS
+.TP
+.BI \-b \ bits
+Specifies the number of bits in the server key (default 768).
+.TP
+.B \-d
+Debug mode. The server sends verbose debug output to the system
+log, and does not put itself in the background. The server also will
+not fork and will only process one connection. This option is only
+intended for debugging for the server.
+.TP
+.BI \-f \ configuration_file
+Specifies the name of the configuration file. The default is
+.IR @ETCDIR@/sshd_config ".
+.TP
+.BI \-g \ login_grace_time
+Gives the grace time for clients to authenticate themselves (default
+300 seconds). If the client fails to authenticate the user within
+this many seconds, the server disconnects and exits. A value of zero
+indicates no limit.
+.TP
+.BI \-h \ host_key_file
+Specifies the file from which the host key is read (default
+.IR @ETCDIR@/ssh_host_key).
+This option must be given if sshd is not run as root (as the normal
+host file is normally not readable by anyone but root).
+.TP
+.B \-i
+Specifies that sshd is being run from inetd. Sshd is normally not run
+from inetd because it needs to generate the server key before it can
+respond to the client, and this may take tens of seconds. Clients
+would have to wait too long if the key was regenerated every time.
+However, with small key sizes (e.g. 512) using sshd from inetd may
+be feasible.
+.TP
+.BI \-k \ key_gen_time
+Specifies how often the server key is regenerated (default 3600
+seconds, or one hour). The motivation for regenerating the key fairly
+often is that the key is not stored anywhere, and after about an hour,
+it becomes impossible to recover the key for decrypting intercepted
+communications even if the machine is cracked into or physically
+seized. A value of zero indicates that the key will never be regenerated.
+.TP
+.BI \-p \ port
+Specifies the port on which the server listens for connections
+(default 22).
+.TP
+.B \-q
+Quiet mode. Nothing is sent to the system log. Normally the beginning,
+authentication, and termination of each connection is logged.
+
+.SH CONFIGURATION FILE
+
+.B Sshd
+reads configuration data from
+.I @ETCDIR@/sshd_config
+(or the file specified with -f on the command line). The file
+contains keyword-value pairs, one per line. Lines starting with '#'
+and empty lines are interpreted as comments.
+
+The following keywords are possible.
+.TP
+.B AFSTokenPassing
+Specifies whether to accept AFS tokens passed from the client. Default
+is "yes".
+.TP
+.B AllowHosts
+This keyword can be followed by any number of host name patterns,
+separated by spaces. If specified, login is allowed only from hosts
+whose name matches one of the patterns. '*' and '?' can be used as
+wildcards in the patterns. Normal name servers are used to map the
+client's host into a canonical host name. If the name cannot be
+mapped, its IP-address is used as the host name. By default all hosts
+are allowed to connect.
+
+Note that
+.B sshd
+can also be configured to use tcp_wrappers using the --with-libwrap
+compile-time configuration option.
+.TP
+.B DenyHosts
+This keyword can be followed by any number of host name patterns,
+separated by spaces. If specified, login is disallowed from the hosts
+whose name matches any of the patterns.
+.TP
+.B FascistLogging
+Specifies whether to use verbose logging. Verbose logging violates
+the privacy of users and is not recommended. The argument must be
+"yes" or "no" (without the quotes). The default is "no".
+.TP
+.B HostKey
+Specifies the file containing the private host key (default
+.IR @ETCDIR@/ssh_host_key ").
+.TP
+.B IgnoreRhosts
+Specifies that rhosts and shosts files will not be used in
+authentication.
+.I /etc/hosts.equiv
+and
+.I @ETCDIR@/shosts.equiv
+are still used. The default is "no".
+.TP
+.B KeepAlive
+Specifies whether the system should send keepalive messages to the
+other side. If they are sent, death of the connection or crash of one
+of the machines will be properly noticed. However, this means that
+connections will die if the route is down temporarily, and some people
+find it annoying. On the other hand, if keepalives are not send,
+sessions may hang indefinitely on the server, leaving "ghost" users
+and consuming server resources.
+
+The default is "yes" (to send keepalives), and the server will notice
+if the network goes down or the client host reboots. This avoids
+infinitely hanging sessions.
+
+To disable keepalives, the value should be set to "no" in both the
+server and the client configuration files.
+.TP
+.B KerberosAuthentication
+Specifies whether Kerberos authentication is allowed. This can
+be in the form of a Kerberos ticket, or if PasswordAuthentication
+is yes, the password provided by the user will be validated through
+the Kerberos KDC / AFS kaserver / DCE Security Server. Default is yes.
+.TP
+.B KerberosOrLocalPasswd
+If set then if password authentication through Kerberos fails then
+the password will be validated via any additional local mechanism
+such as /etc/passwd or SecurID. Default is no.
+.TP
+.B KerberosTgtPassing
+Specifies whether a Kerberos TGT may be forwarded to the server.
+Default is no, TGT forwarding does only work with the AFS kaserver.
+.TP
+.B KerberosTicketCleanup
+Specifies whether to automatically destroy the user's
+ticket cache file on logout. Default is yes.
+.TP
+.B KeyRegenerationInterval
+The server key is automatically regenerated after this many seconds
+(if it has been used). The purpose of regeneration is to prevent
+decrypting captured sessions by later breaking into the machine and
+stealing the keys. The key is never stored anywhere. If the value is
+0, the key is never regenerated. The default is 3600
+(seconds).
+.TP
+.B LoginGraceTime
+The server disconnects after this time if the user has not
+successfully logged in. If the value is 0, there is no time limit.
+The default is 600 (seconds).
+.TP
+.B PasswordAuthentication
+Specifies whether password authentication is allowed.
+The default is "yes".
+.TP
+.B PermitEmptyPasswords
+When password authentication is allowed, it specifies whether the
+server allows login to accounts with empty password strings. The default
+is "yes".
+.TP
+.B PermitRootLogin
+Specifies whether the root can log in using
+.BR ssh .
+The default is "yes".
+
+Root login with RSA authentication when the "command" option has been
+specified will be allowed regardless of the value of this setting
+(which may be useful for taking remote backups even if root login is
+normally not allowed).
+.TP
+.B Port
+Specifies the port number that
+.B sshd
+listens on. The default is 22.
+.TP
+.B PrintMotd
+Specifies whether
+.B sshd
+should print
+.I /etc/motd
+when a user logs in interactively. (On some systems it is also
+printed by the shell, /etc/profile, or equivalent.) The default is
+"yes".
+.TP
+.B QuietMode
+Specifies whether the system runs in quiet mode. In quiet mode,
+nothing is logged in the system log, except fatal errors. The default
+is "no".
+.TP
+.B RandomSeed
+Specifies the file containing the random seed for the server; this
+file is created automatically and updated regularly. The default is
+.IR @ETCDIR@/ssh_random_seed ".
+.TP
+.B RhostsAuthentication
+Specifies whether authentication using rhosts or /etc/hosts.equiv
+files is sufficient. Normally, this method should not be permitted
+because it is insecure. RhostsRSAAuthentication should be used
+instead, because it performs RSA-based host authentication in addition
+to normal rhosts or /etc/hosts.equiv authentication.
+The default is "no".
+.TP
+.B RhostsRSAAuthentication
+Specifies whether rhosts or /etc/hosts.equiv authentication together
+with successful RSA host authentication is allowed. The default is "yes".
+.TP
+.B RSAAuthentication
+Specifies whether pure RSA authentication is allowed. The default is "yes".
+.TP
+.B ServerKeyBits
+Defines the number of bits in the server key. The minimum value is
+512, and the default is 768.
+.TP
+.B StrictModes
+Specifies whether ssh should check file modes and ownership of the
+user's home directory and rhosts files before accepting login. This
+is normally desirable because novices sometimes accidentally leave their
+directory or files world-writable. The default is "yes".
+.TP
+.B SyslogFacility
+Gives the facility code that is used when logging messages from
+.B sshd.
+The possible values are: DAEMON, USER, AUTH, LOCAL0, LOCAL1, LOCAL2,
+LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is DAEMON.
+.TP
+.B X11Forwarding
+Specifies whether X11 forwarding is permitted. The default is "yes".
+Note that disabling X11 forwarding does not improve security in any
+way, as users can always install their own forwarders.
+
+.SH LOGIN PROCESS
+
+When a user successfully logs in,
+.B sshd
+does the following:
+.IP 1.
+If the login is on a tty, and no command has been specified,
+prints last login time and
+.B /etc/motd
+(unless prevented in the configuration file or by
+.IR $HOME/\s+2.\s0hushlogin ;
+see the FILES section).
+.IP 2.
+If the login is on a tty, records login time.
+.IP 3.
+Checks /etc/nologin; if it exists, prints contents and quits
+(unless root).
+.IP 4.
+Changes to run with normal user privileges.
+.IP 5.
+Sets up basic environment.
+.IP 6.
+Reads /etc/environment if it exists.
+.IP 7.
+Reads $HOME/.ssh/environment if it exists.
+.IP 8.
+Changes to user's home directory.
+.IP 9.
+If $HOME/.ssh/rc exists, runs it; else if @ETCDIR@/sshrc exists, runs
+it; otherwise runs xauth. The "rc" files are given the X11
+authentication protocol and cookie in standard input.
+.IP 10.
+Runs user's shell or command.
+.RT
+
+
+.SH AUTHORIZED_KEYS FILE FORMAT
+.LP
+The
+.I \&$HOME/\s+2.\s0ssh/authorized_keys
+file lists the RSA keys that are
+permitted for RSA authentication. Each line of the file contains one
+key (empty lines and lines starting with a '#' are ignored as
+comments). Each line consists of the following fields, separated by
+spaces: options, bits, exponent, modulus, comment. The options field
+is optional; its presence is determined by whether the line starts
+with a number or not (the option field never starts with a number).
+The bits, exponent, modulus and comment fields give the RSA key; the
+comment field is not used for anything (but may be convenient for the
+user to identify the key).
+.LP
+Note that lines in this file are usually several hundred bytes long
+(because of the size of the RSA key modulus). You don't want to type
+them in; instead, copy the
+.I identity.pub
+file and edit it.
+.LP
+The options (if present) consists of comma-separated option
+specifications. No spaces are permitted, except within double quotes.
+The following option specifications are supported:
+.IP
+.ti -.5i
+\fBfrom="pattern-list" \fR
+.br
+Specifies that in addition to RSA authentication, the canonical name
+of the remote host must be present in the comma-separated list of
+patterns ('*' and '?' serve as wildcards). The list may also contain
+patterns negated by prefixing them with '!'; if the canonical host
+name matches a negated pattern, the key is not accepted. The purpose
+of this option is to optionally increase security: RSA authentication
+by itself does not trust the network or name servers or anything (but
+the key); however, if somebody somehow steals the key, the key
+permits an intruder to log in from anywhere in the world. This
+additional option makes using a stolen key more difficult (name
+servers and/or routers would have to be compromised in addition to
+just the key).
+.IP
+.ti -.5i
+\fBcommand="command"\fR
+.br
+Specifies that the command is executed whenever this key is used for
+authentication. The command supplied by the user (if any) is ignored.
+The command is run on a pty if the connection requests a pty;
+otherwise it is run without a tty. A quote may be included in the
+command by quoting it with a backslash. This option might be useful
+to restrict certain RSA keys to perform just a specific operation. An
+example might be a key that permits remote backups but nothing
+else. Notice that the client may specify TCP/IP and/or X11
+forwardings unless they are explicitly prohibited.
+.IP
+.ti -.5i
+\fBenvironment="NAME=value"\fR
+.br
+Specifies that the string is to be added to the environment when
+logging in using this key. Environment variables set this way
+override other default environment values. Multiple options of this
+type are permitted.
+.TP
+.B no-port-forwarding
+Forbids TCP/IP forwarding when this key is used for authentication.
+Any port forward requests by the client will return an error. This
+might be used e.g. in connection with the
+.B command
+option.
+.TP
+.B no-X11-forwarding
+Forbids X11 forwarding when this key is used for authentication.
+Any X11 forward requests by the client will return an error.
+.TP
+.B no-agent-forwarding
+Forbids authentication agent forwarding when this key is used for
+authentication.
+.TP
+.B no-pty
+Prevents tty allocation (a request to allocate a pty will fail).
+
+.SS Examples
+.LP
+1024 33 12121.\|.\|.\|312314325 ylo@foo.bar
+.LP
+from="*.niksula.hut.fi,!pc.niksula.hut.fi" 1024 35 23.\|.\|.\|2334 ylo@niksula
+.LP
+command="dump /home",no-pty,no-port-forwarding 1024 33 23.\|.\|.\|2323 backup.hut.fi
+
+
+
+.SH SSH_KNOWN_HOSTS FILE FORMAT
+.LP
+The
+.I @ETCDIR@/ssh_known_hosts
+and
+.I \&$HOME/\s+2.\s0ssh/known_hosts
+files contain host public keys for all known hosts. The global file should
+be prepared by the admistrator (optional), and the per-user file is
+maintained automatically: whenever the user connects an unknown host
+its key is added to the per-user file. The recommended way to create
+.I @ETCDIR@/ssh_known_hosts
+is to use the
+.B make-ssh-known-hosts
+command.
+.LP
+Each line in these files contains the following fields: hostnames,
+bits, exponent, modulus, comment. The fields are separated by spaces.
+.LP
+Hostnames is a comma-separated list of patterns ('*' and '?' act as
+wildcards); each pattern in turn is matched against the canonical host
+name (when authenticating a client) or against the user-supplied
+name (when authenticating a server). A pattern may also be preceded
+by '!' to indicate negation: if the host name matches a negated
+pattern, it is not accepted (by that line) even if it matched another
+pattern on the line.
+.LP
+Bits, exponent, and modulus are taken directly from the host key; they
+can be obtained e.g. from
+.IR @ETCDIR@/ssh_host_key.pub ".
+The optional comment field continues to the end of the line, and is not used.
+.LP
+Lines starting with '#' and empty lines are ignored as comments.
+.LP
+When performing host authentication, authentication is accepted if any
+matching line has the proper key. It is thus permissible (but not
+recommended) to have several lines or different host keys for the same
+names. This will inevitably happen when short forms of host names
+from different domains are put in the file. It is possible
+that the files contain conflicting information; authentication is
+accepted if valid information can be found from either file.
+.LP
+Note that the lines in these files are typically hundreds of characters
+long, and you definitely don't want to type in the host keys by hand.
+Rather, generate them by a script (see
+.BR make-ssh-known-hosts (1))
+or by taking
+.I @ETCDIR@/ssh_host_key.pub
+and adding the host names at the front.
+
+.SS Examples
+
+closenet,closenet.hut.fi,.\|.\|.\|,130.233.208.41 1024 37 159.\|.\|.93 closenet.hut.fi
+
+.SH FILES
+.TP
+.I @ETCDIR@/sshd_config
+Contains configuration data for
+.BR sshd .
+This file should be writable by root only, but it is recommended
+(though not necessary) that it be world-readable.
+.TP
+.I @ETCDIR@/ssh_host_key
+Contains the private part of the host key. This file is normally
+created automatically by "make install", but can also be created
+manually using
+.BR ssh-keygen (1).
+This file should only be owned by root, readable only by root, and not
+accessible to others.
+.TP
+.I @ETCDIR@/ssh_host_key.pub
+Contains the public part of the host key. This file is normally
+created automatically by "make install", but can also be created
+manually. This file should be world-readable but writable only by
+root. Its contents should match the private part. This file is not
+really used for anything; it is only provided for the convenience of
+the user so its contents can be copied to known hosts files.
+.TP
+.I @ETCDIR@/ssh_random_seed
+This file contains a seed for the random number generator. This file
+should only be accessible by root.
+.TP
+.I @PIDDIR@/sshd.pid
+Contains the process id of the
+.B sshd
+listening for connections (if there are several daemons running
+concurrently for different ports, this contains the pid of the one
+started last). The contents of this file are not sensitive; it can be
+world-readable.
+.TP
+.I \&$HOME/\s+2.\s0ssh/authorized_keys
+Lists the RSA keys that can be used to log into the user's account.
+This file must be readable by root (which may on some machines imply
+it being world-readable if the user's home directory resides on an NFS
+volume). It is recommended that it not be accessible by others. The
+format of this file is described above.
+.TP
+.I "@ETCDIR@/ssh_known_hosts\fR and \fI$HOME/\s+2.\s0ssh/known_hosts\fR
+These files are consulted when using rhosts with RSA host
+authentication to check the public key of the host. The key must be
+listed in one of these files to be accepted. (The client uses the
+same files to verify that the remote host is the one we intended to
+connect.) These files should be writable only by root/the owner.
+.I @ETCDIR@/ssh_known_hosts
+should be world-readable, and \fI$HOME/\s+2.\s0ssh/known_hosts\fR can
+but need not be world-readable.
+.TP
+.I /etc/nologin
+If this file exists,
+.B sshd
+refuses to let anyone except root log in. The contents of the file
+are displayed to anyone trying to log in, and non-root connections are
+refused. The file should be world-readable.
+.TP
+.I \&$HOME/\s+2.\s0rhosts
+This file contains host-username pairs, separated by a space, one per
+line. The given user on the corresponding host is permitted to log in
+without password. The same file is used by rlogind and rshd.
+.B Ssh
+differs from rlogind
+and rshd in that it requires RSA host authentication in addition to
+validating the host name retrieved from domain name servers (unless
+compiled with the \-\-with\-rhosts configuration option). The file must
+be writable only by the user; it is recommended that it not be
+accessible by others.
+
+If is also possible to use netgroups in the file. Either host or user
+name may be of the form +@groupname to specify all hosts or all users
+in the group.
+.TP
+.I \&$HOME/\s+2.\s0shosts
+For
+.B ssh,
+this file is exactly the same as for \s+2.\s0rhosts. However, this file is
+not used by rlogin and rshd, so using this permits access using
+.B ssh
+only.
+.TP
+.I /etc/hosts.equiv
+This file is used during \s+2.\s0rhosts authentication. In the
+simplest form, this file contains host names, one per line. Users on
+those hosts are permitted to log in without a password, provided they
+have the same user name on both machines. The host name may also be
+followed by a user name; such users are permitted to log in as
+.B any
+user on this machine (except root). Additionally, the syntax +@group
+can be used to specify netgroups. Negated entries start with '-'.
+
+If the client host/user is successfully matched in this file, login is
+automatically permitted provided the client and server user names are the
+same. Additionally, successful RSA host authentication is normally
+required. This file must be writable only by root; it is recommended
+that it be world-readable.
+
+\fBWarning: It is almost never a good idea to use user names in
+hosts.equiv.\fR
+Beware that it really means that the named user(s) can log in as
+\fBanybody\fR,
+which includes bin, daemon, adm, and other accounts that own critical
+binaries and directories. Using a user name practically grants the
+user root access. The only valid use for user names that I can think
+of is in negative entries.
+\fBNote that this warning also applies to rsh/rlogin.\fR
+.TP
+.I @ETCDIR@/shosts.equiv
+This is processed exactly as
+.I /etc/hosts.equiv.
+However, this file may be useful in environments that want to run both
+rsh/rlogin and
+.B ssh.
+.TP
+.I /etc/environment
+This file is read into the environment at login (if it exists). It
+can only contain empty lines, comment lines (that start with '#'), and
+assignment lines of the form name=value. This file is processed in
+all environments (normal rsh/rlogin only process it on AIX and
+potentially some other systems). The file should be writable only by
+root, and should be world-readable.
+.TP
+.I \&$HOME/\s+2.\s0ssh/environment
+This file is read into the environment after /etc/environment. It has
+the same format. The file should be writable only by the user; it
+need not be readable by anyone else.
+.TP
+.I \&$HOME/\s+2.\s0ssh/rc
+If this file exists, it is run with /bin/sh after reading the
+environment files but before starting the user's shell or command. If
+X11 spoofing is in use, this will receive the "proto cookie" pair in
+standard input (and DISPLAY in environment). This must call xauth in
+that case.
+
+The primary purpose of this file is to run any initialization routines
+which may be needed before the user's home directory becomes
+accessible; AFS is a particular example of such an environment.
+
+This file will probably contain some initialization code followed by
+something similar to: "if read proto cookie; then echo add $DISPLAY
+$proto $cookie | xauth -q -; fi".
+
+If this file does not exist, @ETCDIR@/sshrc is run, and if that
+does not exist either, xauth is used to store the cookie.
+
+This file should be writable only by the user, and need not be
+readable by anyone else.
+.TP
+.I @ETCDIR@/sshrc
+Like $HOME/\s+2.\s0ssh/rc. This can be used to specify
+machine-specific login-time initializations globally. This file
+should be writable only by root, and should be world-readable.
+
+
+.SH INSTALLATION
+.LP
+.B Sshd
+is normally run as root. If it is not run as root, it can
+only log in as the user it is running as, and password authentication
+may not work if the system uses shadow passwords. An alternative
+host key file must also be used.
+.LP
+.B Sshd
+is normally started from
+.I /etc/rc.local
+or equivalent at system boot.
+.LP
+Considerable work has been put to making
+.B sshd
+secure. However, if you find a security problem, please report it
+immediately to <ssh-bugs@cs.hut.fi>.
+
+.SH AUTHOR
+.LP
+Tatu Ylonen <ylo@cs.hut.fi>
+.LP
+Information about new releases, mailing lists, and other related
+issues can be found from the ssh WWW home page at
+http://www.cs.hut.fi/ssh.
+
+.SH SEE ALSO
+.LP
+.BR ssh (1),
+.BR make-ssh-known-hosts (1),
+.BR ssh-keygen (1),
+.BR ssh-agent (1),
+.BR ssh-add (1),
+.BR scp (1),
+.BR rlogin (1),
+.BR rsh (1)
diff --git a/usr.bin/ssh/sshd.c b/usr.bin/ssh/sshd.c
new file mode 100644
index 00000000000..bdf86bb0e05
--- /dev/null
+++ b/usr.bin/ssh/sshd.c
@@ -0,0 +1,2373 @@
+/*
+
+sshd.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Fri Mar 17 17:09:28 1995 ylo
+
+This program is the ssh daemon. It listens for connections from clients, and
+performs authentication, executes use commands or shell, and forwards
+information to/from the application to the user client over an encrypted
+connection. This can also handle forwarding of X11, TCP/IP, and authentication
+agent connections.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: sshd.c,v 1.1 1999/09/26 20:53:38 deraadt Exp $");
+
+#include <gmp.h>
+#include "xmalloc.h"
+#include "rsa.h"
+#include "ssh.h"
+#include "pty.h"
+#include "packet.h"
+#include "buffer.h"
+#include "cipher.h"
+#include "mpaux.h"
+#include "servconf.h"
+#include "uidswap.h"
+#ifdef HAVE_USERSEC_H
+#include <usersec.h>
+#endif /* HAVE_USERSEC_H */
+#ifdef HAVE_ULIMIT_H
+#include <ulimit.h>
+#endif /* HAVE_ULIMIT_H */
+
+#ifdef LIBWRAP
+#include <tcpd.h>
+#include <syslog.h>
+#ifdef NEED_SYS_SYSLOG_H
+#include <sys/syslog.h>
+#endif /* NEED_SYS_SYSLOG_H */
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;
+#endif /* LIBWRAP */
+
+#ifdef _PATH_BSHELL
+#define DEFAULT_SHELL _PATH_BSHELL
+#else
+#define DEFAULT_SHELL "/bin/sh"
+#endif
+
+#ifndef DEFAULT_PATH
+#ifdef _PATH_USERPATH
+#define DEFAULT_PATH _PATH_USERPATH
+#else
+#define DEFAULT_PATH "/bin:/usr/bin:/usr/ucb:/usr/bin/X11:/usr/local/bin"
+#endif
+#endif /* DEFAULT_PATH */
+
+#ifndef O_NOCTTY
+#define O_NOCTTY 0
+#endif
+
+#ifdef KRB4
+#include <sys/param.h>
+#include <krb.h>
+char *ticket = NULL;
+#ifdef AFS
+#include <kafs.h>
+#endif /* AFS */
+#endif /* KRB4 */
+
+/* Local Xauthority file. */
+char *xauthfile = NULL;
+
+/* Server configuration options. */
+ServerOptions options;
+
+/* Name of the server configuration file. */
+char *config_file_name = SERVER_CONFIG_FILE;
+
+/* Debug mode flag. This can be set on the command line. If debug
+ mode is enabled, extra debugging output will be sent to the system
+ log, the daemon will not go to background, and will exit after processing
+ the first connection. */
+int debug_flag = 0;
+
+/* Flag indicating that the daemon is being started from inetd. */
+int inetd_flag = 0;
+
+/* argv[0] without path. */
+char *av0;
+
+/* Saved arguments to main(). */
+char **saved_argv;
+
+/* This is set to the socket that the server is listening; this is used in
+ the SIGHUP signal handler. */
+int listen_sock;
+
+/* Flags set in auth-rsa from authorized_keys flags. These are set in
+ auth-rsa.c. */
+int no_port_forwarding_flag = 0;
+int no_agent_forwarding_flag = 0;
+int no_x11_forwarding_flag = 0;
+int no_pty_flag = 0;
+char *forced_command = NULL; /* RSA authentication "command=" option. */
+struct envstring *custom_environment = NULL;
+ /* RSA authentication "environment=" options. */
+
+/* Session id for the current session. */
+unsigned char session_id[16];
+
+/* Any really sensitive data in the application is contained in this structure.
+ The idea is that this structure could be locked into memory so that the
+ pages do not get written into swap. However, there are some problems.
+ The private key contains MP_INTs, and we do not (in principle) have
+ access to the internals of them, and locking just the structure is not
+ very useful. Currently, memory locking is not implemented. */
+struct
+{
+ /* Random number generator. */
+ RandomState random_state;
+
+ /* Private part of server key. */
+ RSAPrivateKey private_key;
+
+ /* Private part of host key. */
+ RSAPrivateKey host_key;
+} sensitive_data;
+
+/* Flag indicating whether the current session key has been used. This flag
+ is set whenever the key is used, and cleared when the key is regenerated. */
+int key_used = 0;
+
+/* This is set to true when SIGHUP is received. */
+int received_sighup = 0;
+
+/* Public side of the server key. This value is regenerated regularly with
+ the private key. */
+RSAPublicKey public_key;
+
+/* Prototypes for various functions defined later in this file. */
+void do_connection(int privileged_port);
+void do_authentication(char *user, int privileged_port);
+void do_authenticated(struct passwd *pw);
+void do_exec_pty(const char *command, int ptyfd, int ttyfd,
+ const char *ttyname, struct passwd *pw, const char *term,
+ const char *display, const char *auth_proto,
+ const char *auth_data);
+void do_exec_no_pty(const char *command, struct passwd *pw,
+ const char *display, const char *auth_proto,
+ const char *auth_data);
+void do_child(const char *command, struct passwd *pw, const char *term,
+ const char *display, const char *auth_proto,
+ const char *auth_data, const char *ttyname);
+
+/* Signal handler for SIGHUP. Sshd execs itself when it receives SIGHUP;
+ the effect is to reread the configuration file (and to regenerate
+ the server key). */
+
+RETSIGTYPE sighup_handler(int sig)
+{
+ received_sighup = 1;
+ signal(SIGHUP, sighup_handler);
+}
+
+/* Called from the main program after receiving SIGHUP. Restarts the
+ server. */
+
+void sighup_restart()
+{
+ log("Received SIGHUP; restarting.");
+ close(listen_sock);
+ execv(saved_argv[0], saved_argv);
+ log("RESTART FAILED: av0='%s', error: %s.", av0, strerror(errno));
+ exit(1);
+}
+
+/* Generic signal handler for terminating signals in the master daemon.
+ These close the listen socket; not closing it seems to cause "Address
+ already in use" problems on some machines, which is inconvenient. */
+
+RETSIGTYPE sigterm_handler(int sig)
+{
+ log("Received signal %d; terminating.", sig);
+ close(listen_sock);
+ exit(255);
+}
+
+/* SIGCHLD handler. This is called whenever a child dies. This will then
+ reap any zombies left by exited c. */
+
+RETSIGTYPE main_sigchld_handler(int sig)
+{
+ int status;
+ wait(&status);
+ signal(SIGCHLD, main_sigchld_handler);
+}
+
+/* Signal handler for the alarm after the login grace period has expired. */
+
+RETSIGTYPE grace_alarm_handler(int sig)
+{
+ /* Close the connection. */
+ packet_close();
+
+ /* Log error and exit. */
+ fatal("Timeout before authentication.");
+}
+
+/* Signal handler for the key regeneration alarm. Note that this
+ alarm only occurs in the daemon waiting for connections, and it does not
+ do anything with the private key or random state before forking. Thus there
+ should be no concurrency control/asynchronous execution problems. */
+
+RETSIGTYPE key_regeneration_alarm(int sig)
+{
+ /* Check if we should generate a new key. */
+ if (key_used)
+ {
+ /* This should really be done in the background. */
+ log("Generating new %d bit RSA key.", options.server_key_bits);
+ random_acquire_light_environmental_noise(&sensitive_data.random_state);
+ rsa_generate_key(&sensitive_data.private_key, &public_key,
+ &sensitive_data.random_state, options.server_key_bits);
+ random_stir(&sensitive_data.random_state);
+ random_save(&sensitive_data.random_state, options.random_seed_file);
+ key_used = 0;
+ log("RSA key generation complete.");
+ }
+
+ /* Reschedule the alarm. */
+ signal(SIGALRM, key_regeneration_alarm);
+ alarm(options.key_regeneration_time);
+}
+
+/* Main program for the daemon. */
+
+int main(int ac, char **av)
+{
+ extern char *optarg;
+ extern int optind;
+ int opt, aux, sock_in, sock_out, newsock, i, pid, on = 1;
+ int remote_major, remote_minor;
+ struct sockaddr_in sin;
+ char buf[100]; /* Must not be larger than remote_version. */
+ char remote_version[100]; /* Must be at least as big as buf. */
+ char *comment;
+ FILE *f;
+#ifdef SO_LINGER
+ struct linger linger;
+#endif /* SO_LINGER */
+
+ /* Save argv[0]. */
+ saved_argv = av;
+ if (strchr(av[0], '/'))
+ av0 = strrchr(av[0], '/') + 1;
+ else
+ av0 = av[0];
+
+ /* Initialize configuration options to their default values. */
+ initialize_server_options(&options);
+
+ /* Parse command-line arguments. */
+ while ((opt = getopt(ac, av, "f:p:b:k:h:g:diq")) != EOF)
+ {
+ switch (opt)
+ {
+ case 'f':
+ config_file_name = optarg;
+ break;
+ case 'd':
+ debug_flag = 1;
+ break;
+ case 'i':
+ inetd_flag = 1;
+ break;
+ case 'q':
+ options.quiet_mode = 1;
+ break;
+ case 'b':
+ options.server_key_bits = atoi(optarg);
+ break;
+ case 'p':
+ options.port = atoi(optarg);
+ break;
+ case 'g':
+ options.login_grace_time = atoi(optarg);
+ break;
+ case 'k':
+ options.key_regeneration_time = atoi(optarg);
+ break;
+ case 'h':
+ options.host_key_file = optarg;
+ break;
+ case '?':
+ default:
+ fprintf(stderr, "sshd version %s\n", SSH_VERSION);
+ fprintf(stderr, "Usage: %s [options]\n", av0);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -f file Configuration file (default %s/sshd_config)\n", ETCDIR);
+ fprintf(stderr, " -d Debugging mode\n");
+ fprintf(stderr, " -i Started from inetd\n");
+ fprintf(stderr, " -q Quiet (no logging)\n");
+ fprintf(stderr, " -p port Listen on the specified port (default: 22)\n");
+ fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n");
+ fprintf(stderr, " -g seconds Grace period for authentication (default: 300)\n");
+ fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n");
+ fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
+ HOST_KEY_FILE);
+ exit(1);
+ }
+ }
+
+ /* Read server configuration options from the configuration file. */
+ read_server_config(&options, config_file_name);
+
+ /* Fill in default values for those options not explicitly set. */
+ fill_default_server_options(&options);
+
+ /* Check certain values for sanity. */
+ if (options.server_key_bits < 512 ||
+ options.server_key_bits > 32768)
+ {
+ fprintf(stderr, "Bad server key size.\n");
+ exit(1);
+ }
+ if (options.port < 1 || options.port > 65535)
+ {
+ fprintf(stderr, "Bad port number.\n");
+ exit(1);
+ }
+
+ /* Check that there are no remaining arguments. */
+ if (optind < ac)
+ {
+ fprintf(stderr, "Extra argument %s.\n", av[optind]);
+ exit(1);
+ }
+
+ /* Initialize the log (it is reinitialized below in case we forked). */
+ log_init(av0, debug_flag && !inetd_flag,
+ debug_flag || options.fascist_logging,
+ options.quiet_mode, options.log_facility);
+
+ debug("sshd version %.100s", SSH_VERSION);
+
+ /* Load the host key. It must have empty passphrase. */
+ if (!load_private_key(options.host_key_file, "",
+ &sensitive_data.host_key, &comment))
+ {
+ if (debug_flag)
+ fprintf(stderr, "Could not load host key: %s: %s\n",
+ options.host_key_file, strerror(errno));
+ else
+ {
+ int err = errno;
+ log_init(av0, !inetd_flag, 1, 0, options.log_facility);
+ error("Could not load host key: %.200s: %.100s",
+ options.host_key_file, strerror(err));
+ }
+ exit(1);
+ }
+ xfree(comment);
+
+#ifdef SCO
+ (void) set_auth_parameters(ac, av);
+#endif
+
+#ifdef HAVE_OSF1_C2_SECURITY
+ initialize_osf_security(ac, av);
+#endif /* HAVE_OSF1_C2_SECURITY */
+
+ /* If not in debugging mode, and not started from inetd, disconnect from
+ the controlling terminal, and fork. The original process exits. */
+ if (!debug_flag && !inetd_flag)
+ {
+#ifdef TIOCNOTTY
+ int fd;
+#endif /* TIOCNOTTY */
+
+ /* Fork, and have the parent exit. The child becomes the server. */
+ if (fork())
+ exit(0);
+
+ /* Redirect stdin, stdout, and stderr to /dev/null. */
+ freopen("/dev/null", "r", stdin);
+ freopen("/dev/null", "w", stdout);
+ freopen("/dev/null", "w", stderr);
+
+ /* Disconnect from the controlling tty. */
+#ifdef TIOCNOTTY
+ fd = open("/dev/tty", O_RDWR|O_NOCTTY);
+ if (fd >= 0)
+ {
+ (void)ioctl(fd, TIOCNOTTY, NULL);
+ close(fd);
+ }
+#endif /* TIOCNOTTY */
+#ifdef HAVE_SETSID
+ (void)setsid();
+#endif /* HAVE_SETSID */
+ }
+
+ /* Reinitialize the log (because of the fork above). */
+ log_init(av0, debug_flag && !inetd_flag,
+ debug_flag || options.fascist_logging,
+ options.quiet_mode, options.log_facility);
+
+ /* Check that server and host key lengths differ sufficiently. This is
+ necessary to make double encryption work with rsaref. Oh, I hate
+ software patents. */
+ if (options.server_key_bits >
+ sensitive_data.host_key.bits - SSH_KEY_BITS_RESERVED &&
+ options.server_key_bits <
+ sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED)
+ {
+ options.server_key_bits =
+ sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED;
+ debug("Forcing server key to %d bits to make it differ from host key.",
+ options.server_key_bits);
+ }
+
+ /* Initialize memory allocation so that any freed MP_INT data will be
+ zeroed. */
+ rsa_set_mp_memory_allocation();
+
+ /* Do not display messages to stdout in RSA code. */
+ rsa_set_verbose(0);
+
+ /* Initialize the random number generator. */
+ debug("Initializing random number generator; seed file %.200s",
+ options.random_seed_file);
+ random_initialize(&sensitive_data.random_state, options.random_seed_file);
+
+ /* Chdir to the root directory so that the current disk can be unmounted
+ if desired. */
+ chdir("/");
+
+ /* Close connection cleanly after attack. */
+ cipher_attack_detected = packet_disconnect;
+
+ /* Start listening for a socket, unless started from inetd. */
+ if (inetd_flag)
+ {
+ int s1, s2;
+ s1 = dup(0); /* Make sure descriptors 0, 1, and 2 are in use. */
+ s2 = dup(s1);
+ sock_in = dup(0);
+ sock_out = dup(1);
+ /* We intentionally do not close the descriptors 0, 1, and 2 as our
+ code for setting the descriptors won\'t work if ttyfd happens to
+ be one of those. */
+ debug("inetd sockets after dupping: %d, %d", sock_in, sock_out);
+
+ /* Generate an rsa key. */
+ log("Generating %d bit RSA key.", options.server_key_bits);
+ rsa_generate_key(&sensitive_data.private_key, &public_key,
+ &sensitive_data.random_state,
+ options.server_key_bits);
+ random_stir(&sensitive_data.random_state);
+ random_save(&sensitive_data.random_state, options.random_seed_file);
+ log("RSA key generation complete.");
+ }
+ else
+ {
+ /* Create socket for listening. */
+ listen_sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (listen_sock < 0)
+ fatal("socket: %.100s", strerror(errno));
+
+ /* Set socket options. We try to make the port reusable and have it
+ close as fast as possible without waiting in unnecessary wait states
+ on close. */
+ setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
+ sizeof(on));
+#ifdef SO_LINGER
+ linger.l_onoff = 1;
+ linger.l_linger = 5;
+ setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (void *)&linger,
+ sizeof(linger));
+#endif /* SO_LINGER */
+
+ /* Initialize the socket address. */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_addr = options.listen_addr;
+ sin.sin_port = htons(options.port);
+
+ /* Bind the socket to the desired port. */
+ if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) < 0)
+ {
+ error("bind: %.100s", strerror(errno));
+ shutdown(listen_sock, 2);
+ close(listen_sock);
+ fatal("Bind to port %d failed.", options.port);
+ }
+
+ if (!debug_flag)
+ {
+ /* Record our pid in /etc/sshd_pid to make it easier to kill the
+ correct sshd. We don\'t want to do this before the bind above
+ because the bind will fail if there already is a daemon, and this
+ will overwrite any old pid in the file. */
+ f = fopen(SSH_DAEMON_PID_FILE, "w");
+ if (f)
+ {
+ fprintf(f, "%u\n", (unsigned int)getpid());
+ fclose(f);
+ }
+ }
+
+ /* Start listening on the port. */
+ log("Server listening on port %d.", options.port);
+ if (listen(listen_sock, 5) < 0)
+ fatal("listen: %.100s", strerror(errno));
+
+ /* Generate an rsa key. */
+ log("Generating %d bit RSA key.", options.server_key_bits);
+ rsa_generate_key(&sensitive_data.private_key, &public_key,
+ &sensitive_data.random_state,
+ options.server_key_bits);
+ random_stir(&sensitive_data.random_state);
+ random_save(&sensitive_data.random_state, options.random_seed_file);
+ log("RSA key generation complete.");
+
+ /* Schedule server key regeneration alarm. */
+ signal(SIGALRM, key_regeneration_alarm);
+ alarm(options.key_regeneration_time);
+
+ /* Arrange to restart on SIGHUP. The handler needs listen_sock. */
+ signal(SIGHUP, sighup_handler);
+ signal(SIGTERM, sigterm_handler);
+ signal(SIGQUIT, sigterm_handler);
+
+ /* Arrange SIGCHLD to be caught. */
+ signal(SIGCHLD, main_sigchld_handler);
+
+ /* Stay listening for connections until the system crashes or the
+ daemon is killed with a signal. */
+ for (;;)
+ {
+ if (received_sighup)
+ sighup_restart();
+ /* Wait in accept until there is a connection. */
+ aux = sizeof(sin);
+ newsock = accept(listen_sock, (struct sockaddr *)&sin, &aux);
+ if (received_sighup)
+ sighup_restart();
+ if (newsock < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ error("accept: %.100s", strerror(errno));
+ continue;
+ }
+
+#ifdef LIBWRAP
+ {
+ struct request_info req;
+ request_init(&req, RQ_DAEMON, av0, RQ_FILE, newsock, NULL);
+ fromhost(&req);
+ if (!hosts_access(&req))
+ {
+ error("Connection from %.500s refused by tcp_wrappers.",
+ eval_client(&req));
+ shutdown(newsock, 2);
+ close(newsock);
+ continue;
+ }
+ /* if from inet: refuse(&req); */
+ log("connect from %.500s", eval_client(&req));
+ }
+#endif /* LIBWRAP */
+
+ /* Got connection. Fork a child to handle it, unless we are in
+ debugging mode. */
+ if (debug_flag)
+ {
+ /* In debugging mode. Close the listening socket, and start
+ processing the connection without forking. */
+ debug("Server will not fork when running in debugging mode.");
+ close(listen_sock);
+ sock_in = newsock;
+ sock_out = newsock;
+ pid = getpid();
+ break;
+ }
+ else
+ {
+ /* Normal production daemon. Fork, and have the child process
+ the connection. The parent continues listening. */
+ if ((pid = fork()) == 0)
+ {
+ /* Child. Close the listening socket, and start using
+ the accepted socket. Reinitialize logging (since our
+ pid has changed). We break out of the loop to handle
+ the connection. */
+ close(listen_sock);
+ sock_in = newsock;
+ sock_out = newsock;
+ log_init(av0, debug_flag && !inetd_flag,
+ options.fascist_logging || debug_flag,
+ options.quiet_mode, options.log_facility);
+ break;
+ }
+ }
+
+ /* Parent. Stay in the loop. */
+ if (pid < 0)
+ error("fork: %.100s", strerror(errno));
+ else
+ debug("Forked child %d.", pid);
+
+ /* Mark that the key has been used (it was "given" to the child). */
+ key_used = 1;
+
+ /* Close the new socket (the child is now taking care of it). */
+ close(newsock);
+ }
+ }
+
+ /* This is the child processing a new connection. */
+
+ /* Disable the key regeneration alarm. We will not regenerate the key
+ since we are no longer in a position to give it to anyone. We will
+ not restart on SIGHUP since it no longer makes sense. */
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+ signal(SIGCHLD, SIG_DFL);
+
+ /* Set socket options for the connection. We want the socket to close
+ as fast as possible without waiting for anything. If the connection
+ is not a socket, these will do nothing. */
+ /* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
+#ifdef SO_LINGER
+ linger.l_onoff = 1;
+ linger.l_linger = 5;
+ setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
+#endif /* SO_LINGER */
+
+ /* Register our connection. This turns encryption off because we do not
+ have a key. */
+ packet_set_connection(sock_in, sock_out, &sensitive_data.random_state);
+
+ /* Log the connection. */
+ log("Connection from %.100s port %d",
+ get_remote_ipaddr(), get_remote_port());
+
+ /* Check whether logins are denied from this host. */
+ if (options.num_deny_hosts > 0)
+ {
+ const char *hostname = get_canonical_hostname();
+ const char *ipaddr = get_remote_ipaddr();
+ int i;
+ for (i = 0; i < options.num_deny_hosts; i++)
+ if (match_pattern(hostname, options.deny_hosts[i]) ||
+ match_pattern(ipaddr, options.deny_hosts[i]))
+ {
+ log("Connection from %.200s denied.\n", hostname);
+ hostname = "You are not allowed to connect. Go away!\r\n";
+ write(sock_out, hostname, strlen(hostname));
+ close(sock_in);
+ close(sock_out);
+ exit(0);
+ }
+ }
+
+ /* We don\'t want to listen forever unless the other side successfully
+ authenticates itself. So we set up an alarm which is cleared after
+ successful authentication. A limit of zero indicates no limit.
+ Note that we don\'t set the alarm in debugging mode; it is just annoying
+ to have the server exit just when you are about to discover the bug. */
+ signal(SIGALRM, grace_alarm_handler);
+ if (!debug_flag)
+ alarm(options.login_grace_time);
+
+ /* Send our protocol version identification. */
+ sprintf(buf, "SSH-%d.%d-%.100s\n",
+ PROTOCOL_MAJOR, PROTOCOL_MINOR, SSH_VERSION);
+ if (write(sock_out, buf, strlen(buf)) != strlen(buf))
+ fatal("Could not write ident string.");
+
+ /* Read other side\'s version identification. */
+ for (i = 0; i < sizeof(buf) - 1; i++)
+ {
+ if (read(sock_in, &buf[i], 1) != 1)
+ fatal("Did not receive ident string.");
+ if (buf[i] == '\r')
+ {
+ buf[i] = '\n';
+ buf[i + 1] = 0;
+ break;
+ }
+ if (buf[i] == '\n')
+ {
+ /* buf[i] == '\n' */
+ buf[i + 1] = 0;
+ break;
+ }
+ }
+ buf[sizeof(buf) - 1] = 0;
+
+ /* Check that the versions match. In future this might accept several
+ versions and set appropriate flags to handle them. */
+ if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
+ remote_version) != 3)
+ {
+ const char *s = "Protocol mismatch.\n";
+ (void) write(sock_out, s, strlen(s));
+ close(sock_in);
+ close(sock_out);
+ fatal("Bad protocol version identification: %.100s", buf);
+ }
+ debug("Client protocol version %d.%d; client software version %.100s",
+ remote_major, remote_minor, remote_version);
+ if (remote_major != PROTOCOL_MAJOR)
+ {
+ const char *s = "Protocol major versions differ.\n";
+ (void) write(sock_out, s, strlen(s));
+ close(sock_in);
+ close(sock_out);
+ fatal("Protocol major versions differ: %d vs. %d",
+ PROTOCOL_MAJOR, remote_major);
+ }
+
+ /* Check that the client has sufficiently high software version. */
+ if (remote_major == 1 && remote_minor == 0)
+ packet_disconnect("Your ssh version is too old and is no longer supported. Please install a newer version.");
+
+ /* Check whether logins are permitted from this host. */
+ if (options.num_allow_hosts > 0)
+ {
+ const char *hostname = get_canonical_hostname();
+ const char *ipaddr = get_remote_ipaddr();
+ int i;
+ for (i = 0; i < options.num_allow_hosts; i++)
+ if (match_pattern(hostname, options.allow_hosts[i]) ||
+ match_pattern(ipaddr, options.allow_hosts[i]))
+ break;
+ if (i >= options.num_allow_hosts)
+ {
+ log("Connection from %.200s not allowed.\n", hostname);
+ packet_disconnect("Sorry, you are not allowed to connect.");
+ /*NOTREACHED*/
+ }
+ }
+
+ packet_set_nonblocking();
+
+ /* Handle the connection. We pass as argument whether the connection
+ came from a privileged port. */
+ do_connection(get_remote_port() < 1024);
+
+#ifdef KRB4
+ /* Cleanup user's ticket cache file. */
+ if (options.kerberos_ticket_cleanup)
+ (void) dest_tkt();
+#endif /* KRB4 */
+
+ /* Cleanup user's local Xauthority file. */
+ if (xauthfile) unlink(xauthfile);
+
+ /* The connection has been terminated. */
+ log("Closing connection to %.100s", inet_ntoa(sin.sin_addr));
+ packet_close();
+ exit(0);
+}
+
+/* Process an incoming connection. Protocol version identifiers have already
+ been exchanged. This sends server key and performs the key exchange.
+ Server and host keys will no longer be needed after this functions. */
+
+void do_connection(int privileged_port)
+{
+ int i;
+ MP_INT session_key_int;
+ unsigned char session_key[SSH_SESSION_KEY_LENGTH];
+ unsigned char check_bytes[8];
+ char *user;
+ unsigned int cipher_type, auth_mask, protocol_flags;
+ int plen, slen;
+
+ /* Generate check bytes that the client must send back in the user packet
+ in order for it to be accepted; this is used to defy ip spoofing
+ attacks. Note that this only works against somebody doing IP spoofing
+ from a remote machine; any machine on the local network can still see
+ outgoing packets and catch the random cookie. This only affects
+ rhosts authentication, and this is one of the reasons why it is
+ inherently insecure. */
+ for (i = 0; i < 8; i++)
+ check_bytes[i] = random_get_byte(&sensitive_data.random_state);
+
+ /* Send our public key. We include in the packet 64 bits of random
+ data that must be matched in the reply in order to prevent IP spoofing. */
+ packet_start(SSH_SMSG_PUBLIC_KEY);
+ for (i = 0; i < 8; i++)
+ packet_put_char(check_bytes[i]);
+
+ /* Store our public server RSA key. */
+ packet_put_int(public_key.bits);
+ packet_put_mp_int(&public_key.e);
+ packet_put_mp_int(&public_key.n);
+
+ /* Store our public host RSA key. */
+ packet_put_int(sensitive_data.host_key.bits);
+ packet_put_mp_int(&sensitive_data.host_key.e);
+ packet_put_mp_int(&sensitive_data.host_key.n);
+
+ /* Put protocol flags. */
+ packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);
+
+ /* Declare which ciphers we support. */
+ packet_put_int(cipher_mask());
+
+ /* Declare supported authentication types. */
+ auth_mask = 0;
+ if (options.rhosts_authentication)
+ auth_mask |= 1 << SSH_AUTH_RHOSTS;
+ if (options.rhosts_rsa_authentication)
+ auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;
+ if (options.rsa_authentication)
+ auth_mask |= 1 << SSH_AUTH_RSA;
+#ifdef KRB4
+ if (options.kerberos_authentication && (access(KEYFILE, R_OK) == 0))
+ auth_mask |= 1 << SSH_AUTH_KERBEROS;
+#endif
+#ifdef KERBEROS_TGT_PASSING
+ if (options.kerberos_tgt_passing)
+ auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;
+#endif
+#ifdef AFS
+ if (options.afs_token_passing && k_hasafs())
+ auth_mask |= 1 << SSH_PASS_AFS_TOKEN;
+#endif
+ if (options.password_authentication)
+ auth_mask |= 1 << SSH_AUTH_PASSWORD;
+ packet_put_int(auth_mask);
+
+ /* Send the packet and wait for it to be sent. */
+ packet_send();
+ packet_write_wait();
+
+ debug("Sent %d bit public key and %d bit host key.",
+ public_key.bits, sensitive_data.host_key.bits);
+
+ /* Read clients reply (cipher type and session key). */
+ packet_read_expect(&plen, SSH_CMSG_SESSION_KEY);
+
+ /* Get cipher type. */
+ cipher_type = packet_get_char();
+
+ /* Get check bytes from the packet. These must match those we sent earlier
+ with the public key packet. */
+ for (i = 0; i < 8; i++)
+ if (check_bytes[i] != packet_get_char())
+ packet_disconnect("IP Spoofing check bytes do not match.");
+
+ debug("Encryption type: %.200s", cipher_name(cipher_type));
+
+ /* Get the encrypted integer. */
+ mpz_init(&session_key_int);
+ packet_get_mp_int(&session_key_int, &slen);
+
+ /* Get protocol flags. */
+ protocol_flags = packet_get_int();
+ packet_set_protocol_flags(protocol_flags);
+
+ packet_integrity_check(plen, 1 + 8 + slen + 4, SSH_CMSG_SESSION_KEY);
+
+ /* Decrypt it using our private server key and private host key (key with
+ larger modulus first). */
+ if (mpz_cmp(&sensitive_data.private_key.n, &sensitive_data.host_key.n) > 0)
+ {
+ /* Private key has bigger modulus. */
+ assert(sensitive_data.private_key.bits >=
+ sensitive_data.host_key.bits + SSH_KEY_BITS_RESERVED);
+ rsa_private_decrypt(&session_key_int, &session_key_int,
+ &sensitive_data.private_key);
+ rsa_private_decrypt(&session_key_int, &session_key_int,
+ &sensitive_data.host_key);
+ }
+ else
+ {
+ /* Host key has bigger modulus (or they are equal). */
+ assert(sensitive_data.host_key.bits >=
+ sensitive_data.private_key.bits + SSH_KEY_BITS_RESERVED);
+ rsa_private_decrypt(&session_key_int, &session_key_int,
+ &sensitive_data.host_key);
+ rsa_private_decrypt(&session_key_int, &session_key_int,
+ &sensitive_data.private_key);
+ }
+
+ /* Compute session id for this session. */
+ compute_session_id(session_id, check_bytes, sensitive_data.host_key.bits,
+ &sensitive_data.host_key.n,
+ sensitive_data.private_key.bits,
+ &sensitive_data.private_key.n);
+
+ /* Extract session key from the decrypted integer. The key is in the
+ least significant 256 bits of the integer; the first byte of the
+ key is in the highest bits. */
+ mp_linearize_msb_first(session_key, sizeof(session_key),
+ &session_key_int);
+
+ /* Xor the first 16 bytes of the session key with the session id. */
+ for (i = 0; i < 16; i++)
+ session_key[i] ^= session_id[i];
+
+ /* Destroy the decrypted integer. It is no longer needed. */
+ mpz_clear(&session_key_int);
+
+ /* Set the session key. From this on all communications will be
+ encrypted. */
+ packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH,
+ cipher_type, 0);
+
+ /* Destroy our copy of the session key. It is no longer needed. */
+ memset(session_key, 0, sizeof(session_key));
+
+ debug("Received session key; encryption turned on.");
+
+ /* Send an acknowledgement packet. Note that this packet is sent
+ encrypted. */
+ packet_start(SSH_SMSG_SUCCESS);
+ packet_send();
+ packet_write_wait();
+
+ /* Get the name of the user that we wish to log in as. */
+ packet_read_expect(&plen, SSH_CMSG_USER);
+
+ /* Get the user name. */
+ {
+ int ulen;
+ user = packet_get_string(&ulen);
+ packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
+ }
+
+ /* Destroy the private and public keys. They will no longer be needed. */
+ rsa_clear_public_key(&public_key);
+ rsa_clear_private_key(&sensitive_data.private_key);
+ rsa_clear_private_key(&sensitive_data.host_key);
+
+ /* Do the authentication. */
+ do_authentication(user, privileged_port);
+}
+
+/* Performs authentication of an incoming connection. Session key has already
+ been exchanged and encryption is enabled. User is the user name to log
+ in as (received from the clinet). Privileged_port is true if the
+ connection comes from a privileged port (used for .rhosts authentication).*/
+
+void do_authentication(char *user, int privileged_port)
+{
+ int type;
+ int authenticated = 0;
+ char *password;
+ struct passwd *pw, pwcopy;
+ char *client_user;
+ unsigned int client_host_key_bits;
+ MP_INT client_host_key_e, client_host_key_n;
+
+#ifdef AFS
+ /* If machine has AFS, set process authentication group. */
+ if (k_hasafs()) {
+ k_setpag();
+ k_unlog();
+ }
+#endif /* AFS */
+
+ /* Verify that the user is a valid user. */
+ pw = getpwnam(user);
+ if (!pw)
+ {
+ /* The user does not exist. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+
+ /* Keep reading packets, and always respond with a failure. This is to
+ avoid disclosing whether such a user really exists. */
+ for (;;)
+ {
+ /* Read a packet. This will not return if the client disconnects. */
+ int plen;
+ (void) packet_read(&plen);
+
+ /* Send failure. This should be indistinguishable from a failed
+ authentication. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ }
+ /*NOTREACHED*/
+ abort();
+ }
+
+ /* Take a copy of the returned structure. */
+ memset(&pwcopy, 0, sizeof(pwcopy));
+ pwcopy.pw_name = xstrdup(pw->pw_name);
+ pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
+ pwcopy.pw_uid = pw->pw_uid;
+ pwcopy.pw_gid = pw->pw_gid;
+ pwcopy.pw_dir = xstrdup(pw->pw_dir);
+ pwcopy.pw_shell = xstrdup(pw->pw_shell);
+ pw = &pwcopy;
+
+ /* If we are not running as root, the user must have the same uid as the
+ server. */
+ if (getuid() != 0 && pw->pw_uid != getuid())
+ packet_disconnect("Cannot change user when server not running as root.");
+
+ debug("Attempting authentication for %.100s.", user);
+
+ /* If the user has no password, accept authentication immediately. */
+ if (options.password_authentication &&
+#ifdef KRB4
+ options.kerberos_or_local_passwd &&
+#endif /* KRB4 */
+ auth_password(user, ""))
+ {
+ /* Authentication with empty password succeeded. */
+ debug("Login for user %.100s accepted without authentication.", user);
+ /* authentication_type = SSH_AUTH_PASSWORD; */
+ authenticated = 1;
+ /* Success packet will be sent after loop below. */
+ }
+ else
+ {
+ /* Indicate that authentication is needed. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ }
+
+ /* Loop until the user has been authenticated or the connection is closed. */
+ while (!authenticated)
+ {
+ int plen;
+ /* Get a packet from the client. */
+ type = packet_read(&plen);
+
+ /* Process the packet. */
+ switch (type)
+ {
+
+#ifdef KERBEROS_TGT_PASSING
+ case SSH_CMSG_HAVE_KERBEROS_TGT:
+ if (!options.kerberos_tgt_passing)
+ {
+ log("Kerberos tgt passing disabled.");
+ break;
+ }
+ /* Accept Kerberos tgt. */
+ {
+ int dlen;
+ char *data = packet_get_string(&dlen);
+ packet_integrity_check(plen, 4 + dlen, type);
+ if (!auth_kerberos_tgt(pw, data))
+ debug("Kerberos tgt REFUSED for %.100s", user);
+ }
+ continue;
+#endif /* KERBEROS_TGT_PASSING */
+
+#ifdef AFS
+ case SSH_CMSG_HAVE_AFS_TOKEN:
+ if (!options.afs_token_passing || !k_hasafs()) {
+ /* packet_get_all(); */
+ log("AFS token passing disabled.");
+ break;
+ }
+ else {
+ /* Accept AFS token. */
+ int dlen;
+ char *token_string = packet_get_string(&dlen);
+ packet_integrity_check(plen, 4 + dlen, type);
+ if (!auth_afs_token(user, pw->pw_uid, token_string))
+ debug("AFS token REFUSED for %.100s", user);
+ xfree(token_string);
+ continue;
+ }
+#endif /* AFS */
+
+#ifdef KRB4
+ case SSH_CMSG_AUTH_KERBEROS:
+ if (!options.kerberos_authentication)
+ {
+ log("Kerberos authentication disabled.");
+ break;
+ }
+ {
+ /* Try Kerberos v4 authentication. */
+ KTEXT_ST auth;
+ char *tkt_user = NULL;
+ char *kdata = packet_get_string((unsigned int *)&auth.length);
+ packet_integrity_check(plen, 4 + auth.length, type);
+
+ memcpy(auth.dat, kdata, auth.length);
+ xfree(kdata);
+
+ if (auth_krb4(user, &auth, &tkt_user)) {
+ /* Client has successfully authenticated to us. */
+ log("Kerberos authentication accepted %.100s for account "
+ "%.100s from %.200s", tkt_user, user,
+ get_canonical_hostname());
+ /* authentication_type = SSH_AUTH_KERBEROS; */
+ authenticated = 1;
+ xfree(tkt_user);
+ break;
+ }
+ log("Kerberos authentication failed for account "
+ "%.100s from %.200s", user, get_canonical_hostname());
+ }
+ break;
+#endif /* KRB4 */
+
+ case SSH_CMSG_AUTH_RHOSTS:
+ if (!options.rhosts_authentication)
+ {
+ log("Rhosts authentication disabled.");
+ break;
+ }
+
+ /* Rhosts authentication (also uses /etc/hosts.equiv). */
+ if (!privileged_port)
+ {
+ log("Rhosts authentication not available for connections from unprivileged port.");
+ break;
+ }
+
+ /* Get client user name. Note that we just have to trust the client;
+ this is one reason why rhosts authentication is insecure.
+ (Another is IP-spoofing on a local network.) */
+ {
+ int dlen;
+ client_user = packet_get_string(&dlen);
+ packet_integrity_check(plen, 4 + dlen, type);
+ }
+
+ /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
+ if (auth_rhosts(pw, client_user, options.ignore_rhosts,
+ options.strict_modes))
+ {
+ /* Authentication accepted. */
+ log("Rhosts authentication accepted for %.100s, remote %.100s on %.700s.",
+ user, client_user, get_canonical_hostname());
+ authenticated = 1;
+ xfree(client_user);
+ break;
+ }
+ debug("Rhosts authentication failed for %.100s, remote %.100s.",
+ user, client_user);
+ xfree(client_user);
+ break;
+
+ case SSH_CMSG_AUTH_RHOSTS_RSA:
+ if (!options.rhosts_rsa_authentication)
+ {
+ log("Rhosts with RSA authentication disabled.");
+ break;
+ }
+
+ /* Rhosts authentication (also uses /etc/hosts.equiv) with RSA
+ host authentication. */
+ if (!privileged_port)
+ {
+ log("Rhosts authentication not available for connections from unprivileged port.");
+ break;
+ }
+
+ {
+ int ulen, elen, nlen;
+ /* Get client user name. Note that we just have to trust
+ the client; root on the client machine can claim to be
+ any user. */
+ client_user = packet_get_string(&ulen);
+
+ /* Get the client host key. */
+ mpz_init(&client_host_key_e);
+ mpz_init(&client_host_key_n);
+ client_host_key_bits = packet_get_int();
+ packet_get_mp_int(&client_host_key_e, &elen);
+ packet_get_mp_int(&client_host_key_n, &nlen);
+
+ packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
+ }
+
+ /* Try to authenticate using /etc/hosts.equiv and .rhosts. */
+ if (auth_rhosts_rsa(&sensitive_data.random_state,
+ pw, client_user,
+ client_host_key_bits, &client_host_key_e,
+ &client_host_key_n, options.ignore_rhosts,
+ options.strict_modes))
+ {
+ /* Authentication accepted. */
+ authenticated = 1;
+ xfree(client_user);
+ mpz_clear(&client_host_key_e);
+ mpz_clear(&client_host_key_n);
+ break;
+ }
+ debug("Rhosts authentication failed for %.100s, remote %.100s.",
+ user, client_user);
+ xfree(client_user);
+ mpz_clear(&client_host_key_e);
+ mpz_clear(&client_host_key_n);
+ break;
+
+ case SSH_CMSG_AUTH_RSA:
+ if (!options.rsa_authentication)
+ {
+ log("RSA authentication disabled.");
+ break;
+ }
+
+ /* RSA authentication requested. */
+ {
+ int nlen;
+ MP_INT n;
+ mpz_init(&n);
+ packet_get_mp_int(&n, &nlen);
+
+ packet_integrity_check(plen, nlen, type);
+
+ if (auth_rsa(pw, &n, &sensitive_data.random_state))
+ {
+ /* Successful authentication. */
+ mpz_clear(&n);
+ log("RSA authentication for %.100s accepted.", user);
+ authenticated = 1;
+ break;
+ }
+ mpz_clear(&n);
+ debug("RSA authentication for %.100s failed.", user);
+ }
+ break;
+
+ case SSH_CMSG_AUTH_PASSWORD:
+ if (!options.password_authentication)
+ {
+ log("Password authentication disabled.");
+ break;
+ }
+
+ /* Password authentication requested. */
+ /* Read user password. It is in plain text, but was transmitted
+ over the encrypted channel so it is not visible to an outside
+ observer. */
+ {
+ int passw_len;
+ password = packet_get_string(&passw_len);
+ packet_integrity_check(plen, 4 + passw_len, type);
+ }
+
+ /* Try authentication with the password. */
+ if (auth_password(user, password))
+ {
+ /* Successful authentication. */
+ /* Clear the password from memory. */
+ memset(password, 0, strlen(password));
+ xfree(password);
+ log("Password authentication for %.100s accepted.", user);
+ authenticated = 1;
+ break;
+ }
+ debug("Password authentication for %.100s failed.", user);
+ memset(password, 0, strlen(password));
+ xfree(password);
+ break;
+
+ default:
+ /* Any unknown messages will be ignored (and failure returned)
+ during authentication. */
+ log("Unknown message during authentication: type %d", type);
+ break; /* Respond with a failure message. */
+ }
+ /* If successfully authenticated, break out of loop. */
+ if (authenticated)
+ break;
+
+ /* Send a message indicating that the authentication attempt failed. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ }
+
+ /* Check if the user is logging in as root and root logins are disallowed. */
+ if (pw->pw_uid == 0 && !options.permit_root_login)
+ {
+ if (forced_command)
+ log("Root login accepted for forced command.", forced_command);
+ else
+ packet_disconnect("ROOT LOGIN REFUSED FROM %.200s",
+ get_canonical_hostname());
+ }
+
+ /* The user has been authenticated and accepted. */
+ packet_start(SSH_SMSG_SUCCESS);
+ packet_send();
+ packet_write_wait();
+
+ /* Perform session preparation. */
+ do_authenticated(pw);
+}
+
+/* Prepares for an interactive session. This is called after the user has
+ been successfully authenticated. During this message exchange, pseudo
+ terminals are allocated, X11, TCP/IP, and authentication agent forwardings
+ are requested, etc. */
+
+void do_authenticated(struct passwd *pw)
+{
+ int type;
+#ifdef WITH_ZLIB
+ int compression_level = 0, enable_compression_after_reply = 0;
+#endif /* WITH_ZLIB */
+ int have_pty = 0, ptyfd = -1, ttyfd = -1;
+ int row, col, xpixel, ypixel, screen;
+ char ttyname[64];
+ char *command, *term = NULL, *display = NULL, *proto = NULL, *data = NULL;
+ struct group *grp;
+ gid_t tty_gid;
+ mode_t tty_mode;
+ int n_bytes;
+
+ /* Cancel the alarm we set to limit the time taken for authentication. */
+ alarm(0);
+
+ /* Inform the channel mechanism that we are the server side and that
+ the client may request to connect to any port at all. (The user could
+ do it anyway, and we wouldn\'t know what is permitted except by the
+ client telling us, so we can equally well trust the client not to request
+ anything bogus.) */
+ channel_permit_all_opens();
+
+ /* We stay in this loop until the client requests to execute a shell or a
+ command. */
+ while (1)
+ {
+ int plen, dlen;
+
+ /* Get a packet from the client. */
+ type = packet_read(&plen);
+
+ /* Process the packet. */
+ switch (type)
+ {
+#ifdef WITH_ZLIB
+ case SSH_CMSG_REQUEST_COMPRESSION:
+ packet_integrity_check(plen, 4, type);
+ compression_level = packet_get_int();
+ if (compression_level < 1 || compression_level > 9)
+ {
+ packet_send_debug("Received illegal compression level %d.",
+ compression_level);
+ goto fail;
+ }
+ /* Enable compression after we have responded with SUCCESS. */
+ enable_compression_after_reply = 1;
+ break;
+#endif /* WITH_ZLIB */
+
+ case SSH_CMSG_REQUEST_PTY:
+ if (no_pty_flag)
+ {
+ debug("Allocating a pty not permitted for this authentication.");
+ goto fail;
+ }
+ if (have_pty)
+ packet_disconnect("Protocol error: you already have a pty.");
+
+ debug("Allocating pty.");
+
+ /* Allocate a pty and open it. */
+ if (!pty_allocate(&ptyfd, &ttyfd, ttyname))
+ {
+ error("Failed to allocate pty.");
+ goto fail;
+ }
+
+ /* Determine the group to make the owner of the tty. */
+#ifdef TTY_GROUP
+ grp = getgrnam(TTY_GROUP);
+#else /* TTY_GROUP */
+ grp = getgrnam("tty");
+#endif /* TTY_GROUP */
+ if (grp)
+ {
+ tty_gid = grp->gr_gid;
+ tty_mode = S_IRUSR|S_IWUSR|S_IWGRP;
+ }
+ else
+ {
+ tty_gid = pw->pw_gid;
+ tty_mode = S_IRUSR|S_IWUSR|S_IWGRP|S_IWOTH;
+ }
+
+ /* Change ownership of the tty. */
+ if (chown(ttyname, pw->pw_uid, tty_gid) < 0)
+ fatal("chown(%.100s, %d, %d) failed: %.100s",
+ ttyname, pw->pw_uid, tty_gid, strerror(errno));
+ if (chmod(ttyname, tty_mode) < 0)
+ fatal("chmod(%.100s, 0%o) failed: %.100s",
+ ttyname, tty_mode, strerror(errno));
+
+ /* Get TERM from the packet. Note that the value may be of arbitrary
+ length. */
+
+ term = packet_get_string(&dlen);
+ packet_integrity_check(dlen, strlen(term), type);
+ /* packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type); */
+ /* Remaining bytes */
+ n_bytes = plen - (4 + dlen + 4*4);
+
+ if (strcmp(term, "") == 0)
+ term = NULL;
+
+ /* Get window size from the packet. */
+ row = packet_get_int();
+ col = packet_get_int();
+ xpixel = packet_get_int();
+ ypixel = packet_get_int();
+ pty_change_window_size(ptyfd, row, col, xpixel, ypixel);
+
+ /* Get tty modes from the packet. */
+ tty_parse_modes(ttyfd, &n_bytes);
+ packet_integrity_check(plen, 4 + dlen + 4*4 + n_bytes, type);
+
+ /* Indicate that we now have a pty. */
+ have_pty = 1;
+ break;
+
+ case SSH_CMSG_X11_REQUEST_FORWARDING:
+ if (!options.x11_forwarding)
+ {
+ packet_send_debug("X11 forwarding disabled in server configuration file.");
+ goto fail;
+ }
+#ifdef XAUTH_PATH
+ if (no_x11_forwarding_flag)
+ {
+ packet_send_debug("X11 forwarding not permitted for this authentication.");
+ goto fail;
+ }
+ debug("Received request for X11 forwarding with auth spoofing.");
+ if (display)
+ packet_disconnect("Protocol error: X11 display already set.");
+ {
+ int proto_len, data_len;
+ proto = packet_get_string(&proto_len);
+ data = packet_get_string(&data_len);
+ packet_integrity_check(plen, 4+proto_len + 4+data_len + 4, type);
+ }
+ if (packet_get_protocol_flags() & SSH_PROTOFLAG_SCREEN_NUMBER)
+ screen = packet_get_int();
+ else
+ screen = 0;
+ display = x11_create_display_inet(screen);
+ if (!display)
+ goto fail;
+
+ /* Setup to always have a local .Xauthority. */
+ xauthfile = xmalloc(MAXPATHLEN);
+ sprintf(xauthfile, "/tmp/Xauth%d_%d", pw->pw_uid, getpid());
+
+ break;
+#else /* XAUTH_PATH */
+ /* No xauth program; we won't accept forwarding with spoofing. */
+ packet_send_debug("No xauth program; cannot forward with spoofing.");
+ goto fail;
+#endif /* XAUTH_PATH */
+
+ case SSH_CMSG_AGENT_REQUEST_FORWARDING:
+ if (no_agent_forwarding_flag)
+ {
+ debug("Authentication agent forwarding not permitted for this authentication.");
+ goto fail;
+ }
+ debug("Received authentication agent forwarding request.");
+ auth_input_request_forwarding(pw);
+ break;
+
+ case SSH_CMSG_PORT_FORWARD_REQUEST:
+ if (no_port_forwarding_flag)
+ {
+ debug("Port forwarding not permitted for this authentication.");
+ goto fail;
+ }
+ debug("Received TCP/IP port forwarding request.");
+ channel_input_port_forward_request(pw->pw_uid == 0);
+ break;
+
+ case SSH_CMSG_EXEC_SHELL:
+ /* Set interactive/non-interactive mode. */
+ packet_set_interactive(have_pty || display != NULL,
+ options.keepalives);
+
+ if (forced_command != NULL)
+ goto do_forced_command;
+ debug("Forking shell.");
+ packet_integrity_check(plen, 0, type);
+ if (have_pty)
+ do_exec_pty(NULL, ptyfd, ttyfd, ttyname, pw, term, display, proto,
+ data);
+ else
+ do_exec_no_pty(NULL, pw, display, proto, data);
+ return;
+
+ case SSH_CMSG_EXEC_CMD:
+ /* Set interactive/non-interactive mode. */
+ packet_set_interactive(have_pty || display != NULL,
+ options.keepalives);
+
+ if (forced_command != NULL)
+ goto do_forced_command;
+ /* Get command from the packet. */
+ {
+ int dlen;
+ command = packet_get_string(&dlen);
+ debug("Executing command '%.500s'", command);
+ packet_integrity_check(plen, 4 + dlen, type);
+ }
+ if (have_pty)
+ do_exec_pty(command, ptyfd, ttyfd, ttyname, pw, term, display,
+ proto, data);
+ else
+ do_exec_no_pty(command, pw, display, proto, data);
+ xfree(command);
+ return;
+
+ default:
+ /* Any unknown messages in this phase are ignored, and a failure
+ message is returned. */
+ log("Unknown packet type received after authentication: %d", type);
+ goto fail;
+ }
+
+ /* The request was successfully processed. */
+ packet_start(SSH_SMSG_SUCCESS);
+ packet_send();
+ packet_write_wait();
+
+#ifdef WITH_ZLIB
+ /* Enable compression now that we have replied if appropriate. */
+ if (enable_compression_after_reply)
+ {
+ enable_compression_after_reply = 0;
+ packet_start_compression(compression_level);
+ }
+#endif /* WITH_ZLIB */
+
+ continue;
+
+ fail:
+ /* The request failed. */
+ packet_start(SSH_SMSG_FAILURE);
+ packet_send();
+ packet_write_wait();
+ continue;
+
+ do_forced_command:
+ /* There is a forced command specified for this login. Execute it. */
+ debug("Executing forced command: %.900s", forced_command);
+ if (have_pty)
+ do_exec_pty(forced_command, ptyfd, ttyfd, ttyname, pw, term, display,
+ proto, data);
+ else
+ do_exec_no_pty(forced_command, pw, display, proto, data);
+ return;
+ }
+}
+
+/* This is called to fork and execute a command when we have no tty. This
+ will call do_child from the child, and server_loop from the parent after
+ setting up file descriptors and such. */
+
+void do_exec_no_pty(const char *command, struct passwd *pw,
+ const char *display, const char *auth_proto,
+ const char *auth_data)
+{
+ int pid;
+
+#ifdef USE_PIPES
+ int pin[2], pout[2], perr[2];
+ /* Allocate pipes for communicating with the program. */
+ if (pipe(pin) < 0 || pipe(pout) < 0 || pipe(perr) < 0)
+ packet_disconnect("Could not create pipes: %.100s",
+ strerror(errno));
+#else /* USE_PIPES */
+ int inout[2], err[2];
+ /* Uses socket pairs to communicate with the program. */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
+ socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
+ packet_disconnect("Could not create socket pairs: %.100s",
+ strerror(errno));
+#endif /* USE_PIPES */
+
+ /* Fork the child. */
+ if ((pid = fork()) == 0)
+ {
+ /* Child. Reinitialize the log since the pid has changed. */
+ log_init(av0, debug_flag && !inetd_flag, debug_flag,
+ options.quiet_mode, options.log_facility);
+
+#ifdef USE_PIPES
+ /* Redirect stdin. We close the parent side of the socket pair,
+ and make the child side the standard input. */
+ close(pin[1]);
+ if (dup2(pin[0], 0) < 0)
+ perror("dup2 stdin");
+ close(pin[0]);
+
+ /* Redirect stdout. */
+ close(pout[0]);
+ if (dup2(pout[1], 1) < 0)
+ perror("dup2 stdout");
+ close(pout[1]);
+
+ /* Redirect stderr. */
+ close(perr[0]);
+ if (dup2(perr[1], 2) < 0)
+ perror("dup2 stderr");
+ close(perr[1]);
+#else /* USE_PIPES */
+ /* Redirect stdin, stdout, and stderr. Stdin and stdout will use the
+ same socket, as some programs (particularly rdist) seem to depend
+ on it. */
+ close(inout[1]);
+ close(err[1]);
+ if (dup2(inout[0], 0) < 0) /* stdin */
+ perror("dup2 stdin");
+ if (dup2(inout[0], 1) < 0) /* stdout. Note: same socket as stdin. */
+ perror("dup2 stdout");
+ if (dup2(err[0], 2) < 0) /* stderr */
+ perror("dup2 stderr");
+#endif /* USE_PIPES */
+
+ /* Do processing for the child (exec command etc). */
+ do_child(command, pw, NULL, display, auth_proto, auth_data, NULL);
+ /*NOTREACHED*/
+ }
+ if (pid < 0)
+ packet_disconnect("fork failed: %.100s", strerror(errno));
+#ifdef USE_PIPES
+ /* We are the parent. Close the child sides of the pipes. */
+ close(pin[0]);
+ close(pout[1]);
+ close(perr[1]);
+
+ /* Enter the interactive session. */
+ server_loop(pid, pin[1], pout[0], perr[0]);
+ /* server_loop has closed pin[1], pout[1], and perr[1]. */
+#else /* USE_PIPES */
+ /* We are the parent. Close the child sides of the socket pairs. */
+ close(inout[0]);
+ close(err[0]);
+
+ /* Enter the interactive session. Note: server_loop must be able to handle
+ the case that fdin and fdout are the same. */
+ server_loop(pid, inout[1], inout[1], err[1]);
+ /* server_loop has closed inout[1] and err[1]. */
+#endif /* USE_PIPES */
+}
+
+struct pty_cleanup_context
+{
+ const char *ttyname;
+ int pid;
+};
+
+/* Function to perform cleanup if we get aborted abnormally (e.g., due to a
+ dropped connection). */
+
+void pty_cleanup_proc(void *context)
+{
+ struct pty_cleanup_context *cu = context;
+
+ debug("pty_cleanup_proc called");
+
+#if defined(KRB4) || defined(AFS)
+ /* Destroy user's ticket cache file. */
+ (void) dest_tkt();
+#endif /* KRB4 || AFS */
+
+ /* Record that the user has logged out. */
+ record_logout(cu->pid, cu->ttyname);
+
+ /* Release the pseudo-tty. */
+ pty_release(cu->ttyname);
+}
+
+/* This is called to fork and execute a command when we have a tty. This
+ will call do_child from the child, and server_loop from the parent after
+ setting up file descriptors, controlling tty, updating wtmp, utmp,
+ lastlog, and other such operations. */
+
+void do_exec_pty(const char *command, int ptyfd, int ttyfd,
+ const char *ttyname, struct passwd *pw, const char *term,
+ const char *display, const char *auth_proto,
+ const char *auth_data)
+{
+ int pid, fdout;
+ const char *hostname;
+ time_t last_login_time;
+ char buf[100], *time_string;
+ FILE *f;
+ char line[256];
+ struct stat st;
+ int quiet_login;
+ struct sockaddr_in from;
+ int fromlen;
+ struct pty_cleanup_context cleanup_context;
+
+ /* Get remote host name. */
+ hostname = get_canonical_hostname();
+
+ /* Get the time when the user last logged in. Buf will be set to contain
+ the hostname the last login was from. */
+ last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
+ buf, sizeof(buf));
+
+ /* Fork the child. */
+ if ((pid = fork()) == 0)
+ {
+ pid = getpid();
+
+ /* Child. Reinitialize the log because the pid has changed. */
+ log_init(av0, debug_flag && !inetd_flag, debug_flag, options.quiet_mode,
+ options.log_facility);
+
+ /* Close the master side of the pseudo tty. */
+ close(ptyfd);
+
+ /* Make the pseudo tty our controlling tty. */
+ pty_make_controlling_tty(&ttyfd, ttyname);
+
+ /* Redirect stdin from the pseudo tty. */
+ if (dup2(ttyfd, fileno(stdin)) < 0)
+ error("dup2 stdin failed: %.100s", strerror(errno));
+
+ /* Redirect stdout to the pseudo tty. */
+ if (dup2(ttyfd, fileno(stdout)) < 0)
+ error("dup2 stdin failed: %.100s", strerror(errno));
+
+ /* Redirect stderr to the pseudo tty. */
+ if (dup2(ttyfd, fileno(stderr)) < 0)
+ error("dup2 stdin failed: %.100s", strerror(errno));
+
+ /* Close the extra descriptor for the pseudo tty. */
+ close(ttyfd);
+
+ /* Get IP address of client. This is needed because we want to record
+ where the user logged in from. If the connection is not a socket,
+ let the ip address be 0.0.0.0. */
+ memset(&from, 0, sizeof(from));
+ if (packet_get_connection_in() == packet_get_connection_out())
+ {
+ fromlen = sizeof(from);
+ if (getpeername(packet_get_connection_in(),
+ (struct sockaddr *)&from, &fromlen) < 0)
+ fatal("getpeername: %.100s", strerror(errno));
+ }
+
+ /* Record that there was a login on that terminal. */
+ record_login(pid, ttyname, pw->pw_name, pw->pw_uid, hostname,
+ &from);
+
+ /* Check if .hushlogin exists. */
+ sprintf(line, "%.200s/.hushlogin", pw->pw_dir);
+ quiet_login = stat(line, &st) >= 0;
+
+ /* If the user has logged in before, display the time of last login.
+ However, don't display anything extra if a command has been
+ specified (so that ssh can be used to execute commands on a remote
+ machine without users knowing they are going to another machine). */
+ if (command == NULL && last_login_time != 0 && !quiet_login)
+ {
+ /* Convert the date to a string. */
+ time_string = ctime(&last_login_time);
+ /* Remove the trailing newline. */
+ if (strchr(time_string, '\n'))
+ *strchr(time_string, '\n') = 0;
+ /* Display the last login time. Host if displayed if known. */
+ if (strcmp(buf, "") == 0)
+ printf("Last login: %s\r\n", time_string);
+ else
+ printf("Last login: %s from %s\r\n", time_string, buf);
+ }
+
+ /* Print /etc/motd unless a command was specified or printing it was
+ disabled in server options. Note that some machines appear to
+ print it in /etc/profile or similar. */
+ if (command == NULL && options.print_motd && !quiet_login)
+ {
+ /* Print /etc/motd if it exists. */
+ f = fopen("/etc/motd", "r");
+ if (f)
+ {
+ while (fgets(line, sizeof(line), f))
+ fputs(line, stdout);
+ fclose(f);
+ }
+ }
+
+ /* Do common processing for the child, such as execing the command. */
+ do_child(command, pw, term, display, auth_proto, auth_data, ttyname);
+ /*NOTREACHED*/
+ }
+ if (pid < 0)
+ packet_disconnect("fork failed: %.100s", strerror(errno));
+ /* Parent. Close the slave side of the pseudo tty. */
+ close(ttyfd);
+
+ /* Create another descriptor of the pty master side for use as the standard
+ input. We could use the original descriptor, but this simplifies code
+ in server_loop. The descriptor is bidirectional. */
+ fdout = dup(ptyfd);
+ if (fdout < 0)
+ packet_disconnect("dup failed: %.100s", strerror(errno));
+
+ /* Add a cleanup function to clear the utmp entry and record logout time
+ in case we call fatal() (e.g., the connection gets closed). */
+ cleanup_context.pid = pid;
+ cleanup_context.ttyname = ttyname;
+ fatal_add_cleanup(pty_cleanup_proc, (void *)&cleanup_context);
+
+ /* Enter interactive session. */
+ server_loop(pid, ptyfd, fdout, -1);
+ /* server_loop has not closed ptyfd and fdout. */
+
+ /* Cancel the cleanup function. */
+ fatal_remove_cleanup(pty_cleanup_proc, (void *)&cleanup_context);
+
+ /* Record that the user has logged out. */
+ record_logout(pid, ttyname);
+
+ /* Release the pseudo-tty. */
+ pty_release(ttyname);
+
+ /* Close the server side of the socket pairs. We must do this after the
+ pty cleanup, so that another process doesn't get this pty while we're
+ still cleaning up. */
+ close(ptyfd);
+ close(fdout);
+}
+
+/* Sets the value of the given variable in the environment. If the variable
+ already exists, its value is overriden. */
+
+void child_set_env(char ***envp, unsigned int *envsizep, const char *name,
+ const char *value)
+{
+ unsigned int i, namelen;
+ char **env;
+
+ /* Find the slot where the value should be stored. If the variable already
+ exists, we reuse the slot; otherwise we append a new slot at the end
+ of the array, expanding if necessary. */
+ env = *envp;
+ namelen = strlen(name);
+ for (i = 0; env[i]; i++)
+ if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
+ break;
+ if (env[i])
+ {
+ /* Name already exists. Reuse the slot. */
+ xfree(env[i]);
+ }
+ else
+ {
+ /* New variable. Expand the array if necessary. */
+ if (i >= (*envsizep) - 1)
+ {
+ (*envsizep) += 50;
+ env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
+ }
+
+ /* Need to set the NULL pointer at end of array beyond the new
+ slot. */
+ env[i + 1] = NULL;
+ }
+
+ /* Allocate space and format the variable in the appropriate slot. */
+ env[i] = xmalloc(strlen(name) + 1 + strlen(value) + 1);
+ sprintf(env[i], "%s=%s", name, value);
+}
+
+/* Reads environment variables from the given file and adds/overrides them
+ into the environment. If the file does not exist, this does nothing.
+ Otherwise, it must consist of empty lines, comments (line starts with '#')
+ and assignments of the form name=value. No other forms are allowed. */
+
+void read_environment_file(char ***env, unsigned int *envsize,
+ const char *filename)
+{
+ FILE *f;
+ char buf[4096];
+ char *cp, *value;
+
+ /* Open the environment file. */
+ f = fopen(filename, "r");
+ if (!f)
+ return; /* Not found. */
+
+ /* Process each line. */
+ while (fgets(buf, sizeof(buf), f))
+ {
+ /* Skip leading whitespace. */
+ for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
+ ;
+
+ /* Ignore empty and comment lines. */
+ if (!*cp || *cp == '#' || *cp == '\n')
+ continue;
+
+ /* Remove newline. */
+ if (strchr(cp, '\n'))
+ *strchr(cp, '\n') = '\0';
+
+ /* Find the equals sign. Its lack indicates badly formatted line. */
+ value = strchr(cp, '=');
+ if (value == NULL)
+ {
+ fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
+ continue;
+ }
+
+ /* Replace the equals sign by nul, and advance value to the value
+ string. */
+ *value = '\0';
+ value++;
+
+ /* Set the value in environment. */
+ child_set_env(env, envsize, cp, value);
+ }
+
+ fclose(f);
+}
+
+
+#ifdef HAVE_ETC_DEFAULT_LOGIN
+
+/* Gets the value of the given variable in the environment. If the
+ variable does not exist, returns NULL. */
+
+char *child_get_env(char **env, const char *name)
+{
+ unsigned int i, namelen;
+
+ namelen = strlen(name);
+
+ for (i = 0; env[i]; i++)
+ if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
+ break;
+ if (env[i])
+ return &env[i][namelen + 1];
+ else
+ return NULL;
+}
+
+/* Processes /etc/default/login; this involves things like environment
+ settings, ulimit, etc. This file exists at least on Solaris 2.x. */
+
+void read_etc_default_login(char ***env, unsigned int *envsize,
+ struct passwd *pw)
+{
+ unsigned int defenvsize;
+ char **defenv, *def;
+ int i;
+
+ /* Read /etc/default/login into a separate temporary environment. */
+ defenvsize = 10;
+ defenv = xmalloc(defenvsize * sizeof(char *));
+ defenv[0] = NULL;
+ read_environment_file(&defenv, &defenvsize, "/etc/default/login");
+
+ /* Set SHELL if ALTSHELL is YES. */
+ def = child_get_env(defenv, "ALTSHELL");
+ if (def != NULL && strcmp(def, "YES") == 0)
+ child_set_env(env, envsize, "SHELL", pw->pw_shell);
+
+ /* Set PATH from SUPATH if we are logging in as root, and PATH
+ otherwise. If neither of these exists, we use the default ssh
+ path. */
+ if (pw->pw_uid == 0)
+ def = child_get_env(defenv, "SUPATH");
+ else
+ def = child_get_env(defenv, "PATH");
+ if (def != NULL)
+ child_set_env(env, envsize, "PATH", def);
+ else
+ child_set_env(env, envsize, "PATH", DEFAULT_PATH);
+
+ /* Set TZ if TIMEZONE is defined and we haven't inherited a value
+ for TZ. */
+ def = getenv("TZ");
+ if (def == NULL)
+ def = child_get_env(defenv, "TIMEZONE");
+ if (def != NULL)
+ child_set_env(env, envsize, "TZ", def);
+
+ /* Set HZ if defined. */
+ def = child_get_env(defenv, "HZ");
+ if (def != NULL)
+ child_set_env(env, envsize, "HZ", def);
+
+ /* Set up the default umask if UMASK is defined. */
+ def = child_get_env(defenv, "UMASK");
+ if (def != NULL)
+ {
+ int i, value;
+
+ for (value = i = 0;
+ def[i] && isdigit(def[i]) && def[i] != '8' && def[i] != '9';
+ i++)
+ value = value * 8 + def[i] - '0';
+
+ umask(value);
+ }
+
+ /* Set up the file size ulimit if ULIMIT is set. */
+ def = child_get_env(defenv, "ULIMIT");
+ if (def != NULL && atoi(def) > 0)
+ ulimit(UL_SETFSIZE, atoi(def));
+
+ /* Free the temporary environment. */
+ for (i = 0; defenv[i]; i++)
+ xfree(defenv[i]);
+ xfree(defenv);
+}
+
+#endif /* HAVE_ETC_DEFAULT_LOGIN */
+
+/* Performs common processing for the child, such as setting up the
+ environment, closing extra file descriptors, setting the user and group
+ ids, and executing the command or shell. */
+
+void do_child(const char *command, struct passwd *pw, const char *term,
+ const char *display, const char *auth_proto,
+ const char *auth_data, const char *ttyname)
+{
+ const char *shell, *cp;
+ char buf[256];
+ FILE *f;
+ unsigned int envsize, i;
+ char **env;
+ extern char **environ;
+ struct stat st;
+ char *argv[10];
+
+ /* Check /etc/nologin. */
+ f = fopen("/etc/nologin", "r");
+ if (f)
+ { /* /etc/nologin exists. Print its contents and exit. */
+ while (fgets(buf, sizeof(buf), f))
+ fputs(buf, stderr);
+ fclose(f);
+ if (pw->pw_uid != 0)
+ exit(254);
+ }
+
+#ifdef HAVE_SETLOGIN
+ /* Set login name in the kernel. */
+ setlogin(pw->pw_name);
+#endif /* HAVE_SETLOGIN */
+
+#ifdef HAVE_USERSEC_H
+ /* On AIX, this "sets process credentials". I am not sure what this
+ includes, but it seems to be important. This also does setuid
+ (but we do it below as well just in case). */
+ if (setpcred((char *)pw->pw_name, NULL))
+ log("setpcred %.100s: %.100s", strerror(errno));
+#endif /* HAVE_USERSEC_H */
+
+ /* Set uid, gid, and groups. */
+ if (getuid() == 0 || geteuid() == 0)
+ {
+ if (setgid(pw->pw_gid) < 0)
+ {
+ perror("setgid");
+ exit(1);
+ }
+#ifdef HAVE_INITGROUPS
+ /* Initialize the group list. */
+ if (initgroups(pw->pw_name, pw->pw_gid) < 0)
+ {
+ perror("initgroups");
+ exit(1);
+ }
+#endif /* HAVE_INITGROUPS */
+ endgrent();
+
+#ifdef HAVE_SETLUID
+ /* Initialize login UID. */
+ if (setluid(user_uid) < 0)
+ {
+ perror("setluid");
+ exit(1);
+ }
+#endif /* HAVE_SETLUID */
+
+ /* Permanently switch to the desired uid. */
+ permanently_set_uid(pw->pw_uid);
+ }
+
+ if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
+ fatal("Failed to set uids to %d.", (int)pw->pw_uid);
+
+ /* Get the shell from the password data. An empty shell field is legal,
+ and means /bin/sh. */
+ shell = (pw->pw_shell[0] == '\0') ? DEFAULT_SHELL : pw->pw_shell;
+
+#ifdef AFS
+ /* Try to get AFS tokens for the local cell. */
+ if (k_hasafs()) {
+ char cell[64];
+
+ if (k_afs_cell_of_file(pw->pw_dir, cell, sizeof(cell)) == 0)
+ krb_afslog(cell, 0);
+
+ krb_afslog(0, 0);
+ }
+#endif /* AFS */
+
+ /* Initialize the environment. In the first part we allocate space for
+ all environment variables. */
+ envsize = 100;
+ env = xmalloc(envsize * sizeof(char *));
+ env[0] = NULL;
+
+ /* Set basic environment. */
+ child_set_env(&env, &envsize, "USER", pw->pw_name);
+ child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
+ child_set_env(&env, &envsize, "HOME", pw->pw_dir);
+ child_set_env(&env, &envsize, "PATH", DEFAULT_PATH);
+
+ /* Let it inherit timezone if we have one. */
+ if (getenv("TZ"))
+ child_set_env(&env, &envsize, "TZ", getenv("TZ"));
+
+#ifdef MAIL_SPOOL_DIRECTORY
+ sprintf(buf, "%.200s/%.50s", MAIL_SPOOL_DIRECTORY, pw->pw_name);
+ child_set_env(&env, &envsize, "MAIL", buf);
+#else /* MAIL_SPOOL_DIRECTORY */
+#ifdef HAVE_TILDE_NEWMAIL
+ sprintf(buf, "%.200s/newmail", pw->pw_dir);
+ child_set_env(&env, &envsize, "MAIL", buf);
+#endif /* HAVE_TILDE_NEWMAIL */
+#endif /* MAIL_SPOOL_DIRECTORY */
+
+#ifdef HAVE_ETC_DEFAULT_LOGIN
+ /* Read /etc/default/login; this exists at least on Solaris 2.x. */
+ read_etc_default_login(&env, &envsize, pw);
+#else /* HAVE_ETC_DEFAULT_LOGIN */
+ /* Normal systems set SHELL by default. */
+ child_set_env(&env, &envsize, "SHELL", shell);
+#endif /* HAVE_ETC_DEFAULT_LOGIN */
+
+ /* Set custom environment options from RSA authentication. */
+ while (custom_environment)
+ {
+ struct envstring *ce = custom_environment;
+ char *s = ce->s;
+ int i;
+ for (i = 0; s[i] != '=' && s[i]; i++)
+ ;
+ if (s[i] == '=')
+ {
+ s[i] = 0;
+ child_set_env(&env, &envsize, s, s + i + 1);
+ }
+ custom_environment = ce->next;
+ xfree(ce->s);
+ xfree(ce);
+ }
+
+ /* Set SSH_CLIENT. */
+ sprintf(buf, "%.50s %d %d",
+ get_remote_ipaddr(), get_remote_port(), options.port);
+ child_set_env(&env, &envsize, "SSH_CLIENT", buf);
+
+ /* Set SSH_TTY if we have a pty. */
+ if (ttyname)
+ child_set_env(&env, &envsize, "SSH_TTY", ttyname);
+
+ /* Set TERM if we have a pty. */
+ if (term)
+ child_set_env(&env, &envsize, "TERM", term);
+
+ /* Set DISPLAY if we have one. */
+ if (display)
+ child_set_env(&env, &envsize, "DISPLAY", display);
+
+#ifdef KRB4 /* XXX - how to make these coexist? */
+ if (ticket)
+ child_set_env(&env, &envsize, "KRBTKFILE", ticket);
+#endif /* KRB4 */
+
+ /* Set XAUTHORITY to always be a local file. */
+ if (xauthfile)
+ child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
+
+ /* Set variable for forwarded authentication connection, if we have one. */
+ if (get_permanent_fd(pw->pw_shell) < 0)
+ {
+ if (auth_get_socket_name() != NULL)
+ child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
+ auth_get_socket_name());
+ }
+ else
+ if (auth_get_fd() >= 0)
+ {
+ sprintf(buf, "%d", auth_get_fd());
+ child_set_env(&env, &envsize, SSH_AUTHFD_ENV_NAME, buf);
+ }
+
+ /* Read environment variable settings from /etc/environment. (This exists
+ at least on AIX, but could be useful also elsewhere.) */
+ read_environment_file(&env, &envsize, "/etc/environment");
+
+ /* Read $HOME/.ssh/environment. */
+ sprintf(buf, "%.200s/.ssh/environment", pw->pw_dir);
+ read_environment_file(&env, &envsize, buf);
+
+ /* If debugging, dump the environment to stderr. */
+ if (debug_flag)
+ {
+ fprintf(stderr, "Environment:\n");
+ for (i = 0; env[i]; i++)
+ fprintf(stderr, " %.200s\n", env[i]);
+ }
+
+ /* Close the connection descriptors; note that this is the child, and the
+ server will still have the socket open, and it is important that we
+ do not shutdown it. Note that the descriptors cannot be closed before
+ building the environment, as we call get_remote_ipaddr there. */
+ if (packet_get_connection_in() == packet_get_connection_out())
+ close(packet_get_connection_in());
+ else
+ {
+ close(packet_get_connection_in());
+ close(packet_get_connection_out());
+ }
+ /* Close all descriptors related to channels. They will still remain
+ open in the parent. */
+ channel_close_all();
+
+ /* Close any extra file descriptors. Note that there may still be
+ descriptors left by system functions. They will be closed later. */
+ endpwent();
+ endhostent();
+
+ /* Close any extra open file descriptors so that we don\'t have them
+ hanging around in clients. Note that we want to do this after
+ initgroups, because at least on Solaris 2.3 it leaves file descriptors
+ open. */
+ for (i = 3; i < 64; i++)
+ {
+ if (i == auth_get_fd())
+ continue;
+ close(i);
+ }
+
+ /* Change current directory to the user\'s home directory. */
+ if (chdir(pw->pw_dir) < 0)
+ fprintf(stderr, "Could not chdir to home directory %s: %s\n",
+ pw->pw_dir, strerror(errno));
+
+ /* Must take new environment into use so that .ssh/rc, /etc/sshrc and
+ xauth are run in the proper environment. */
+ environ = env;
+
+ /* Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
+ in this order). */
+ if (stat(SSH_USER_RC, &st) >= 0)
+ {
+ if (debug_flag)
+ fprintf(stderr, "Running /bin/sh %s\n", SSH_USER_RC);
+
+ f = popen("/bin/sh " SSH_USER_RC, "w");
+ if (f)
+ {
+ if (auth_proto != NULL && auth_data != NULL)
+ fprintf(f, "%s %s\n", auth_proto, auth_data);
+ pclose(f);
+ }
+ else
+ fprintf(stderr, "Could not run %s\n", SSH_USER_RC);
+ }
+ else
+ if (stat(SSH_SYSTEM_RC, &st) >= 0)
+ {
+ if (debug_flag)
+ fprintf(stderr, "Running /bin/sh %s\n", SSH_SYSTEM_RC);
+
+ f = popen("/bin/sh " SSH_SYSTEM_RC, "w");
+ if (f)
+ {
+ if (auth_proto != NULL && auth_data != NULL)
+ fprintf(f, "%s %s\n", auth_proto, auth_data);
+ pclose(f);
+ }
+ else
+ fprintf(stderr, "Could not run %s\n", SSH_SYSTEM_RC);
+ }
+#ifdef XAUTH_PATH
+ else
+ {
+ /* Add authority data to .Xauthority if appropriate. */
+ if (auth_proto != NULL && auth_data != NULL)
+ {
+ if (debug_flag)
+ fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n",
+ XAUTH_PATH, display, auth_proto, auth_data);
+
+ f = popen(XAUTH_PATH " -q -", "w");
+ if (f)
+ {
+ fprintf(f, "add %s %s %s\n", display, auth_proto, auth_data);
+ fclose(f);
+ }
+ else
+ fprintf(stderr, "Could not run %s -q -\n", XAUTH_PATH);
+ }
+ }
+#endif /* XAUTH_PATH */
+
+ /* Get the last component of the shell name. */
+ cp = strrchr(shell, '/');
+ if (cp)
+ cp++;
+ else
+ cp = shell;
+
+ /* If we have no command, execute the shell. In this case, the shell name
+ to be passed in argv[0] is preceded by '-' to indicate that this is
+ a login shell. */
+ if (!command)
+ {
+ char buf[256];
+
+ /* Start the shell. Set initial character to '-'. */
+ buf[0] = '-';
+ strncpy(buf + 1, cp, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = 0;
+ /* Execute the shell. */
+ argv[0] = buf;
+ argv[1] = NULL;
+ execve(shell, argv, env);
+ /* Executing the shell failed. */
+ perror(shell);
+ exit(1);
+ }
+
+ /* Execute the command using the user's shell. This uses the -c option
+ to execute the command. */
+ argv[0] = (char *)cp;
+ argv[1] = "-c";
+ argv[2] = (char *)command;
+ argv[3] = NULL;
+ execve(shell, argv, env);
+ perror(shell);
+ exit(1);
+}
diff --git a/usr.bin/ssh/tildexpand.c b/usr.bin/ssh/tildexpand.c
new file mode 100644
index 00000000000..390eab3c064
--- /dev/null
+++ b/usr.bin/ssh/tildexpand.c
@@ -0,0 +1,71 @@
+/*
+
+tildexpand.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Wed Jul 12 01:07:36 1995 ylo
+
+*/
+
+#include "includes.h"
+RCSID("$Id: tildexpand.c,v 1.1 1999/09/26 20:53:38 deraadt Exp $");
+
+#include "xmalloc.h"
+#include "ssh.h"
+
+/* Expands tildes in the file name. Returns data allocated by xmalloc.
+ Warning: this calls getpw*. */
+
+char *tilde_expand_filename(const char *filename, uid_t my_uid)
+{
+ const char *cp;
+ unsigned int userlen;
+ char *expanded;
+ struct passwd *pw;
+ char user[100];
+
+ /* Return immediately if no tilde. */
+ if (filename[0] != '~')
+ return xstrdup(filename);
+
+
+ /* Skiop the tilde. */
+ filename++;
+
+ /* Find where the username ends. */
+ cp = strchr(filename, '/');
+ if (cp)
+ userlen = cp - filename; /* Have something after username. */
+ else
+ userlen = strlen(filename); /* Nothign after username. */
+ if (userlen == 0)
+ pw = getpwuid(my_uid); /* Own home directory. */
+ else
+ {
+ /* Tilde refers to someone elses home directory. */
+ if (userlen > sizeof(user) - 1)
+ fatal("User name after tilde too long.");
+ memcpy(user, filename, userlen);
+ user[userlen] = 0;
+ pw = getpwnam(user);
+ }
+
+ /* Check that we found the user. */
+ if (!pw)
+ fatal("Unknown user %100s.", user);
+
+ /* If referring to someones home directory, return it now. */
+ if (!cp)
+ { /* Only home directory specified */
+ return xstrdup(pw->pw_dir);
+ }
+
+ /* Build a path combining the specified directory and path. */
+ expanded = xmalloc(strlen(pw->pw_dir) + strlen(cp + 1) + 2);
+ sprintf(expanded, "%s/%s", pw->pw_dir, cp + 1);
+ return expanded;
+}
diff --git a/usr.bin/ssh/ttymodes.c b/usr.bin/ssh/ttymodes.c
new file mode 100644
index 00000000000..c03e968937c
--- /dev/null
+++ b/usr.bin/ssh/ttymodes.c
@@ -0,0 +1,499 @@
+/*
+
+ttymodes.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Tue Mar 21 15:59:15 1995 ylo
+
+Encoding and decoding of terminal modes in a portable way.
+Much of the format is defined in ttymodes.h; it is included multiple times
+into this file with the appropriate macro definitions to generate the
+suitable code.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: ttymodes.c,v 1.1 1999/09/26 20:53:38 deraadt Exp $");
+
+#include "packet.h"
+#include "ssh.h"
+
+#define TTY_OP_END 0
+#define TTY_OP_ISPEED 192 /* int follows */
+#define TTY_OP_OSPEED 193 /* int follows */
+
+/* Speed extraction & setting macros for sgtty. */
+
+#ifdef USING_SGTTY
+#define cfgetospeed(tio) ((tio)->sg_ospeed)
+#define cfgetispeed(tio) ((tio)->sg_ispeed)
+#define cfsetospeed(tio, spd) ((tio)->sg_ospeed = (spd), 0)
+#define cfsetispeed(tio, spd) ((tio)->sg_ispeed = (spd), 0)
+#ifndef SPEED_T_IN_STDTYPES_H
+typedef char speed_t;
+#endif
+#endif
+
+/* Converts POSIX speed_t to a baud rate. The values of the constants
+ for speed_t are not themselves portable. */
+
+static int speed_to_baud(speed_t speed)
+{
+ switch (speed)
+ {
+ case B0:
+ return 0;
+ case B50:
+ return 50;
+ case B75:
+ return 75;
+ case B110:
+ return 110;
+ case B134:
+ return 134;
+ case B150:
+ return 150;
+ case B200:
+ return 200;
+ case B300:
+ return 300;
+ case B600:
+ return 600;
+ case B1200:
+ return 1200;
+ case B1800:
+ return 1800;
+ case B2400:
+ return 2400;
+ case B4800:
+ return 4800;
+ case B9600:
+ return 9600;
+
+#ifdef B19200
+ case B19200:
+ return 19200;
+#else /* B19200 */
+#ifdef EXTA
+ case EXTA:
+ return 19200;
+#endif /* EXTA */
+#endif /* B19200 */
+
+#ifdef B38400
+ case B38400:
+ return 38400;
+#else /* B38400 */
+#ifdef EXTB
+ case EXTB:
+ return 38400;
+#endif /* EXTB */
+#endif /* B38400 */
+
+#ifdef B7200
+ case B7200:
+ return 7200;
+#endif /* B7200 */
+#ifdef B14400
+ case B14400:
+ return 14400;
+#endif /* B14400 */
+#ifdef B28800
+ case B28800:
+ return 28800;
+#endif /* B28800 */
+#ifdef B57600
+ case B57600:
+ return 57600;
+#endif /* B57600 */
+#ifdef B76800
+ case B76800:
+ return 76800;
+#endif /* B76800 */
+#ifdef B115200
+ case B115200:
+ return 115200;
+#endif /* B115200 */
+#ifdef B230400
+ case B230400:
+ return 230400;
+#endif /* B230400 */
+ default:
+ return 9600;
+ }
+}
+
+/* Converts a numeric baud rate to a POSIX speed_t. */
+
+static speed_t baud_to_speed(int baud)
+{
+ switch (baud)
+ {
+ case 0:
+ return B0;
+ case 50:
+ return B50;
+ case 75:
+ return B75;
+ case 110:
+ return B110;
+ case 134:
+ return B134;
+ case 150:
+ return B150;
+ case 200:
+ return B200;
+ case 300:
+ return B300;
+ case 600:
+ return B600;
+ case 1200:
+ return B1200;
+ case 1800:
+ return B1800;
+ case 2400:
+ return B2400;
+ case 4800:
+ return B4800;
+ case 9600:
+ return B9600;
+
+#ifdef B19200
+ case 19200:
+ return B19200;
+#else /* B19200 */
+#ifdef EXTA
+ case 19200:
+ return EXTA;
+#endif /* EXTA */
+#endif /* B19200 */
+
+#ifdef B38400
+ case 38400:
+ return B38400;
+#else /* B38400 */
+#ifdef EXTB
+ case 38400:
+ return EXTB;
+#endif /* EXTB */
+#endif /* B38400 */
+
+#ifdef B7200
+ case 7200:
+ return B7200;
+#endif /* B7200 */
+#ifdef B14400
+ case 14400:
+ return B14400;
+#endif /* B14400 */
+#ifdef B28800
+ case 28800:
+ return B28800;
+#endif /* B28800 */
+#ifdef B57600
+ case 57600:
+ return B57600;
+#endif /* B57600 */
+#ifdef B76800
+ case 76800:
+ return B76800;
+#endif /* B76800 */
+#ifdef B115200
+ case 115200:
+ return B115200;
+#endif /* B115200 */
+#ifdef B230400
+ case 230400:
+ return B230400;
+#endif /* B230400 */
+ default:
+ return B9600;
+ }
+}
+
+/* Encodes terminal modes for the terminal referenced by fd in a portable
+ manner, and appends the modes to a packet being constructed. */
+
+void tty_make_modes(int fd)
+{
+#ifdef USING_TERMIOS
+ struct termios tio;
+#endif
+#ifdef USING_SGTTY
+ struct sgttyb tio;
+ struct tchars tiotc;
+ struct ltchars tioltc;
+ int tiolm;
+#ifdef TIOCGSTAT
+ struct tstatus tiots;
+#endif /* TIOCGSTAT */
+#endif /* USING_SGTTY */
+ int baud;
+
+ /* Get the modes. */
+#ifdef USING_TERMIOS
+ if (tcgetattr(fd, &tio) < 0)
+ {
+ packet_put_char(TTY_OP_END);
+ log("tcgetattr: %.100s", strerror(errno));
+ return;
+ }
+#endif /* USING_TERMIOS */
+#ifdef USING_SGTTY
+ if (ioctl(fd, TIOCGETP, &tio) < 0)
+ {
+ packet_put_char(TTY_OP_END);
+ log("ioctl(fd, TIOCGETP, ...): %.100s", strerror(errno));
+ return;
+ }
+ if (ioctl(fd, TIOCGETC, &tiotc) < 0)
+ {
+ packet_put_char(TTY_OP_END);
+ log("ioctl(fd, TIOCGETC, ...): %.100s", strerror(errno));
+ return;
+ }
+ if (ioctl(fd, TIOCLGET, &tiolm) < 0)
+ {
+ packet_put_char(TTY_OP_END);
+ log("ioctl(fd, TIOCLGET, ...): %.100s", strerror(errno));
+ return;
+ }
+ if (ioctl(fd, TIOCGLTC, &tioltc) < 0)
+ {
+ packet_put_char(TTY_OP_END);
+ log("ioctl(fd, TIOCGLTC, ...): %.100s", strerror(errno));
+ return;
+ }
+#ifdef TIOCGSTAT
+ if (ioctl(fd, TIOCGSTAT, &tiots) < 0)
+ {
+ packet_put_char(TTY_OP_END);
+ log("ioctl(fd, TIOCGSTAT, ...): %.100s", strerror(errno));
+ return;
+ }
+#endif /* TIOCGSTAT */
+#endif /* USING_SGTTY */
+
+ /* Store input and output baud rates. */
+ baud = speed_to_baud(cfgetospeed(&tio));
+ packet_put_char(TTY_OP_OSPEED);
+ packet_put_int(baud);
+ baud = speed_to_baud(cfgetispeed(&tio));
+ packet_put_char(TTY_OP_ISPEED);
+ packet_put_int(baud);
+
+ /* Store values of mode flags. */
+#ifdef USING_TERMIOS
+#define TTYCHAR(NAME, OP) \
+ packet_put_char(OP); packet_put_char(tio.c_cc[NAME]);
+#define TTYMODE(NAME, FIELD, OP) \
+ packet_put_char(OP); packet_put_char((tio.FIELD & NAME) != 0);
+#define SGTTYCHAR(NAME, OP)
+#define SGTTYMODE(NAME, FIELD, OP)
+#define SGTTYMODEN(NAME, FIELD, OP)
+#endif /* USING_TERMIOS */
+
+#ifdef USING_SGTTY
+#define TTYCHAR(NAME, OP)
+#define TTYMODE(NAME, FIELD, OP)
+#define SGTTYCHAR(NAME, OP) \
+ packet_put_char(OP); packet_put_char(NAME);
+#define SGTTYMODE(NAME, FIELD, OP) \
+ packet_put_char(OP); packet_put_char((FIELD & NAME) != 0);
+#define SGTTYMODEN(NAME, FIELD, OP) \
+ packet_put_char(OP); packet_put_char((FIELD & NAME) == 0);
+#endif /* USING_SGTTY */
+
+#include "ttymodes.h"
+
+#undef TTYCHAR
+#undef TTYMODE
+#undef SGTTYCHAR
+#undef SGTTYMODE
+#undef SGTTYMODEN
+
+ /* Mark end of mode data. */
+ packet_put_char(TTY_OP_END);
+}
+
+/* Decodes terminal modes for the terminal referenced by fd in a portable
+ manner from a packet being read. */
+
+void tty_parse_modes(int fd, int *n_bytes_ptr)
+{
+#ifdef USING_TERMIOS
+ struct termios tio;
+#endif /* USING_TERMIOS */
+#ifdef USING_SGTTY
+ struct sgttyb tio;
+ struct tchars tiotc;
+ struct ltchars tioltc;
+ int tiolm;
+#ifdef TIOCGSTAT
+ struct tstatus tiots;
+#endif /* TIOCGSTAT */
+#endif
+ int opcode, baud;
+ int n_bytes = 0;
+ int failure = 0;
+
+ /* Get old attributes for the terminal. We will modify these flags.
+ I am hoping that if there are any machine-specific modes, they will
+ initially have reasonable values. */
+#ifdef USING_TERMIOS
+ if (tcgetattr(fd, &tio) < 0)
+ failure = -1;
+#endif /* USING_TERMIOS */
+#ifdef USING_SGTTY
+ if (ioctl(fd, TIOCGETP, &tio) < 0)
+ failure = -1;
+ if (ioctl(fd, TIOCGETC, &tiotc) < 0)
+ failure = -1;
+ if (ioctl(fd, TIOCLGET, &tiolm) < 0)
+ failure = -1;
+ if (ioctl(fd, TIOCGLTC, &tioltc) < 0)
+ failure = -1;
+#ifdef TIOCGSTAT
+ if (ioctl(fd, TIOCGSTAT, &tiots) < 0)
+ failure = -1;
+#endif /* TIOCGSTAT */
+#endif /* USING_SGTTY */
+
+ for (;;)
+ {
+ n_bytes += 1;
+ opcode = packet_get_char();
+ switch (opcode)
+ {
+ case TTY_OP_END:
+ goto set;
+
+ case TTY_OP_ISPEED:
+ n_bytes += 4;
+ baud = packet_get_int();
+ if (failure != -1 && cfsetispeed(&tio, baud_to_speed(baud)) < 0)
+ error("cfsetispeed failed for %d", baud);
+ break;
+
+ case TTY_OP_OSPEED:
+ n_bytes += 4;
+ baud = packet_get_int();
+ if (failure != -1 && cfsetospeed(&tio, baud_to_speed(baud)) < 0)
+ error("cfsetospeed failed for %d", baud);
+ break;
+
+#ifdef USING_TERMIOS
+#define TTYCHAR(NAME, OP) \
+ case OP: \
+ n_bytes += 1; \
+ tio.c_cc[NAME] = packet_get_char(); \
+ break;
+#define TTYMODE(NAME, FIELD, OP) \
+ case OP: \
+ n_bytes += 1; \
+ if (packet_get_char()) \
+ tio.FIELD |= NAME; \
+ else \
+ tio.FIELD &= ~NAME; \
+ break;
+#define SGTTYCHAR(NAME, OP)
+#define SGTTYMODE(NAME, FIELD, OP)
+#define SGTTYMODEN(NAME, FIELD, OP)
+#endif /* USING_TERMIOS */
+
+#ifdef USING_SGTTY
+#define TTYCHAR(NAME, OP)
+#define TTYMODE(NAME, FIELD, OP)
+#define SGTTYCHAR(NAME, OP) \
+ case OP: \
+ n_bytes += 1; \
+ NAME = packet_get_char(); \
+ break;
+#define SGTTYMODE(NAME, FIELD, OP) \
+ case OP: \
+ n_bytes += 1; \
+ if (packet_get_char()) \
+ FIELD |= NAME; \
+ else \
+ FIELD &= ~NAME; \
+ break;
+#define SGTTYMODEN(NAME, FIELD, OP) \
+ case OP: \
+ n_bytes += 1; \
+ if (packet_get_char()) \
+ FIELD &= ~NAME; \
+ else \
+ FIELD |= NAME; \
+ break;
+#endif /* USING_SGTTY */
+
+#include "ttymodes.h"
+
+#undef TTYCHAR
+#undef TTYMODE
+#undef SGTTYCHAR
+#undef SGTTYMODE
+#undef SGTTYMODEN
+
+ default:
+ debug("Ignoring unsupported tty mode opcode %d (0x%x)",
+ opcode, opcode);
+ /* Opcodes 0 to 127 are defined to have a one-byte argument. */
+ if (opcode >= 0 && opcode < 128)
+ {
+ n_bytes += 1;
+ (void)packet_get_char();
+ break;
+ }
+ else
+ {
+ /* Opcodes 128 to 159 are defined to have an integer argument. */
+ if (opcode >= 128 && opcode < 160)
+ {
+ n_bytes += 4;
+ (void)packet_get_int();
+ break;
+ }
+ }
+ /* It is a truly undefined opcode (160 to 255). We have no idea
+ about its arguments. So we must stop parsing. Note that some
+ data may be left in the packet; hopefully there is nothing more
+ coming after the mode data. */
+ log("parse_tty_modes: unknown opcode %d", opcode);
+ packet_integrity_check(0, 1, SSH_CMSG_REQUEST_PTY);
+ goto set;
+ }
+ }
+
+ set:
+ if (*n_bytes_ptr != n_bytes)
+ {
+ *n_bytes_ptr = n_bytes;
+ return; /* Don't process bytes passed */
+ }
+
+ if (failure == -1)
+ return; /* Packet parsed ok but tty stuff failed */
+
+ /* Set the new modes for the terminal. */
+#ifdef USING_TERMIOS
+ if (tcsetattr(fd, TCSANOW, &tio) < 0)
+ log("Setting tty modes failed: %.100s", strerror(errno));
+#endif /* USING_TERMIOS */
+#ifdef USING_SGTTY
+ if (ioctl(fd, TIOCSETP, &tio) < 0
+ || ioctl(fd, TIOCSETC, &tiotc) < 0
+ || ioctl(fd, TIOCLSET, &tiolm) < 0
+ || ioctl(fd, TIOCSLTC, &tioltc) < 0
+#ifdef TIOCSSTAT
+ || ioctl(fd, TIOCSSTAT, &tiots) < 0
+#endif /* TIOCSSTAT */
+ )
+ log("Setting tty modes failed: %.100s", strerror(errno));
+#endif /* USING_SGTTY */
+ return;
+}
diff --git a/usr.bin/ssh/ttymodes.h b/usr.bin/ssh/ttymodes.h
new file mode 100644
index 00000000000..a9a064903c5
--- /dev/null
+++ b/usr.bin/ssh/ttymodes.h
@@ -0,0 +1,138 @@
+/*
+
+ttymodes.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+ SGTTY stuff contributed by Janne Snabb <snabb@niksula.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Tue Mar 21 15:42:09 1995 ylo
+
+*/
+
+/* RCSID("$Id: ttymodes.h,v 1.1 1999/09/26 20:53:38 deraadt Exp $"); */
+
+/* The tty mode description is a stream of bytes. The stream consists of
+ opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0).
+ Opcodes 1-127 have one-byte arguments. Opcodes 128-159 have integer
+ arguments. Opcodes 160-255 are not yet defined, and cause parsing to
+ stop (they should only be used after any other data).
+
+ The client puts in the stream any modes it knows about, and the
+ server ignores any modes it does not know about. This allows some degree
+ of machine-independence, at least between systems that use a posix-like
+ tty interface. The protocol can support other systems as well, but might
+ require reimplementing as mode names would likely be different. */
+
+/* Some constants and prototypes are defined in packet.h; this file
+ is only intended for including from ttymodes.h. */
+
+/* termios macro */ /* sgtty macro */
+/* name, op */
+TTYCHAR(VINTR, 1) SGTTYCHAR(tiotc.t_intrc, 1)
+TTYCHAR(VQUIT, 2) SGTTYCHAR(tiotc.t_quitc, 2)
+TTYCHAR(VERASE, 3) SGTTYCHAR(tio.sg_erase, 3)
+#if defined(VKILL) || defined(USING_SGTTY)
+TTYCHAR(VKILL, 4) SGTTYCHAR(tio.sg_kill, 4)
+#endif /* VKILL */
+TTYCHAR(VEOF, 5) SGTTYCHAR(tiotc.t_eofc, 5)
+#if defined(VEOL) || defined(USING_SGTTY)
+TTYCHAR(VEOL, 6) SGTTYCHAR(tiotc.t_brkc, 6)
+#endif /* VEOL */
+#ifdef VEOL2 /* n/a */
+TTYCHAR(VEOL2, 7)
+#endif /* VEOL2 */
+TTYCHAR(VSTART, 8) SGTTYCHAR(tiotc.t_startc, 8)
+TTYCHAR(VSTOP, 9) SGTTYCHAR(tiotc.t_stopc, 9)
+#if defined(VSUSP) || defined(USING_SGTTY)
+TTYCHAR(VSUSP, 10) SGTTYCHAR(tioltc.t_suspc, 10)
+#endif /* VSUSP */
+#if defined(VDSUSP) || defined(USING_SGTTY)
+TTYCHAR(VDSUSP, 11) SGTTYCHAR(tioltc.t_dsuspc, 11)
+#endif /* VDSUSP */
+#if defined(VREPRINT) || defined(USING_SGTTY)
+TTYCHAR(VREPRINT, 12) SGTTYCHAR(tioltc.t_rprntc, 12)
+#endif /* VREPRINT */
+#if defined(VWERASE) || defined(USING_SGTTY)
+TTYCHAR(VWERASE, 13) SGTTYCHAR(tioltc.t_werasc, 13)
+#endif /* VWERASE */
+#if defined(VLNEXT) || defined(USING_SGTTY)
+TTYCHAR(VLNEXT, 14) SGTTYCHAR(tioltc.t_lnextc, 14)
+#endif /* VLNEXT */
+#if defined(VFLUSH) || defined(USING_SGTTY)
+TTYCHAR(VFLUSH, 15) SGTTYCHAR(tioltc.t_flushc, 15)
+#endif /* VFLUSH */
+#ifdef VSWTCH
+TTYCHAR(VSWTCH, 16) /* n/a */
+#endif /* VSWTCH */
+#if defined(VSTATUS) || (defined(USING_SGTTY) && defined(TIOCGSTAT))
+TTYCHAR(VSTATUS, 17) SGTTYCHAR(tiots.tc_statusc, 17)
+#endif /* VSTATUS */
+#ifdef VDISCARD
+TTYCHAR(VDISCARD, 18) /* n/a */
+#endif /* VDISCARD */
+
+/* name, field, op */
+TTYMODE(IGNPAR, c_iflag, 30) /* n/a */
+TTYMODE(PARMRK, c_iflag, 31) /* n/a */
+TTYMODE(INPCK, c_iflag, 32) SGTTYMODEN(ANYP, tio.sg_flags, 32)
+TTYMODE(ISTRIP, c_iflag, 33) SGTTYMODEN(LPASS8, tiolm, 33)
+TTYMODE(INLCR, c_iflag, 34) /* n/a */
+TTYMODE(IGNCR, c_iflag, 35) /* n/a */
+TTYMODE(ICRNL, c_iflag, 36) SGTTYMODE(CRMOD, tio.sg_flags, 36)
+#if defined(IUCLC) || defined(USING_SGTTY)
+TTYMODE(IUCLC, c_iflag, 37) SGTTYMODE(LCASE, tio.sg_flags, 37)
+#endif
+TTYMODE(IXON, c_iflag, 38) /* n/a */
+TTYMODE(IXANY, c_iflag, 39) SGTTYMODEN(LDECCTQ, tiolm, 39)
+TTYMODE(IXOFF, c_iflag, 40) SGTTYMODE(TANDEM, tio.sg_flags, 40)
+#ifdef IMAXBEL
+TTYMODE(IMAXBEL,c_iflag, 41) /* n/a */
+#endif /* IMAXBEL */
+
+TTYMODE(ISIG, c_lflag, 50) /* n/a */
+TTYMODE(ICANON, c_lflag, 51) SGTTYMODEN(CBREAK, tio.sg_flags, 51)
+#ifdef XCASE
+TTYMODE(XCASE, c_lflag, 52) /* n/a */
+#endif
+TTYMODE(ECHO, c_lflag, 53) SGTTYMODE(ECHO, tio.sg_flags, 53)
+TTYMODE(ECHOE, c_lflag, 54) SGTTYMODE(LCRTERA, tiolm, 54)
+TTYMODE(ECHOK, c_lflag, 55) SGTTYMODE(LCRTKIL, tiolm, 55)
+TTYMODE(ECHONL, c_lflag, 56) /* n/a */
+TTYMODE(NOFLSH, c_lflag, 57) SGTTYMODE(LNOFLSH, tiolm, 57)
+TTYMODE(TOSTOP, c_lflag, 58) SGTTYMODE(LTOSTOP, tiolm, 58)
+#ifdef IEXTEN
+TTYMODE(IEXTEN, c_lflag, 59) /* n/a */
+#endif /* IEXTEN */
+#if defined(ECHOCTL) || defined(USING_SGTTY)
+TTYMODE(ECHOCTL,c_lflag, 60) SGTTYMODE(LCTLECH, tiolm, 60)
+#endif /* ECHOCTL */
+#ifdef ECHOKE
+TTYMODE(ECHOKE, c_lflag, 61) /* n/a */
+#endif /* ECHOKE */
+#if defined(PENDIN) || defined(USING_SGTTY)
+TTYMODE(PENDIN, c_lflag, 62) SGTTYMODE(LPENDIN, tiolm, 62)
+#endif /* PENDIN */
+
+TTYMODE(OPOST, c_oflag, 70) /* n/a */
+#if defined(OLCUC) || defined(USING_SGTTY)
+TTYMODE(OLCUC, c_oflag, 71) SGTTYMODE(LCASE, tio.sg_flags, 71)
+#endif
+TTYMODE(ONLCR, c_oflag, 72) SGTTYMODE(CRMOD, tio.sg_flags, 72)
+#ifdef OCRNL
+TTYMODE(OCRNL, c_oflag, 73) /* n/a */
+#endif
+#ifdef ONOCR
+TTYMODE(ONOCR, c_oflag, 74) /* n/a */
+#endif
+#ifdef ONLRET
+TTYMODE(ONLRET, c_oflag, 75) /* n/a */
+#endif
+
+TTYMODE(CS7, c_cflag, 90) /* n/a */
+TTYMODE(CS8, c_cflag, 91) SGTTYMODE(LPASS8, tiolm, 91)
+TTYMODE(PARENB, c_cflag, 92) /* n/a */
+TTYMODE(PARODD, c_cflag, 93) SGTTYMODE(ODDP, tio.sg_flags, 93)
+
diff --git a/usr.bin/ssh/uidswap.c b/usr.bin/ssh/uidswap.c
new file mode 100644
index 00000000000..314be452980
--- /dev/null
+++ b/usr.bin/ssh/uidswap.c
@@ -0,0 +1,126 @@
+/*
+
+uidswap.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Sep 9 01:56:14 1995 ylo
+
+Code for uid-swapping.
+
+*/
+
+#include "includes.h"
+RCSID("$Id: uidswap.c,v 1.1 1999/09/26 20:53:38 deraadt Exp $");
+
+#include "ssh.h"
+#include "uidswap.h"
+
+/* Note: all these functions must work in all of the following cases:
+
+ 1. euid=0, ruid=0
+ 2. euid=0, ruid!=0
+ 3. euid!=0, ruid!=0
+
+ Additionally, they must work regardless of whether the system has
+ POSIX saved uids or not. */
+
+#ifdef HAVE_SETEUID
+
+#ifdef _POSIX_SAVED_IDS
+/* Lets assume that posix saved ids also work with seteuid, even though that
+ is not part of the posix specification. */
+#define SAVED_IDS_WORK_WITH_SETEUID
+#endif /* _POSIX_SAVED_IDS */
+
+/* Saved effective uid. */
+static uid_t saved_euid = 0;
+
+/* Temporarily changes to the given uid. If the effective user id is not
+ root, this does nothing. This call cannot be nested. */
+
+void temporarily_use_uid(uid_t uid)
+{
+#ifdef SAVED_IDS_WORK_WITH_SETEUID
+
+ /* Save the current euid. */
+ saved_euid = geteuid();
+
+ /* Set the effective uid to the given (unprivileged) uid. */
+ if (seteuid(uid) == -1)
+ debug("seteuid %d: %.100s", (int)uid, strerror(errno));
+
+#else /* SAVED_IDS_WORK_WITH_SETUID */
+
+ /* Propagate the privileged uid to all of our uids. */
+ if (setuid(geteuid()) < 0)
+ debug("setuid %d: %.100s", (int)geteuid(), strerror(errno));
+
+ /* Set the effective uid to the given (unprivileged) uid. */
+ if (seteuid(uid) == -1)
+ debug("seteuid %d: %.100s", (int)uid, strerror(errno));
+
+#endif /* SAVED_IDS_WORK_WITH_SETEUID */
+
+}
+
+/* Restores to the original uid. */
+
+void restore_uid()
+{
+#ifdef SAVED_IDS_WORK_WITH_SETEUID
+
+ /* Set the effective uid back to the saved uid. */
+ if (seteuid(saved_euid) < 0)
+ debug("seteuid %d: %.100s", (int)saved_euid, strerror(errno));
+
+#else /* SAVED_IDS_WORK_WITH_SETEUID */
+
+ /* We are unable to restore the real uid to its unprivileged value. */
+ /* Propagate the real uid (usually more privileged) to effective uid
+ as well. */
+ setuid(getuid());
+
+#endif /* SAVED_IDS_WORK_WITH_SETEUID */
+}
+
+/* Permanently sets all uids to the given uid. This cannot be called while
+ temporarily_use_uid is effective. */
+
+void permanently_set_uid(uid_t uid)
+{
+ if (setuid(uid) < 0)
+ debug("setuid %d: %.100s", (int)uid, strerror(errno));
+}
+
+#else /* HAVE_SETEUID */
+
+YOUR_SYSTEM_DOES_NOT_PERMIT_UID_SWAPPING_READ_AND_EDIT_UIDSWAP_C;
+/* If we ever come here, if means that your system does not support any of
+ the uid swapping methods we are aware of. Tough. This means that
+ ssh will have to read certain files as root, which causes some security
+ problems. Unless your are very concerned about security, you can
+ comment out the above line. The effect is that local users on your
+ machine might be able to read each other's files. Also, you may encounter
+ problems if home directories are on a NFS volume. You may also
+ encounter other problems; please don't complain unless you have some idea
+ how to fix it. */
+
+void temporarily_use_uid(uid_t uid)
+{
+}
+
+void restore_uid()
+{
+}
+
+void permanently_set_uid(uid_t uid)
+{
+ if (setuid(uid) < 0)
+ debug("setuid %d: %.100s", (int)uid, strerror(errno));
+}
+
+#endif /* HAVE_SETEUID */
diff --git a/usr.bin/ssh/uidswap.h b/usr.bin/ssh/uidswap.h
new file mode 100644
index 00000000000..af4f924f0ce
--- /dev/null
+++ b/usr.bin/ssh/uidswap.h
@@ -0,0 +1,30 @@
+/*
+
+uidswap.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Sat Sep 9 01:43:15 1995 ylo
+Last modified: Sat Sep 9 02:34:04 1995 ylo
+
+*/
+
+#ifndef UIDSWAP_H
+#define UIDSWAP_H
+
+/* Temporarily changes to the given uid. If the effective user id is not
+ root, this does nothing. This call cannot be nested. */
+void temporarily_use_uid(uid_t uid);
+
+/* Restores the original effective user id after temporarily_use_uid().
+ This should only be called while temporarily_use_uid is effective. */
+void restore_uid();
+
+/* Permanently sets all uids to the given uid. This cannot be called while
+ temporarily_use_uid is effective. This must also clear any saved uids. */
+void permanently_set_uid(uid_t uid);
+
+#endif /* UIDSWAP_H */
diff --git a/usr.bin/ssh/version.h b/usr.bin/ssh/version.h
new file mode 100644
index 00000000000..ca606fd62a3
--- /dev/null
+++ b/usr.bin/ssh/version.h
@@ -0,0 +1 @@
+#define SSH_VERSION "ossh-1.2.16"
diff --git a/usr.bin/ssh/xmalloc.c b/usr.bin/ssh/xmalloc.c
new file mode 100644
index 00000000000..b50959a9d27
--- /dev/null
+++ b/usr.bin/ssh/xmalloc.c
@@ -0,0 +1,60 @@
+/*
+
+xmalloc.c
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Mar 20 21:23:10 1995 ylo
+
+Versions of malloc and friends that check their results, and never return
+failure (they call fatal if they encounter an error).
+
+*/
+
+#include "includes.h"
+RCSID("$Id: xmalloc.c,v 1.1 1999/09/26 20:53:38 deraadt Exp $");
+
+#include "ssh.h"
+
+#if 0
+void *malloc(size_t size);
+void *realloc(void *ptr, size_t size);
+void free(void *ptr);
+#endif
+
+void *xmalloc(size_t size)
+{
+ void *ptr = malloc(size);
+ if (ptr == NULL)
+ fatal("xmalloc: out of memory (allocating %d bytes)", (int)size);
+ return ptr;
+}
+
+void *xrealloc(void *ptr, size_t new_size)
+{
+ void *new_ptr;
+
+ if (ptr == NULL)
+ fatal("xrealloc: NULL pointer given as argument");
+ new_ptr = realloc(ptr, new_size);
+ if (new_ptr == NULL)
+ fatal("xrealloc: out of memory (new_size %d bytes)", (int)new_size);
+ return new_ptr;
+}
+
+void xfree(void *ptr)
+{
+ if (ptr == NULL)
+ fatal("xfree: NULL pointer given as argument");
+ free(ptr);
+}
+
+char *xstrdup(const char *str)
+{
+ char *cp = xmalloc(strlen(str) + 1);
+ strcpy(cp, str);
+ return cp;
+}
diff --git a/usr.bin/ssh/xmalloc.h b/usr.bin/ssh/xmalloc.h
new file mode 100644
index 00000000000..ffdde62ed1d
--- /dev/null
+++ b/usr.bin/ssh/xmalloc.h
@@ -0,0 +1,34 @@
+/*
+
+xmalloc.h
+
+Author: Tatu Ylonen <ylo@cs.hut.fi>
+
+Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ All rights reserved
+
+Created: Mon Mar 20 22:09:17 1995 ylo
+
+Versions of malloc and friends that check their results, and never return
+failure (they call fatal if they encounter an error).
+
+*/
+
+/* RCSID("$Id: xmalloc.h,v 1.1 1999/09/26 20:53:38 deraadt Exp $"); */
+
+#ifndef XMALLOC_H
+#define XMALLOC_H
+
+/* Like malloc, but calls fatal() if out of memory. */
+void *xmalloc(size_t size);
+
+/* Like realloc, but calls fatal() if out of memory. */
+void *xrealloc(void *ptr, size_t new_size);
+
+/* Frees memory allocated using xmalloc or xrealloc. */
+void xfree(void *ptr);
+
+/* Allocates memory using xmalloc, and copies the string into that memory. */
+char *xstrdup(const char *str);
+
+#endif /* XMALLOC_H */